ICE09 . playing with java, scala, groovy and spring .

Playing with Spring

Archive for the ‘Spring Web Services’ Category

…afraid of SOAP?

Posted by ice09 on June 3, 2011

Intention

Thinking of Web Services, REST, mostly combined with JSON as the transport medium, currently is everywhere. Having done a lot for the acceptance of Web Services and furthermore simplifying the usage of Web Services themselves, there nevertheless seems to be a strong tendency to overuse REST.

How can REST be overused? This obviously depends on the use case, there are several use cases REST is not the definite answer:

  • A strictly defined format of input and output data (the data transfer format), which can easily be validated
  • A backend to backend communication, where no REST-affine language like JavaScript is used
  • Communication between legacy systems which would have to have REST adapters built and already have SOAP-compliant adapters
  • Pure service-oriented components, as well as (pre-)ESB and EAI systems

So, REST is not the answer to all Web Service problems. However, it is often proposed as this. To my experience, this is mainly caused by the fact that people think SOAP is just too complicated, not suitable for light services and just too much overhead. Even though that might be true with respect to WS-*, it is really quite easy to setup Web Services server and clients (and tests) which use SOAP – with no hassle.

The User Web Service – A practical approach to SOAP Web Services

We will follow a really practical approach, ie. many pictures, almost no theoretical background. However, whenever necessary, a link will be present to sites explaining the theoretical background.

In this post, Spring Web Services 2 is used for the server and client side. Even though there are “easier” frameworks around, which make creation of (SOAP) Web Services from existing Java code a breeze, this is exactly the approach you should not follow, if maintenance, extensibility and flexibility is of concern.

So, here is the first drawback: we will use the slightly more complicated “contract-first” approach. But just believe in me: after having dealt with several Web Services, you will never regret the challenging beginning when it comes to maintenance of existing services (including versioning, implementing fixes/patches, etc.)

Let’s go

During this post, the Spring Tool Suite (currently 2.6.0) is used. You can just as well use Eclipse (or any other IDE), the STS is used since the Maven plugin is already included, as well as Spring tooling, which supports Spring Web Services and eases usage of this framework.

  1. Download SpringSource Tool Suite
  2. Create new Maven Project with spring-ws-archetype
  3. Add XML Schema (the contract)
  4. Generate JAXB classes, the XML-Java data binding from the XML Schema files
  5. Create Endpoint and Spring WS annotations and config
  6. …that’s it – test it

Step 2: Create new Maven Project with spring-ws-archetype

Choose “File / New / Other… / Maven Project”

mvn_new

Choose “archetype selection” (do not check skip…)

mvn_new_2

Choose “Add archetype” and type values according to screenshot (we need to add at least version 2.0.2, currently only 2.0.0-M1 is available in catalog)

mvn_choose_at

Choose the added archetype from selection

mvn_new_4

Choose the settings for your project, these values are arbitrary (for testing purposes you can use the ones from the screenshot)

mvn_new_5

The steps above can be shortened by just creating the Maven project from the command line and importing the generated project as an existing maven project in STS/Eclipse (with “File / Import / Existing Maven project”).

mvn archetype:create -DarchetypeGroupId=org.springframework.ws -DarchetypeArtifactId=spring-ws-archetype -DarchetypeVersion=2.0.2.RELEASE -DgroupId=de.ice09.blog -DartifactId=userservice-ws

However, for this to work Maven has to be installed correctly, M2_HOME and JAVA_HOME have to be set correctly, etc. Using the steps above just require STS or Eclipse + Maven plugin to be installed.

More details about these steps are available in this short & nice blog post.

Right now this project structure should have been generated

structure_1

Step 3: Add XML Schema (the contract)

There are several ways for creating a XML Schema, you can use XMLSpy, which to me is the best tool for this task, but is quite expensive. The XML Schema editor in Eclipse is quite useful as well (and integrated and free).

A recent discovery is WMHelp XMLPad, which is pretty cool and supports diagrams similar to those of XMLSpy:

GetUser

StoreUser

These diagrams are quite self-explanatory, we want to have to services, the first one accepts requests of type GetUserRequest, which just have an id and returns a GetUserResponse, which consists of id, firstname, lastname, and 1..n buddies, which themselves are just ids. The second service is StoreUser, which is the “storage” equivalent if the “reading” GetUser service.

Since the contract is the most important part of the Web Service, I will list the XML Schemas as well as sample data here, you can just skip them if you are more interested in the framework usage.

Please note: all posted source code in this blog post is just for clarifying purpose, you do not need to copy & paste this code – a complete SpringSource Tool Suite/Maven-project is available on Google Code.

XML Schema (just GetUser, StoreUser is similar)

 
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://de.ice09.blog/userservice-ws/"
	targetNamespace="http://de.ice09.blog/userservice-ws/">

    <element name="GetUserRequest">
    	<complexType>
    		<sequence>
	    		<element name="id" type="string"/>
    		</sequence>
    	</complexType>
    </element>
    
    <element name="GetUserResponse">
    	<complexType>
	    	<sequence>
	    		<element name="id" type="string"/>
	    		<element name="firstname" type="string"/>
	    		<element name="lastname" type="string"/>
	    		<sequence>
	    			<element name="Buddies">
	    				<complexType>
	    					<sequence>
	    						<element name="Buddy" type="string" minOccurs="0" maxOccurs="unbounded"/>
	    					</sequence>
	    				</complexType>
	    			</element>
	    		</sequence>
	    	</sequence>
    	</complexType>
    </element>
    
</schema>

Step 4: Generate JAXB classes, the XML-Java data binding from the XML Schema files

For the next step to work we have to enrich our Maven pom.xml with a jaxb-maven-plugin. This plugin will create the JAXB-classes from the XML Schema files during a Maven build.

str_xsd

Add the following lines to the pom.xml in the project’s root folder in section “plugins” as well as the dependencies in section “dependencies”. After saving the file, a new folder “generated-sources” in the target-folder should be created (if this does not happen, choose “Project / Clean”). These are the generated classes, which have to be added to the sources.

JAXB2-Maven-Plugin

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>jaxb2-maven-plugin</artifactId>
  <executions>
    <execution>
      <goals>
	<goal>xjc</goal>
      </goals>
     </execution>
   </executions>
  <configuration>
    <schemaDirectory>src/main/webapp/WEB-INF/</schemaDirectory>
  </configuration>
</plugin>

pom_add_plugin

JAXB2-Maven-Dependencies

<dependency>
  <groupId>javax.xml.bind</groupId>
  <artifactId>jaxb-api</artifactId>
  <version>2.0</version>
</dependency>
<dependency>
  <groupId>com.sun.xml.bind</groupId>
  <artifactId>jaxb-impl</artifactId>
  <version>2.0.3</version>
</dependency>
<dependency>
  <groupId>org.apache.xmlbeans</groupId>
  <artifactId>xmlbeans</artifactId>
  <version>2.4.0</version>
</dependency>
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.8.1</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>log4j</groupId>
  <artifactId>log4j</artifactId>
  <scope>compile</scope>
  <version>1.2.16</version>
</dependency>

pom_add_deps

Step 5: Create Endpoint and Spring WS annotations and config

Create a folder named “java” in src/main-folder and add this folder to the source path, analog to the generated-sources folder. This step might not be necessary in future archetype versions.

Afterwards, this classes must be added to the source folder.

//[imports removed]

@Endpoint
public class GetUserEndpoint {

        @Autowired
        private UserService userService;

        @PayloadRoot(localPart = "GetUserRequest", namespace = "http://de.ice09.blog/userservice-ws/")
        @ResponsePayload
        public GetUserResponse getUser(@RequestPayload GetUserRequest request) {
                GetUserResponse response = new ObjectFactory().createGetUserResponse();
                response.setLastname(userService.getName());
                response.setFirstname("firstname");
                return response;
        }

}

A detailed explanation of the annotation can be found on the Spring Web Services site. For now, only a minimal explanation is given: The @Endpoint annotation lets Spring know that this class will be used as a Web Service endpoint. The @Autowired annotation is standard Spring and results in the service class being injected to the endpoint automatically without XML declarations. The interesting part is the @PayloadRoot annotation in combination with @RequestPayload and @ResponsePayload. There is a lot of convention-over-configuration going on here and a lot of magic inside. If used this way, Spring recognizes the generated JAXB-classes on the classpath. When a XML request with an XML element “GetUserRequest” (localPart) and namespace “http://de.ice09.blog/userservice-ws” arrives, the generated JAXB-classes are used to marshall the XML element to a Java object due to the @Request/ResponsePayload annotations and the presence of JAXB and the generated JAXB-classes on the classpath.

If this is new to you, you should get familiar with it, otherwise it will fall back on you if you have to change anything, eg. from JAXB to Castor, DOM, XPath or whatever. This described usage (JAXB and annotations) is the easiest way possible, but the framework allows for almost any thinkable combination and framework usage. There might be more configuration necessary though.

The service is just listed for completeness, it does nothing special. Just note the @Coomponent annotation. This lets Spring know that this bean/class will be injected somewhere, eg. by using @Autowired as we did.

de.ice09.blog.ws.service;

import org.springframework.stereotype.Component;

@Component
public class UserService {

        public String getName() {
                return "lastname";
        }

}

Now for the most interesting component, the Spring config. It is already present in the WEB-INF directory. You just have to insert these XML elements:

<?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:sws="http://www.springframework.org/schema/web-services"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:util="http://www.springframework.org/schema/util"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

        <bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
                <property name="soapVersion">
                        <util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_12" />
                </property>
        </bean>

        <sws:annotation-driven />

        <context:component-scan base-package="de.ice09.blog.ws" />

        <sws:dynamic-wsdl id="GetUser" portTypeName="UserManagement"
                createSoap12Binding="true" createSoap11Binding="false" locationUri="/userservice"
                targetNamespace="http://de.ice09.blog/userservice-ws/">
                <sws:xsd location="/WEB-INF/GetUser.xsd" />
        </sws:dynamic-wsdl>

        <sws:dynamic-wsdl id="StoreUser" portTypeName="UserManagement"
                createSoap12Binding="true" createSoap11Binding="false" locationUri="/userservice"
                targetNamespace="http://de.ice09.blog/userservice-ws/">
                <sws:xsd location="/WEB-INF/StoreUser.xsd" />
        </sws:dynamic-wsdl>

</beans>

The most important element is <sws:annotation-driven>, together with <context:componant-scan>. These elements do all the magic, I highly advise you to get accustomed to the way these elements work. The other parts are just for automatic WSDL generation, which eases the usage of the generated Web Services a lot, but are not necessary for the services themselves. The messageFactory is just for compliance with SOAP 1.2 and can be ignored – just make sure you include it if you want to use SOAP 1.2 instead of SOAP 1.1. Same is true for the dynamic WSDL-generation – the attributes must be set to true and false respectively.

For the WSDL generation, the web.xml has to be modified as well, just add the init-param lines:

<servlet>
        <servlet-name>spring-ws</servlet-name>
        <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet
        </servlet-class>
        <init-param>
                <param-name>transformWsdlLocations</param-name>
                <param-value>true</param-value>
        </init-param>
</servlet>

Step 6: …that’s it – test it

Yes, that’s it. We created a complete new Web Service with really simple steps.

Just start the Web application now on the STS included tc-Server, just by right-clicking the project and choosing “Run As… / Run on Server”

run_final

Afterwards, navigate to http://localhost:8080/userservicews/GetUser.wsdl there should be a WSDL printed in the browser.

We can now test the Web Service with a Web Service client, for now we will use soapUI, which is a pretty neat tool for this purpose. You can Web Start it or download it, it requires no install. Even better than soapUI is the Spring Web Service client, which we will investigate in the following blog entry.

After starting soapUI, create a new project and provide the aforementioned WSDL-Url. soapUI will ask for creating a test suite and test cases, which should just be unmodified accepted.

soapui_new

soapui_new_1

If everything worked, you can just choose the created test suite with its test case and run the test case. The result should look like the screenshot.

soapui_run

If this blog post was useful to you, you can tip me. Maybe you do not want to tip, but please inform yourself about Bitcoin and applications of Bitcoin like Youttipit.

Posted in SOAP, Spring Web Services | 4 Comments »

Consuming Services – the Spring Web Service Client

Posted by ice09 on August 25, 2008

There is a downloadable zipped Eclipse project at the end of this post.

Having created a sample (mail) web service some posts ago, we would like to have a client consuming this service.

With Spring Web Services, this can easily be done by using the ubiquitous Template Pattern and, in this special case, the WebServiceTemplate . As the project structure can be downloaded, only the two important snippets are shown here:

The application-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<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.0.xsd">

    <bean id="mailclient" class="de.mail.MailClient">
    	<property name="webServiceTemplate" ref="webServiceTemplate"/>
    </bean>

    <bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>

    <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
        <constructor-arg ref="messageFactory"/>
        <property name="marshaller" ref="marshaller"/>
        <property name="unmarshaller" ref="marshaller"/>
        <property name="defaultUri" value="http://localhost:8080/mailservice"/>
    </bean>

    <bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
		<property name="classesToBeBound">
			<list>
				<value>org.mail.mailschema.MailRequest</value>
				<value>org.mail.mailschema.MailResponse</value>
			</list>
		</property>
	</bean>

</beans>

and the actual Web Service client:

package de.mail;

import org.mail.mailschema.MailRequest;
import org.mail.mailschema.MailResponse;
import org.springframework.ws.client.core.WebServiceTemplate;

public class MailClient {

	private WebServiceTemplate webServiceTemplate;

	public void setWebServiceTemplate(WebServiceTemplate webServiceTemplate) {
		this.webServiceTemplate = webServiceTemplate;
	}

	public boolean send(String user, String password, String from, String to, String subject, String content) {
		MailRequest request = new MailRequest();
		request.setFrom(from);
		request.setTo(to);
		request.setUser(user);
		request.setPassword(password);
		request.setContent(content);
		request.setSubject(subject);
		return ((MailResponse)webServiceTemplate.marshalSendAndReceive(request)).isResult();
	}

}

The servlet sample is not shown, since it is just for demonstration and not a nice piece of code. However, it exemplifies some Spring antipatterns, because DI is not used and the servlet is not Springified at all. But it’s only a sample showing how to use the Web Service client.
By deploying the servlet (or using mvn jetty:run again), a mail can be send by calling http://server/mailwebapp/Mailer?user=USER&password=PASSWORD&to=RECIPIENT@BLA.DE&from=me&subject=SUBJECT&content=MAILTEXT
But the actual code could be much nicer (also, it is definitely not safe – just a counter and a whitelist is added to prevent immediate abuse :))

Sample Mail Web Service client project:

Instructions:

  1. Download the wsclient-sample
  2. Download the mailwebapp-sample
  3. Download the maildatabinding

If correctly imported as Eclipse projects, the dependencies should be automatically resolved.
The mailwebapp can be deployed as a usual Web application which uses the Web Service client to call the Mail Web Service, which must be already deployed (compare the Spring Web Service post).

Posted in Mail, Maven, Spring Web Services | Tagged: , | 7 Comments »

Service Oriented Spring

Posted by ice09 on June 29, 2008

There is a downloadable zipped Eclipse project at the end of this post.

An interesting almost new subproject in the Spring environment is Spring Web Services.
In short: in finest Spring manner, DI and small little helper form a contract-first Web Service framework. The pros and cons about contract-first vs. contract-last Web Services is explained in the tutorial. From personal experience, contract-first requires more initial effort, but pays a lot afterwards. In our application, the aspect of versioning was underestimated first. By using contract-first, it was really easy to introduce detailed versioning (on basis of namespaces with the PayloadRootAnnotationMethodEndpointMapping)
Depending on the data structure which should be transferred, it may be better to choose the XPathParamAnnotationMethodEndpointAdapter
(for little payloads) over the GenericMarshallingMethodEndpointAdapter (for huge, object oriented payloads).

Excursion

When marshalling should be used, the Java classes for the XML Schema must be generated. There exist several framework to ease this process. In this sample, JAXB2 is used. There are several helper for using JAXB and automize the process of class generation.

  • Create a quickstart Maven project (using the Eclipse-Maven plugin, compare this post).
  • Overwrite the generated POM with the following
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>javabinding</groupId>
	<artifactId>javabinding</artifactId>
	<packaging>jar</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>javabinding</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.0</version>
		</dependency>
	</dependencies>
	<repositories>
		<repository>
			<id>java.net</id>
			<name>java.net Maven Repository</name>
			<url>https://maven-repository.dev.java.net/nonav/repository</url>
			<layout>legacy</layout>
		</repository>
	</repositories>
	<build>
		<plugins>
			<plugin>
				<groupId>com.sun.tools.xjc.maven2</groupId>
				<artifactId>maven-jaxb-plugin</artifactId>
				<executions>
					<execution>
						<goals>
							<goal>generate</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.5</source>
					<target>1.5</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

This POM includes several configuration and dependency information which allows for using the JAXB-Maven2-Plugin

  • You can put your XSDs into the subdirectory /src/main/resources.
  • Below is a sample XML Schema which defines a Request and Response object (this convention is necessary for automatic WSDL generation).
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/WSSchema"
	xmlns:tns="http://www.example.org/WSSchema" elementFormDefault="qualified">

	<element name="SampleRequest">
		<complexType>
			<sequence>
				<element name="StringArgument" type="string"></element>
			</sequence>
		</complexType>
	</element>

	<element name="SampleResponse">
		<complexType>
			<sequence>
				<element name="StringArgument" type="string"></element>
			</sequence>
		</complexType>
	</element>
</schema>
  • Run Maven with goals clean,install.

Afterwards (and a refresh (F5) on the project), there should be a generated-resources directory in subdirectory target. The compiled classes reside in classes.

  • Add target/generated-sources/xjc to the project’s buildpath.
  • You can now include the generated, compiled classes in other projects with this dependency in the POM.
<dependency>
  <groupId>javabinding</groupId>
  <artifactId>javabinding</artifactId>
  <version>0.0.1-SNAPSHOT</version>
</dependency>

Setup

  • Following the tutorial, create the Maven project first
mvn archetype:create -DarchetypeGroupId=org.springframework.ws -DarchetypeArtifactId=spring-ws-archetype -DarchetypeVersion=1.5.2 -DgroupId=de.wssample -DartifactId=wssample
  • Afterwards, create a eclipse project from the maven resources.
cd wssample
mvn eclipse:eclipse
  • The generated eclipse project can now be imported as a Eclipse project into eclipse.
  • Remove the M2_REPO entries from the project’s build path.
  • Use the follwing POM which includes the javabinding we generated above and the jetty-plugin for fast deployments.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>de.wssample</groupId>
    <artifactId>wssample</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>wssample Spring-WS Application</name>
    <url>http://www.springframework.org/spring-ws</url>
    <build>
        <finalName>wssample</finalName>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<inherited>true</inherited>
				<configuration>
					<source>1.5</source>
					<target>1.5</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.mortbay.jetty</groupId>
				<artifactId>maven-jetty-plugin</artifactId>
				<version>6.1.4</version>
				<configuration>
					<contextPath>/</contextPath>
					<scanIntervalSeconds>10</scanIntervalSeconds>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<dependencies>
		<dependency>
			<groupId>org.springframework.ws</groupId>
			<artifactId>spring-oxm</artifactId>
			<version>1.5.2</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.ws</groupId>
			<artifactId>spring-oxm-tiger</artifactId>
			<version>1.5.2</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.ws</groupId>
			<artifactId>spring-ws-core</artifactId>
			<version>1.5.2</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.ws</groupId>
			<artifactId>spring-ws-core-tiger</artifactId>
			<version>1.5.2</version>
		</dependency>
		<dependency>
			<groupId>javabinding</groupId>
			<artifactId>javabinding</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
	</dependencies>
</project>
  • Put your XSD in the WEB-INF directory (in the sample above, the WSSample.xsd). This is necessary for the automatic WSDL generation.

The project structure should look like this:

The spring-ws-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<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.0.xsd">

	<!-- Register PayloadRootAnnotationMethodEndpointMapping -->
	<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping" />

	<!-- Register Endpoint -->
	<bean id="sampleEndpoint" class="de.wssample.SampleEndpoint"></bean>

	
	<!-- Configure XML Marshaller -->
	<bean class="org.springframework.ws.server.endpoint.adapter.GenericMarshallingMethodEndpointAdapter">
		<constructor-arg ref="marshaller" />
	</bean>

	<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
		<property name="classesToBeBound">
			<list>
				<value>org.example.wsschema.SampleRequest</value>
				<value>org.example.wsschema.SampleResponse</value>
			</list>
		</property>
	</bean>

	<!-- Add automatic WSDL generation support -->
	<bean id="sample" class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition">
		<property name="schema" ref="schema" />
		<property name="portTypeName" value="SampleWS" />
		<property name="locationUri" value="http://localhost:8080/samplews/" />
		<property name="targetNamespace" value="http://samplews" />
	</bean>

	<bean id="schema" class="org.springframework.xml.xsd.SimpleXsdSchema">
		<property name="xsd" value="/WEB-INF/WSSchema.xsd" />
	</bean>

</beans>

The web.xml was generated automatically, the Endpoint is as follows

package de.wssample;

import org.example.wsschema.SampleRequest;
import org.example.wsschema.SampleResponse;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;

@Endpoint
public class SampleEndpoint {
    
    @PayloadRoot(localPart = "SampleRequest", namespace = "http://www.example.org/WSSchema")
    public SampleResponse doit(SampleRequest request) {
    	SampleResponse response = new SampleResponse();
    	response.setStringArgument("response");
        return response;
    }

}
  • Run mvn with goals clean,compile,jetty:run.
  • Point the browser to the generated WSDL.
  • It is important to note that with this setup, the root context can be used and the WSDL is generated if the org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition bean id + .wsdl is called (“sample” in this case).

You can now test the Web Service with the great tool soapUI, which generates test request data for you, let’s you modify the data and allows for creating and executing test cases.

Sampleproject: A mail web service

In the project a web services around the velocitymailsample is created which results in a mail web service.

Instructions:

  1. Download the velocitymail-sample
  2. Download the mail-databinding-sample
  3. Download the mail-service-sample

server in /velocitymail/src/main/resources/applicationContext.xml has to be set and access to a (secured) SMTP mail server is necessary to run the sample.

If correctly installed into the same eclipse workspace, the dependencies should be resolved automatically. However, to deploy the application as a WAR, you will need to mvn clean install sampledatabinding, velocitymail and mailservice in this order.

To run the web service with the jetty-maven-plugin, you can run the mailservice project with goals mvn clean install jetty:run.

Posted in Maven, Spring Web Services | Tagged: , | 2 Comments »