My previous post was about creating a client with the spring-ws project. This dis take me some time to grasp. But without a published webservice a client is of no much use. Therefore I also had a look at the server side. To my surprise this was even easier than expected. I did have some requirements for the sample:

  • wsdl generation
  • marshalling/unmarshalling using jaxb2

That does not sound to bad does it? Well try to do it with axis and you’ll be surprised. If you know a little bid about spring-webmvc and the use of the dispatcher, you know you need one configuration file for spring. For the webservice I had to provide the spring config file and one class, yes really, just one class. I used maven to generate the jaxb stuff and this is wat I did:

web.xml
<servlet>
  <servlet-name>spring-ws /servlet-name>
  <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>spring-ws /servlet-name>
  <url-pattern>/* /url-pattern>
</servlet-mapping>

The spring-ws framework provides a special servlet that receives the requests. No the really hard part, the spring configuration for the endpoint:

<bean class="org.springframework.ws.server.endpoint.mapping.SimpleMethodEndpointMapping">
  <property name="endpoints" ref="congressRegistrationEndpoint"/>
</bean>
<bean id="congressRegistrationEndpoint"  class="nl.gridshore.samples.springws.server.JaxbMarshallingMethodEndpoint">
  <property name="marshaller" ref="marshaller"/>
  <property name="unmarshaller" ref="unmarshaller"/>
</bean>
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
  <property name="contextPath" value="nl.gridshore.samples.jaxb"/>
</bean>
<bean id="unmarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
  <property name="contextPath" value="nl.gridshore.samples.jaxb"/>
</bean>

First check the endpoint mapping, this class SimpleMethodEndpointMapping is found by the dispatcher to map all incoming requests to endpoints. In our case we map to our only endpoint called the congressRegistrationEndpoint. This class has a special super class that needs a marshaller and unmarshaller. Other than that it needs nothing. By convention the name of the Request is used by the super class to know which method to call. In our case we have a CongressRegistrationRequest. Therefore we need to implement to method handleCongressRegistrationRequest as you can see in the following coded block.

public CongressRegistrationResponse handleCongressRegistrationRequest(CongressRegistrationRequest request) {
  ObjectFactory objectFactory = new ObjectFactory();
  CongressRegistrationResponse response = objectFactory.createCongressRegistrationResponse();
  response.setRegistrationCode("code333");
  return response;
}

In this code the argument and the return value are JAXB objects. I created the most easy method, do nothing with the request and always return the same response. Bu as you can see the code itself is very clean. I do not need to do a lot of conding. I think this is probably one of the easiest implementations I have seen that works in java 1.4 as well.

That is it for one of the requirements. Now I also wanted a solution for generating the wsdl. In the end this is only some springframework configuration. You also need an xsd, but you have already used this to generate the jaxb classes with maven. So we can reuse it. Check the following configuration

<bean id="service" class="org.springframework.ws.wsdl.wsdl11.DynamicWsdl11Definition">
  <property name="builder">
    <bean class="org.springframework.ws.wsdl.wsdl11.builder.XsdBasedSoap11Wsdl4jDefinitionBuilder">
      <property name="schema" value="/WEB-INF/classes/congressregistration.xsd"/>
      <property name="portTypeName" value="services"/>
      <property name="locationUri" value="http://localhost:8080/spring-ws-sample-server/"/>
      <property name="targetNamespace" value="https://www.gridshore.nl/samples/definitions"/>
    </bean>
  </property>
</bean>

So you need the location of the xsd, the name of the bean is used to find the wsdl. The locationUri locates the endpoint and the targetNamespace is the namespace used in the xsd. By entering the following url you can find the wsdl.
http://localhost:8080/spring-ws-sample-server/service.wsdl

You can check the code at the google code project.

I know it is pretty short, but with the code you should be able to understand it.

greetz Jettro

Using Spring-ws for creating a webservice