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

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

Related

Spring schema folder & Spring XML namespaces

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.

Create beans with property names as element names?

I am new to spring and happy to see that following works as expected:
<bean id="..." class="server.Shell">
<property name="usableCommands" value="cat"/>
</bean>
The above is in the client code, where I have provided the server.Shell. Now I would like for the clients to be able to use the following:
<shell id="...">
<usableCommands value="cat"/>
</shell>
Is there anything in springframework that I can use to map say an xsd to bean classes? Any other suggestion for easily creating a simple xml based domain language?
You can register a custom XML Namespace in Spring that would allow you to customize your configuration XML. If you're looking to create a sort of DSL in your Spring configuration XML, that might be a good place to start.
UPDATE:
Check out this link for a general example of how custom namespaces in Spring work. This pattern should hold in OSGi as well -- check out Section 6.4 of the Spring OSGi docs for an explanation. If you're new to OSGi, it can be daunting in general. SpringDM can help. Try here for some background and here for an example. Hope that helps.

Get config setting in custom taglib using Spring "context-property-placeholder"

I'm creating a custom taglib, and would like to use some config options that are loaded via the underlying Spring framework using:
<context:property-placeholder location="classpath:config.properties" />
How would I get access to these variables in my taglib?
Thanks,
James.
The JSP taglibs have nothing in common with the Spring context's lifecycle, they're managed by the servlet container. This can complicate things a bit, for example: inject-dependency-into-a-taglib-class, how-to-write-tag-in-my-spring-project.
Since you're only mentioning the need for contents of the properties file, you could use plain old java.util.ResourceBundle (or, if you need more flexibility, Apache Commons' org.apache.commons.configuration.PropertiesConfiguration).
(One could also argue that requiring access to configuration in your tags indicates a design problem...)

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.

why is jax-ws spring service reference prefixed with #, as in ws:service bean="#myService"

I've developed a web service with jax-ws and Spring using the tutorials at the jax-ws commons website. It shows you how to define and reference your service from your spring applicationContext file (https://jax-ws-commons.dev.java.net/spring/).
What is the reason for the "#" when referencing the web service? I would expect to see something more like
<ws:service name="myEventWS" ref="eventWebService"/>
but following example at the above link I created the following which works.
<bean id="eventWebService" class="com.myws.EventWS">
<property name="model" ref="EventModel"/>
</bean>
<wss:binding url="/EventWS">
<wss:service>
<ws:service bean="#eventWebService"/>
</wss:service>
</wss:binding>
<ws:service> is using a custom configuration namespace, which is a feature of Spring which allow you to express complex bean graphs using simpler namespace. The meaning and interpretation of these custom namespaces is down to the implementation in question, in this case the JAX-WS-Commons project. It seems the authors of that decided that bean=#eventWebService means what you refer to as ref="eventWebService".
I don't know whay they did it that way, maybe they thought it was more readable... maybe they thought that bean=eventWebService (without the hash) means a name, rather than a reference... I don't know. The documentation isn't very clear either.
Either way, I'm pretty sure sure it's not a core Spring syntax, nor a convention that I've seen before.
the "#" tells the bean that it's not a class, but rather a ref.
HTH
#eventWebService refers to the bean of type EventWebService (according to the default Spring naming convention when bean is is not specified).

Resources