Tuesday, November 22, 2011

Exploring Spring Integration & Spring Web Service, Part 1

I have been learning Spring Integration and Spring Web Services on the project I am on. The more I learn the more I like the framework, but I have to say it has not been easy to make progress. The number of resources available is lacking. I thought I would spend the next several blogs covering some of the information I have been learning.

I needed to do was expose four SOAP Web Services based on a set of WSDL and XSD files provided by the vendor. First thing that had to happen was setting up the web.xml file. From reading the documentation on the main Spring site, I determined to use MessageDispatcherServlet.

web.xml

<web-app>
<display-name>My Application Name</display-name>
<servlet>
<servlet-name>si-ws-gateway</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:si-ws-gateway-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>si-ws-gateway</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>


Next, let's take a look at the spring application context file.
si-ws-gateway-config.xml

<bean class="org.springframework.ws.server.endpoint.mapping.UriEndpointMapping">
<property name="mappings">
<props>
<prop key="${data.subscriber.url}">dataGateway</prop>
<prop key="${request.status.url}">statusGateway</prop>
</property>
</bean>

<si:channel id="dataArrivedChannel" />
<si-ws:inbound-gateway id="dataGateway" request-channel="dataArrivedChannel" />
<stream:stdout-channel-adapter id="stdoutAdaptorWithDefaultCharsetDataArrived" channel="dataArrivedChannel"/>

<si:channel id="statusChangedChannel" />
<si-ws:inbound-gateway id="statusChangedGateway"
request-channel="statusChangedChannel"
marshaller="marshaller"
unmarshaller="marshaller"/>
<si:service-activator input-channel="statusChangedChannel"
ref="statusServiceEndpoint"
method="processStatusMessage"/>

<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.ourvendor.StatusUpdate</value>
</list>
</property>
</bean>

<bean id="StatusDao" class="com.company.StatusDao"/>

<bean id="statusServiceEndpoint"
class="com.company.StatusServiceEndpoint">
<constructor-arg ref="statusManager"/>
</bean>

<bean id="statusManager"
class="com.company.StatusManagerImpl">
<constructor-arg ref="statusDao"/>
</bean>



Well that seems like a lot of spring configuration, but it eliminates a bunch of Java code. Let's break down this configuration a bit. First, the UriEndpointMapping bean. You might notice that there are some values provided from a properties file. I will be covering properties in more detail in a future blog. For now, just know spring replaces the ${data.subscriber.url} and ${request.status.url} with a valid URL value from a properties file. This defines which URLs will be routed to the specified spring integration web services inbound-gateway. The gateway will place the SOAP message onto the specified channel as a DOMSource object.

As seen above the dataGateway does not specify a marshaller and unmarshaller which is why the DOMSource object is placed on the channel. The statusChangedGateway does specify the marshaller and unmarshaller, so when it places the object on the channel, it is not a DOMSource object, but a StatusUpdate object. As you can see it is very easy to leave the input in it's native format or convert it to a Java Object. In one case the object was only going to be routed(eventually) to a JMS queue, and did not need to be unmarshalled, in the other case it required unmarshalling so that a service activator endpoint could save the object to the database. As we will see in a future blog, it would have been nice if there was a way to specify the output to the channel as a string, instead of DOMSource. This would be a great enhancement to spring integration.

The service activator is an endpoint that allows a specific method to be called, and passes the object from the incoming channel to the method. It can also place the object, either unmodified or modified, onto an outgoing channel to be further processed by the system. The rest of the configuration is very straightforward spring beans with dependency injection. This works very well if each of the web services have a unique URL, but what happens if all calls come into a single URL. That will be the topic of the next blog in this series.

3 comments:

Mel said...

Hi Jeff, there is something with the code. Can check it again..IT Support

Anonymous said...

Great effort.I like your way of explanation.It really useful .Thanks for sharing your creation.
Ecommerce developer

Unknown said...

Hi,Ask how long it takes to get a response via email or telephone and inquire in Web Design Cochin as to what hours your web developer will be available to speak with you. Often times, entrepreneurs and business owners do not have time during their busy day to deal with their website matters, and after hour meetings are needed. Thanks.........