Spring schema folder & Spring XML namespaces - spring

I am looking for how we should determine the symbol of a namespace in Spring bean XML definitions. I guess they are in the Spring schema folder, but I can't find it. For example, what are c:, p:, util:, .. in the XML bean configuration?
Where can I find the schema's for each namespace? For example, how do I know if I should use http://www.springframework.org/schema/p in xmlns:p="http://www.springframework.org/schema/p", where are the other namespaces and how can I find them?

You can choose the symbol (p, util, jee, beans, ...) by yourself. These are namespaces, and they work by adding the xmlns attribute like:
<beans xmlns:util="http://www.springframework.org/schema/util">
<!-- Content -->
</beans>
In this case we said that util: will be used by the util schema, so you'll have to use <util:properties> to access things from this namespace. But you could also have said xmlns:foobar="http://www.springframework.org/schema/util" in which case you could have used things like <foobar:properties>.
But you also need to provide the location of the XSD of that namespace by using xsi:schemaLocation:
<beans xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- Content -->
</beans>
In this case the XSD for http://www.springframework.org/schema/util is available at http://www.springframework.org/schema/util/spring-util.xsd. The http://www.springframework.org/schema/util part is just a label and can be chosen as well. The only thing that has to match is the XSD schema.
For more information about XML namespaces, you should look at this question and its answers.
A list of common XML schema's with Spring can be found in their documentation (33. XML Schema-based configuration). However, these only list the core schemas. Some projects (like Spring Web Services, ...) have their own namespaces like:
http://www.springframework.org/schema/web-services/web-services.xsd
http://www.springframework.org/schema/oxm/spring-oxm.xsd
...
You can find the entire list by visiting the Index of /schema. However, like I mentioned, most of these are only used for specific Spring projects, don't just import them, read the specific documentation to find out what you need. The documentation about the constructor namespace (c:) can be found in 7. The IoC container.

Related

Can SpEL be used with import statements in spring xml configuration

I am trying to use SpEL in import statement in spring xml configuration.
I am trying to do this
<import resource="classpath*:/'#{'${enable.mass.quote.service:false}'=='true' ? 'massquoting' : 'quoting'}'-beans.xml"/>
but it is not working, any suggestions please
Actually you are right: <import resource> doesn't support SpEL, but it supports property-placeholders:
// Resolve system properties: e.g. "${user.dir}"
location = environment.resolveRequiredPlaceholders(location);
So, for your case it might look like:
<import resource="classpath*:/${enable.mass.quote.service:quoting}-beans.xml"/>
where enable.mass.quote.service should have value massquoting.
If you have more high condition, e.g. enable.mass.quote.service=true, you should rely on Spring Profiles:
<beans profile="service">
<import resource="classpath*:/massquoting-beans.xml"/>
</beans>
<beans profile="nonService">
<import resource="classpath*:/quoting-beans.xml"/>
</beans>
I too came across this requirement and turns out the answer is NO. SpEL or placeholders cannot be used in Spring import statements because the import happens before the placeholders/expressions are evaluated and substituted. Refer here. Spring profiles is the answer just that Spring profiles were floated beginning Spring 3.1.x so when using an older version of Spring one might have to take on the onerous task of writing custom namespaces and their handlers.

How does the Spring framework process XML namespace based syntax for configuring spring components?

While reading about spring-rabbit, I stumble upon the following syntax of configuring spring components:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<rabbit:connection-factory id="connectionFactory"/>
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory"/>
<rabbit:admin connection-factory="connectionFactory"/>
<rabbit:queue name="myqueue"/>
</beans>
I am only aware of bean way of configuring components, where you declare a bean with id and class and set appropriate properties. I am not clear about the above way, by making use of XML namespace, of configuring components and how it is internally handled by Spring.
Thanks.
The use of namespaces is really nothing more than shortcut configurations. Behind the scenes, Spring is doing all of your bean creating like you mentioned you are accustomed to doing yourself. As for HOW, well, there are a few components. First you need a registered NamespaceHandler. Going with your spring-rabbit example, you'll find in the spring-rabbit jar a file at a META-INF/spring/spring.handlers with something like this:
http\://www.springframework.org/schema/rabbit=org.springframework.amqp.rabbit.config.RabbitNamespaceHandler
This is registering RabbitNamespaceHandler for the rabbit namespace configurations. Alongside that file you will see one called spring.schemas, and its purpose is to register the schemas that constrain the rabbit namespace.
The next step is to have one or more BeanDefinitionParser instances that do the "magic" of turning your shortcut configurations into full-blown bean creation definitions, so to speak. In this rabbit example, you will find ConnectionFactoryParser which is responsible for parsing the <rabbit:connection-factory /> element. It simply looks at all of the attributes, sub-elements, etc. that your declare in xml and creates the necessary beans for you.
You can follow this formula to create your own namespace configuration as well.
Spring's XML namespace support provides a way to register several components at once, in a more succinct and meta-data driven (or indeed domain-specific) approach. Anything you can do with a namespace handler, could also be done with (probably quite a lot more) bean definitions.
Creating a namespace handler is a fairly simple process - and Spring, by its extensible nature easily allows you to create your own, if you wish.
Here's a some detailed documentation on how to do that:
http://docs.spring.io/spring/docs/3.0.0.M3/reference/html/apbs03.html
http://cscarioni.blogspot.com/2012/04/creating-custom-spring-3-xml-namespace.html

How to retrieve context parameters in Spring 3.1 xml context

It seems like there's been a few iterations of property support in spring it's hard to tell what's best practice and the manuals are written from the point of view of someone who is familiar with every other iteration. I feel like this should be a simple and common requirement but given how hard it's been please correct me if there's a more idiomatic way.
What I want is to pass an additional properties file to my spring web app based on a context property which the client is setting using a tomcat descriptor like so
<Context path="/foo" reloadable="true">
<Parameter name="foo.config" value="file:${catalina.base}/conf/foo.properties"/>
</Context>
In spring for the live profile I have this
<beans profile="live">
<context:property-placeholder location="classpath:timetabling.live.properties,${timetabling.config}"
ignore-resource-not-found="true" />
</beans>
So I'd assumed this doesn;t work because I'm trying to configure placeholder suppport with a placeholder. If I use a system property however then this works fine. I know that spring 3.1 has baked in support for system and environment properties so I guess my question is how can I augment this support with something context aware before the placeholder is resolved?
--Update--
looking at http://blog.springsource.org/2011/02/15/spring-3-1-m1-unified-property-management/ particularly at footnote 1, I would expect to have a DefaultWebEnvironment which should already have aceess to context init params. Now I am more confused, can someone provide me with a concrete example of context property retrieval? At this point I feel like I've read every javadoc available and they are just not helpful.
<context:property-placeholder /> sets up a PropertyPlaceholderConfigurer which reads from .properties, system properties and environment variables. A Tomcat context.xml however sets up a servlet context init parameter. So what you need is a ServletContextPropertyPlaceholderConfigurer.

Switching spring application context or Impl java classes using maven profiles

I know the question I'm asking must be answered somewhere but I cant find an example on the net with some guidelines.
I wish to swap out the Spring 3.0 bean definition at build and runtime for a common codebase. I'm also using Maven profiles to build different versions of the same code.
Currently my bean def is
<bean id="somebean" class="com.x.SomeImpl" >
I will need to replace and deploy it at some times as
<bean id="somebean" class="com.x.SomeOtherImpl" >
Now the approaches I'm thinking of are
1) Use Maven profiles to switch out the complete applicationContext.xml to some other applicationContextB.xml based on the Maven profile.
2) Use Maven profiles to somehow? replace only the bean id definition for "somebean"
My questions are:
a) How can Option 2 be achieved?
b) These approaches still compile and package both SomeImpl and SomeOtherImpl during build. How can I pick only one and not the other for compliation and packaging into EAR?
I know Spring 3.1 has env profiles for the beans, but presently that's not an option.
You could consider using the maven resources and filtering feature available. You could have placeholders in your context file and a property file per profile holding values. In each profile, you could use a different property file and appropriately have your context file filtered.
Take a look to Maven Build Helper Plugin add-source.
You can combine profiles and Build Helper Plugin (add-source goal) to add the required classes in both cases.
you can import multiple config files to your config like this:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<import resource="applicationContextA.xml"/>
<import resource="applicationContextB"/>
</beans>
For switching you can use Spring profiles.

OC4J 10.1.3.5 / Spring3 Issue

I'm using OC4J 10.1.3.5.0, and have an issue with the XML namespaces in the Spring XML files supplied in the WAR/EAR.
According to the Oracle documentation, there is a known issue in parsing the Spring 3 XSD files within OC4J, as this embeds the Oracle XMLParserV2 jar and uses this for all XML parsing (which has issues with some XSD tricks used in Spring 3 apparently).
I've folowed the Oracle work-around, defining my own XML parser shared libraries on the OC4J instance, and (in the orion-application.xml), defining the shared library to use. I created a shared library,'apache.xml', with xercesImpl (v 2.9.1), xml-apis (v 1.3.04), and xml-resolver (v 1.2). I tried defining the EAR to use the new library
<imported-shared-libraries>
<imported-shared-library name="apache.xml"/>
</imported-shared-libraries>
I receive the following error
14:50:31 ERROR (UserId:) [DispatcherServlet] Context initialization failed
org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException:
Line 10 in XML document from ServletContext resource [/WEB-INF/spring/webflow-config.xml] is invalid;
nested exception is org.xml.sax.SAXParseException: cvc-complex-type.2.4.c:
The matching wildcard is strict, but no declaration can be found for element 'webflow:flow-executor'.
The webflow-config.xml file is defined as normal:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd">
<!-- Executes web flows -->
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry" />
<!-- Rest of the file ... -->
</beans>
Does anyone have any ideas?
[Edit]
The snippet:
<imported-shared-libraries>
<imported-shared-library name="apache.xml"/>
</imported-shared-libraries>
should, of course read:
<imported-shared-libraries>
<import-shared-library name="apache.xml"/>
</imported-shared-libraries>
Sorry!
I found the answer to this. Turns out this was specifically because I was running OC4J on a Java 6 JVM. If anyone else gets this problem, here's what we did to resolve:
The Oracle XML parser does not handle the Spring 3 XSD files well, this is a know issue. You need to remove the Oracle XSD libraries for your application. In your orion-application.xml file, you need
<imported-shared-libraries>
<remove-inherited name="oracle.xml"/>
</imported-shared-libraries>
The Oracle documentation then tells you to import a new shared library. However, if you're running OC4J on a Java 6 JVM (which we are!), you can't do this. It looks like there is an XML parser in the Java 6 core now, and importing Xerces libraries will conflict with these classes, causing weird errors.
Anyway, on Java 6, remove the Oracle libraries, but don't import any other ones!

Resources