As detailed in my last article I think the current CXF configuration style has it´s problems. To provide people with a short time solution I have described how to use the Camel transport together with Camel´s JMS transport. After my article there was a discussion on the CXF dev mailing list on better JMS support for CXF. The agreement was that CXF should not depend on Camel for JMS and that the JMS config for CXF should be improved.In this article I will propose an alternative configuration style for JMS (and perhaps also other transports). The style is quite similar to Camel´s style and tries to bring the positive aspects of the Camel transports to CXF.
I have started by defining some goals that are important to achieve for the new configuration and implementation. Of course this is only my opinion. I would be very interested in what goals you would like to see implemented.
- Focus more on dependency injection. Do less in the JMSConduit
- Allow injection of the ConnectionFactory. So it can be provided directly from a spring bean or via a spring JNDI lookup
- Allow setting of parameters via ProperyPlaceholderConfigurer
- Avoid coupling the Conduit to the Client by endpoint name. Instead set the config as property
- Allow setting of Transport parameters from the address property of the Client or Endpoint
- Support declarative transactions using Springs JMS support (This is mainly an implementation issue)
The basis will be as before the Client or Endpoint config. This is extended by one new property transportConfig.
In this sample config we reference the bean jmsConf1 as transportConfig. So all settings in this bean will be the defaults. The url after jms:// is implicit set as the parameter targetDestinationName.
Then each parameter from the address overwrites a property of the JMSConfig. So you can define defaults in the JMSConfig and still do special settings for the Endpoint using the URL. Camel has a nice Tool to extract such config info from a string like address and configure a bean with it using reflection. Setting parameters in this way has it´s drawbacks in transports where the parameters are part of the real URL. I am not yet sure how this can be avoided. Setting the parameters from the URL is not absolutely necessary so we should decide if the advantages are worth the trouble.
This is my proposal for a new Config Element of Client and Endpoint named TransportConfig. TransportConfig is a marker interface. The classs JMSConfig implements this interface and contains the special config settings for JMS. Here I only show some few settings. For a complete list we could take a look at the JMSComponent in Camel and see which we need. They also include declarative transactions which we should also try to implement.
I have used the new p Style from spring for the xml sample but it is a normal Bean. The first parameter is a reference to a connection Factory bean. The next two parameters are taken from the Camel JMSComponent as illustration of what we could configure. The last property is for the target JMS Destination. It can be set either as a reference to a bean or as a string. In this case I used the reference to a bean and retrieve the Destination by doing a JNDI lookup. Alternatively I could have set the targetDestination name with a string that defines a queue in the chosen JMS provider.
If you don´t want to use the above described override by using the URL parameters you can also use Springs templating mechanism to support basic configs that are then overriden in some properties. Here is a short sample:
Here the jmsConf2 will have all properties from jmsConf1 and then override some.
I think this new configuration style could be easily built into CXF and would improve the experience for users dramatically. What do you think about it? Are there other ideas how to do a better config for CXF?