Before you start
About this tutorial
Objectives
In this tutorial, you
design and develop a simple application with maven that exposes its
functionality as web services in a platform-independent manner. After going through this
tutorial, you can apply the concepts and knowledge to develop web services for
your application using JAX-WS technology and maven.
- We will build it with Maven
- We will not copy jars to the Tomcat. All dependencies will be managed by Maven
Plan :
1- Develop
a web service maven project
2- Develop
a JAXWS web service with SOAP 1.2
2.1 Develop a Person Management web service
2.2 Generate web services artifacts with wsgen
2.3 Update web.xml
2.4 Create web service deployment descriptor sun-jaxws.xml
2.5 Deployment
2.6 Test with SOAPUI 4.5.1 :
3- Develop
a web service Client maven project
3.1 create maven project
3.2 Generate web services artifacts for client with
wsimport
3.3 A factory, a manager and a main class for test
Prerequisites
To complete this
tutorial successfully, you should have a basic understanding of web services
technology and have some proficiency in Java programming.
System requirements
To run the examples in
this tutorial, you need :
- Eclipse WTP 3.4
- Maven 3.0
- JAXWS RT 2.1.3
- JAVA 6
- TOMCAT 6
Introduction to JAX-WS
Why JAX-WS?
Java API for XML Web
Services (JAX-WS), JSR 224, is an important part of the Java EE 5 and EE 6
platforms. A follow-up to the release of Java API for XML-based RPC
1.1(JAX-RPC), JAX-WS simplifies the task of developing web services using Java
technology. It addresses some of the issues in JAX-RPC 1.1 by providing support
for multiple protocols such as SOAP 1.1, SOAP 1.2, XML, and by providing a
facility for supporting additional protocols along with HTTP. JAX-WS uses JAXB
2.0 for data binding and supports customizations to control generated service
endpoint interfaces. With its support for annotations, JAX-WS simplifies web
service development and reduces the size of runtime JAR files.
Introduction to Maven
Why Maven?
Maven's primary goal is
to allow a developer to comprehend the complete state of a development effort
in the shortest period of time. In order to attain this goal there are several
areas of concern that Maven attempts to deal with:
- Making the build process easy
- Providing a uniform build
system
- Providing quality project
information
- Providing guidelines for best
practices development
- Allowing transparent migration
to new features
1-
Develop a web service maven project
·
In
command Line type to generate a web project with maven using this command :
mvn archetype:generate
-DgroupId=com.aam.jaxws.server -DartifactId=PersonManagementServer
-DarchetypeArtifactId=maven-archetype-webapp
·
Maven
has generated a folder project called PersonManagementServer
·
Add
Jaxws dependency to pom.xml
<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>com.aam.jaxws.server</groupId>
<artifactId>PersonManagementServer</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<name>PersonManagementServer
Maven Webapp</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>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>2.1.3</version>
</dependency>
</dependencies>
<build>
<finalName>PersonManagementServer</finalName>
</build>
</project>
|
·
In
command line and under /PersonManagementServer, type mvn
eclipse:eclipse to be able to import the
project into eclipse.
·
Import
the existing maven project to your workspace.
2- Develop a JAXWS web
service with SOAP 1.2
Contract-first approach
versus code-first approach
A good way to get
initiated into JAX-WS is to first develop a web service. You can develop a web
service using one of two approaches:
- Contract first: Start with
a WSDL contract, and generate a Java class to implement the service.
- Code first: Start with a Java
class, and use annotations to generate both a WSDL file and a Java
interface.
The contract-first WSDL
approach requires a good understanding of WSDL and XSD (XML Schema Definition)
for defining message formats. It's a good idea to start with the code-first
approach if you're fairly new to web services, which is what you'll use in this
tutorial to develop web services.
Code-first web services
development
Using the code-first
approach, you start with a Java class, or classes, that implements features you
want to expose as services. The code-first approach is particularly useful when
Java implementations are already available and you need to expose implementations
as services.
Requirements of a JAX-WS Endpoint
JAX-WS endpoints must follow these requirements :
·
The implementing
class must be annotated with either the javax.jws.WebService or the javax.jws.WebServiceProvider annotation.
·
The implementing
class may explicitly reference an SEI through the endpointInterface element of the @WebService annotation but is not required to do so. If no endpointInterface is specified in@WebService,
an SEI is implicitly defined for the implementing class.
·
The business
methods of the implementing class must be public and must not be declared static or final.
·
Business methods
that are exposed to web service clients must be annotated with javax.jws.WebMethod.
·
Business methods
that are exposed to web service clients must have JAXB-compatible parameters
and return types. See the list of JAXB default data type bindings athttp://docs.oracle.com/javaee/5/tutorial/doc/bnazq.html#bnazs.
·
The implementing
class must not be declared final and must not be abstract.
·
The implementing
class must have a default public constructor.
·
The implementing
class must not define the finalize method.
·
The implementing
class may use the javax.annotation.PostConstruct or the javax.annotation.PreDestroy annotations on its methods for lifecycle event callbacks.
2.1 Develop a Person Management web service
Let's start by creating
a person management web service that accepts CIN ID and generates person
information as a response. The code for the service is provided Listing 1-2-3-4.
This is a dummy implementation that prints the person CIN ID and number of
items at the console, then returns a dummy PersonOut response.
Listing 1 : File : PersonManagementService.java
package
com.aam.jaxws.server;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import
javax.jws.WebService;
import
javax.xml.ws.BindingType;
@WebService(endpointInterface
= "com.aam.jaxws.server.PersonManagement", serviceName = "PersonManagementService", targetNamespace =
"http://com.aam.jaxws.server/")
@BindingType(value = "http://java.sun.com/xml/ns/jaxws/2003/05/soap/bindings/HTTP/")
public class
PersonManagementService implements PersonManagement {
private static Map<String,
PersonOut> persons = new HashMap<String, PersonOut>() {
{put("p1", new PersonOut("p1", "aam", "aam", new Date()));}
{put("p2", new PersonOut("p2", "bob", "bob", new Date()));}
};
@Override
public PersonOut
findPersonByCIN(String CIN) throws PersonException {
return persons.get(CIN);
};
}
|
Listing 2 : File : PersonManagement.java
package
com.aam.jaxws.server;
import
javax.jws.WebParam;
import
javax.jws.WebService;
import
javax.jws.soap.SOAPBinding;
import
javax.jws.soap.SOAPBinding.Style;
import
javax.jws.soap.SOAPBinding.Use;
@WebService(name = "PersonManagementService")
@SOAPBinding(style = Style.DOCUMENT, use = Use.LITERAL)
public interface PersonManagement {
public PersonOut
findPersonByCIN(@WebParam(name = "CIN") String CIN) throws PersonException;
}
|
Listing 3 : File : PersonOut.java
package
com.aam.jaxws.server;
import java.util.Date;
public class PersonOut {
private String CIN;
private String name;
private String firstName;
private Date birthDate;
//very important to JAXB
public PersonOut() {
}
public PersonOut(String cIN, String name,
String firstName, Date birthDate) {
super();
CIN = cIN;
this.name = name;
this.firstName = firstName;
this.birthDate = birthDate;
}
/* Getters &
Setters */
}
|
Listing 4 : File : PersonException.java
package
com.aam.jaxws.server;
public class PersonException extends Exception {
}
|
@WebService (name = "PersonManagementService")
The starting point for
developing a JAX-WS web service is a Java class annotated with the javax.jws.WebService annotation.
The JAX-WS annotations used are part of the Web Services Metadata for the Java
Platform specification (JSR-181). As you have probably noticed, PersonManagementService is annotated with the WebService annotation, which
defines the class as a web service endpoint.
@BindingType(value = "http://java.sun.com/xml/ns/jaxws/2003/05/soap/bindings/HTTP/")
Using this annotation we
can specify witch binding we want use (Default SOAP 1.1) and in our case is
SOAP 1.2.
@SOAPBinding(style = Style.DOCUMENT, use = Use.LITERAL)
The @SOAPBinding annotation
is defined by the javax.jws.soap.SOAPBinding interface. It provides
details about the SOAP binding used by the service when it is deployed. If the @SOAPBinding annotation
is not specified, a service is published using a wrapped doc/literal SOAP
binding.
After the web service is
implemented, you need to generate any artifacts required to deploy the service,
then package the web service as a deployed artifact—typically as a WAR file—and
deploy the WAR file to any compliant server that supports the JAX-WS 2.0
specification. Typical artifacts generated are classes that provide conversion
of Java objects to XML, and the WSDL file and XSD schema based on the service
interface.
2.2 Generate web services artifacts with wsgen
2.2 Generate web services artifacts with wsgen
To generate artifacts we
will use maven wsgen plugin, let’s update our pom.xml by adding this build fragment and execute mvn clean install command line under
the PersonManagementServer folder.
<build>
<finalName>PersonManagementServer</finalName>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>wsgen</goal>
</goals>
</execution>
</executions>
<configuration>
<sei>com.aam.jaxws.server.PersonManagementService</sei>
<genWsdl>true</genWsdl>
<keep>true</keep>
<resourceDestDir>${basedir}/src/main/webapp/WEB-INF/wsdl</resourceDestDir>
<sourceDestDir>${basedir}/src/main/java</sourceDestDir>
</configuration>
</plugin>
</plugins>
</build>
|
The wsgen plugin has generated artifacts and wsdl :
2.3 Update web.xml :
Update web.xml deployment
descriptor for the deployment. Defines WSServletContextListener as
listener class, WSServlet as your PersonManagementService servlet.
<web-app>
<display-name>Archetype Created
Web Application</display-name>
<listener>
<listener-class>
com.sun.xml.ws.transport.http.servlet.WSServletContextListener </listener-class>
</listener>
<servlet>
<servlet-name>PersonManagementService</servlet-name>
<servlet-class>
com.sun.xml.ws.transport.http.servlet.WSServlet </servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>PersonManagementService</servlet-name>
<url-pattern>/PersonManagementService</url-pattern>
</servlet-mapping>
<mime-mapping>
<extension>txt</extension>
<mime-type>text/xml</mime-type>
</mime-mapping>
</web-app>
|
2.4 Create web service deployment descriptor sun-jaxws.xml:
Create a web service deployment descriptor, which is also known as JAX-WS RI deployment descriptor – sun-jaxws.xml.
<?xml version="1.0"
encoding="UTF-8"?>
<endpoints version="2.0"
xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime">
<endpoint implementation="com.aam.jaxws.server.PersonManagementService"
name="PersonManagementService"
url-pattern="/PersonManagementService"
/>
</endpoints>
|
2.5 Deployment :
Copy the generated WAR file to {$TOMCAT}/webapps/ folder
and start the Tomcat server.
29-oct.-2012 11:13:59
org.apache.tomcat.util.digester.SetPropertiesRule begin
29-oct.-2012 11:13:59
org.apache.coyote.http11.Http11Protocol init
INFO: Initialisation de Coyote HTTP/1.1 sur http-8080
29-oct.-2012 11:13:59
org.apache.catalina.startup.Catalina load
INFO: Initialization
processed in 364 ms
29-oct.-2012 11:13:59
org.apache.catalina.core.StandardService start
INFO: Démarrage du
service Catalina
29-oct.-2012 11:13:59
org.apache.catalina.core.StandardEngine start
INFO: Starting
Servlet Engine: Apache Tomcat/6.0.35
29-oct.-2012 11:13:59
com.sun.xml.ws.transport.http.servlet.WSServletContextListener
contextInitialized
INFO: WSSERVLET12:
JAX-WS context listener initializing
29-oct.-2012 11:14:00
com.sun.xml.ws.transport.http.servlet.WSServletDelegate <init>
INFO: WSSERVLET14:
JAX-WS servlet initializing
29-oct.-2012 11:14:00
org.apache.coyote.http11.Http11Protocol start
INFO: Démarrage de Coyote HTTP/1.1 sur http-8080
29-oct.-2012 11:14:00
org.apache.jk.common.ChannelSocket init
INFO: JK: ajp13
listening on /0.0.0.0:8009
29-oct.-2012 11:14:00
org.apache.jk.server.JkMain start
INFO: Jk running ID=0
time=0/19 config=null
29-oct.-2012 11:14:00
org.apache.catalina.startup.Catalina start
INFO: Server startup
in 1088 ms
|
For testing, you can
access this URL http://localhost:8080/PersonManagementServer/PersonManagementService
, if you see following page, it means web services are deploy
successfully.
To get the wsdl you can access http://localhost:8080/PersonManagementServer/PersonManagementService?wsdl
:
<?xml version="1.0"
encoding="UTF-8" standalone="yes"?>
<!-- Generated
by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI
2.1.3-b02-. -->
<definitions targetNamespace="http://com.aam.jaxws.server/"
name="PersonManagementService" xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://com.aam.jaxws.server/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/">
<import namespace="http://server.jaxws.aam.com/"
location="PersonManagementServicePortType.wsdl"/>
<binding name="PersonManagementServicePortBinding"
type="ns1:PersonManagementService" xmlns:ns1="http://server.jaxws.aam.com/">
<soap12:binding transport="http://www.w3.org/2003/05/soap/bindings/HTTP/"
style="document"/>
<operation name="findPersonByCIN">
<soap12:operation soapAction=""/>
<input>
<soap12:body use="literal"/>
</input>
<output>
<soap12:body use="literal"/>
</output>
<fault name="PersonException">
<soap12:fault name="PersonException"
use="literal"/>
</fault>
</operation>
</binding>
<service name="PersonManagementService">
<port name="PersonManagementServicePort"
binding="tns:PersonManagementServicePortBinding">
<soap12:address location="REPLACE_WITH_ACTUAL_URL"/>
</port>
</service>
</definitions>
|
2.6 Test with SOAPUI 4.5.1 :
You have now successfully created and published
your web service and Testd it using Soap UI.
You can use this links to Download source code
After downloading, execute mvn clean install command and import the prjectto your eclipse. You can after deploy the WebService in your favorite server and use Soap UI or move on to the next article to generate a java client project using jaxws and maven
END.
Salut Aymen,
RépondreSupprimerGreat work !
Bien à toi
Hamdi
Merci Hamdi :) I hope it helps.
RépondreSupprimerMerci beacoup
RépondreSupprimerDe rien, you are welcome :)
SupprimerVery nice tutorial. I had some issues with deploying web services on tomcat but after this tutorial it's easy pie ;) Good job!
RépondreSupprimerHappy to know that it helps :)
Supprimernice tutorial but how can it be achieved with jms transportation.
RépondreSupprimerYes it can be by defining a JMS binding in the WSDL also some server specific configuration (JMS Template,JMS Connection factory,JMS Server,JMS Queue).
RépondreSupprimerHi,
RépondreSupprimerJust want to confirm should we annotate the PersonOut class as if I don't do so then the response generated is empty.
Nice tutorial, to the point. Thank you for sharing !
RépondreSupprimerNice job 7bib :-)
RépondreSupprimerNice tutorial. How would you handle soap inputs like this instead?:
RépondreSupprimerp1