WELCOME Abdennour : Software engineer

May 16, 2012

4.Develop Web services extended With Jax-Ws :Part1




JAX-ws  is a set of APIs for creating web services in XML format (SOAP). JAX-WS provides many annotation to simplify the development and deployment for both web service clients and web service providers (endpoints)..


1.JAX-WS Generalities 
2.Server Developpement
        a.Bottom -> up
                 Full Example with Eclipse Helios from scratch:
        c.Top ->Down
                 Example With Eclipse (Apache Tomcat+Axis) : 
3. Client Developpement : 
4.Annotations:
5.wsimport vs  wsgen:
6.Handler:
7.Java6 &EJB



1JAX-WS Generalities : 
-Java API for XML Web Services (JAX-WS), is a set of APIs for creating web services in XML format (SOAP).
-JAX-WS base on POJO(Plain old java object)
-JAX-WS provides many annotations to simplify the development and deployment for both web service clients and web service providers (endpoints).

-It provides an independent description of the language and platform .
=>Ensure independence of Prtocol (SOAP), of Transport(HTTP).

Two ways to develop a Web Service with JAX-WS :
    1)From WSDL Document (Top/Down) :2)From POJO (Bottom/up) : 
    

     1)From WSDL Document (Top/Down) :  
    *Generation of Java Classes(JAXB & Skeleton(squlette) of WS) by using wsimport .
      *Accomplish the Skeleton of implementation Class .
      *Compile >Deploy>Test
     2)From POJO (Bottom/up) : 
       *Create & Annotate POJO
       *Compile>Deploy>Test
       *WSDL Document is generated automatically .




2.Server Developpement
-WSDL : Web Service Des
        Bottom -> up

-1)Create Class Pojo .
  2)Add @WebService Annotation.
  3)Deploy  Application on :App Server or JAVA SE6 Directly.
   4)WSDL is generate under :URL: http://monserveur/app/Service?WSDL 
 5)Methods OverLoaded is not Supported.
EXAMPLE1: 
1)Web Service : 
package slm.abdennour.jaxws;

import javax.jws.WebService;

@WebService
public class HelloService {
  public String makeHello(String value){
    return "Peace upon to you "+value;
  }
  public String simpleHello(){
    return "Peace upon to everybody";
  }
}

2)Publisher : 
package slm.abdennour.jaxws;

import javax.xml.ws.Endpoint;
/**
*
* @author عبد النور التومي Abdennour
* @since 15 mai 2012
*/
public class Publisher {

/**
* @param args
*/
   public static void main(String[] args) {
      Endpoint.publish("http://localhost:8080/jaxws/hello", new HelloService());

   }

}
3)URL of wsdl  : 
<definitions targetNamespace="http://jaxws.abdennour.slm/" name="HelloServiceService">

<types>....</types>

<message name="makeHello">....</message>

<message name="makeHelloResponse">..</message>

<message name="simpleHello">...</message>

<message name="simpleHelloResponse">...</message>
<portType name="HelloService">...</portType>
<binding name="HelloServicePortBinding" type="tns:HelloService">......</binding>
<service name="HelloServiceService">......</service>
</definitions>

EXAMPLE2:Parameterize WS  HelloWorld :
1)Use Interface to define WS parameters :
package slm.abdennour.jaxws.facade;

import javax.jws.WebMethod;

import javax.jws.WebParam;

import javax.jws.WebResult;

import javax.jws.WebService;

import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import javax.jws.soap.SOAPBinding.Use;
/**
*
* @author عبد النور التومي Abdennour
* @since 15 mai 2012
*/
@WebService(name = "IHelloService", targetNamespace = "http://facade.jaxws.abdennour.slm/")
@SOAPBinding(style = Style.RPC, use = Use.LITERAL)
public interface IHelloService {
    @WebMethod(operationName = "makeHello")
    @WebResult(name = "helloResult")
    public String makeHello(@WebParam(name = "value") String value);

    @WebMethod(operationName = "simpleHello")
    @WebResult(name = "helloResult")
    public String simpleHello();

}

2)Implementation Of  Web Srevice Interface : 
package slm.abdennour.jaxws.impl;
import javax.jws.WebService;
import slm.abdennour.jaxws.facade.IHelloService;
/**
*
* @author عبد النور التومي Abdennour
* @since 15 mai 2012
*/
@WebService(endpointInterface = "slm.abdennour.jaxws.facade.IHelloService", serviceName = "HelloWorld", portName = "HelloWorldPort")
public class HelloServiceImpl implements IHelloService {

    @Override
    public String makeHello(String value) {
        return "Peace upon to " + value;
    }

    @Override
    public String simpleHello() {
        return "Peace upon to everyBody";
    }

}



3°WSDL Generated : 
<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://impl.jaxws.abdennour.slm/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://impl.jaxws.abdennour.slm/"
name="HelloWorld">
<import namespace="http://facade.jaxws.abdennour.slm/"
location="http://localhost:8080/helloWithParameter?wsdl=1"></import>
<binding xmlns:ns1="http://facade.jaxws.abdennour.slm/" name="HelloWorldPortBinding"
type="ns1:IHelloService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="rpc"></soap:binding>
<operation name="makeHello">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal" namespace="http://facade.jaxws.abdennour.slm/"></soap:body>
</input>
<output>
<soap:body use="literal" namespace="http://facade.jaxws.abdennour.slm/"></soap:body>
</output>
</operation>
<operation name="simpleHello">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal" namespace="http://facade.jaxws.abdennour.slm/"></soap:body>
</input>
<output>
<soap:body use="literal" namespace="http://facade.jaxws.abdennour.slm/"></soap:body>
</output>
</operation>
</binding>
<service name="HelloWorld">
<port name="HelloWorldPort" binding="tns:HelloWorldPortBinding">
<soap:address location="http://localhost:8080/helloWithParameter"></soap:address>
</port>
</service>
</definitions>







  ===============================
-wsgen tools generate artifacts(jaxb,wsdl) from java classes annotated via JAX-WS.
1)Generate Java Class+JAXB Annotations : 
wsgen –cp . slm.abdennour.jaxws.impl.IHelloWorldService –keep 
2)Generate WSDL document : 
 wsgen –cp . slm.abdennour.jaxws.impl.IHelloWorldService –keep - wsdl


JAX-WS & MAVEN : 
<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.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>wsgen</goal>
</goals>
<configuration>
<sei>fr.ensma.lisi.helloworldquietwebservice.HelloWorldService</sei>
<genWsdl>true</genWsdl>
<keep>true</keep>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>maven-repository.dev.java.net</id>
<name>Java.net Repository for Maven 1</name>
<url>http://download.java.net/maven/1/</url>
<layout>legacy</layout>
</repository>
<repository>
<id>maven2-repository.dev.java.net</id>
<name>Java.net Repository for Maven 2</name>
<url>http://download.java.net/maven/2/</url>
</repository>
</repositories>


* Web Service Deployed By Web Application : 
   1)Container Respect JSR 109: 
              Example : GlassFish .

    2/Container need  WS Management by Servlet : 
               =>Explicit Configuration of Web Service .
             Example : Tomcat .
          The Required Configuration : 
             a.in web.xml => Specify Servlet which ensures the Management .
             b.sun-jaxws.xml =>perform Relation between application context & WS Class.
  * Structure of Web Application Provide WS:  
       Example  Configuration of web.xml in Tomcat: 
   <?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<description>HelloWorld</description>
<display-name>HelloWorld</display-name>
<listener>
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet>
<description>JAX-WS endpoint - helloworld</description>
<display-name>helloworld</display-name>
<servlet-name>helloworld</servlet-name>
<!-- Servlet ensure the management of Web Service -->


<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>helloworld</servlet-name>
<url-pattern>/helloworld</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
</web-app>
  Example  Configuration of sun-jaxws.xml in Tomcat: 

<!-- Link Servlet(/helloWorld) of Ws management to Class which implement W.Service -->


<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime'
version='2.0'>
   <endpoint name='helloworld'
implementation='slm.abdennour.jaxws.impl.HelloServiceImpl'
url-pattern='/helloworld' />
</endpoints> 
 Full Example with Eclipse Helios from scratch:
 Step 1 : 
  Install WTP (Web Tools PlateForm)
    if you have Helios :  http://download.eclipse.org/webtools/repository/helios/
    if you have indigo :  http://download.eclipse.org/webtools/repository/indigo/
      Step 2 : 
            -Downlaod apache-tomcat-7.0.12 for Example .
            -Add it as Server (Window>Show View >Servers) then Right Click Add Server ....
      Step 3: 
            -New :Dynamic Web Project : 
      Step 4 : 
            -New Class : HelloServiceImpl  .
          package slm.abdennour.ws.cxf;
            /**
              * @author عبد النور Abdennour
              * @since 16 mai 2012
            */
          public class HelloServiceImpl {
              public String sayHello(String name) {
                   return "Peace upon " + name; 
                }

              public String simpleHello() {
                  return "Peace upon to you";
                }
           }

      Step 5 : 
            -Retrieve WSDL from this POJO Class : 


    Step 6:
       -A WSDL Document has been generated : 
 - Eclipse provides us a GUI for WSDL : 
    => indeed , We have Abstract Part & Concret Part  of WSDL Document: 


        Top ->Down(Server)[from WSDL]
Porcess OF Top/Down : 


 STEPS : 
=>WSDL is accessible via url or physical file
1 =>wsimport  used to generate WS Skeleton (Class linked to JAXB , WS interface discribe the PortType)
2=>Creation of POJO annoted by @WebService & Specify the place of PortType Interface . 
3=>Deploy Application . 
4=> The rest is the same as Bottom/up Method
 Example With Eclipse (Apache Tomcat+Axis) : 
Step1 : 
     Create new Project . 
Step2 : 
     Right Click >New >Web Service . 
  Step3
      -Choose Web Service Type : Top Down Java bean Web Service .
      -Put an URL of wsdl : for Example : WSDL provided by Eclipse .
 http://www.eclipse.org/webtools/jst/components/ws/1.5/tutorials/TopDownWebService/srcfiles/AreaService.wsdl


    Step4:
      Start Server & Generate Skeleton : 




  Generated Files: 

     WSDL & POJO Class : 
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://tempuri.org/AreaService/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="AreaService" targetNamespace="http://tempuri.org/AreaService/">
<wsdl:types>
<xsd:schema targetNamespace="http://tempuri.org/AreaService/">
<xsd:element name="area" type="xsd:float"/>
<xsd:element name="parameters" type="tns:dimensions"/>
<xsd:complexType name="dimensions">
<xsd:sequence>
<xsd:element name="width" type="xsd:float"/>
<xsd:element name="height" type="xsd:float"/>
</xsd:sequence>
</xsd:complexType>

</xsd:schema>
</wsdl:types>
<wsdl:message name="CalculateRectAreaResponse">
<wsdl:part element="tns:area" name="area"/>
</wsdl:message>
<wsdl:message name="CalculateRectAreaRequest">
<wsdl:part element="tns:parameters" name="parameters"/>
</wsdl:message>
<wsdl:portType name="AreaService">
<wsdl:operation name="CalculateRectArea">
<wsdl:input message="tns:CalculateRectAreaRequest"/>
<wsdl:output message="tns:CalculateRectAreaResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="AreaServiceSOAP" type="tns:AreaService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="CalculateRectArea">
<soap:operation soapAction="http://tempuri.org/AreaService/NewOperation"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="AreaService">
<wsdl:port binding="tns:AreaServiceSOAP" name="AreaServiceSOAP">
<soap:address location="http://localhost:8080/jaxwsFromWSDL/services/AreaServiceSOAP"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>


package org.tempuri.AreaService;


public class Dimensions implements java.io.Serializable {
private float width;


private float height;


public Dimensions() {
}


public Dimensions(
float width,
float height) {
this.width = width;
this.height = height;
}
public float getWidth() {
return width;
….........

Our Web Service is : public class AreaServiceSOAPImpl  include   calculateRectArea Method
  EXAMPLE 2: wsimport & Maven2 : 
   Pom.xml 
 ===

<project>
...
<dependencies>
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>2.1.7 </version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<wsdlDirectory>${basedir}/src/wsdl </wsdlDirectory>
<genWsdl>true</genWsdl>
<keep>true</keep>
<packageName>fr.ensma.lisi.notebookwebservicefromwsdl</packageName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>maven-repository.dev.java.net </id>
<name>Java.net Repository for Maven 1 </name>
<url>http://download.java.net/maven/1/ </url>
<layout>legacy</layout>
</repository>
<repository>
<id>maven2-repository.dev.java.net</id>
<name>Java.net Repository for Maven 2</name>
<url>http://download.java.net/maven/2/</url>
</repository>
</repositories>
</project>

==
f
3. Client Developpement : 


-Client Application Can be :
              * Java SE(Swing,RPC Eclipse)   or    
               * JEE &EJB(Jsp ,Servlet..)
-Client manipulates Java Code Only => XML Code is Hidden(JAXB) .
 -Client retrieve Port via : get<ServiceName>Port() .
-Code generation is the same such as Server Top/Down Approch.


Example : 
  i.Web Service Server : 
      
   ii.Web Service Client :  
=>Retrieve a port  via getHelloServImplPort()
=>Call Method <port>.<Method>
 iii.Web Service Client  Synchron to Web Service Server: 
==>it's class HelloServImpl.java
=>5000 (5sec) :that's means that the processing(traitement) of Web Service can take some time
=>If the response time of the call to an operation of a WebService is long, predict an asynchronous call .
=>JAX-WS allows to call Web services asynchronously if the information is specified in the binding
=>When generating Classes via wsimport , a file provides binding as follow : 

<?xml version="1.0" encoding="ISO-8859-1"?>
<bindings
wsdlLocation="http://localhost:8080/helloWebService/HelloServImpl?wsdl"
xmlns="http://java.sun.com/xml/ns/jaxws" >
<enableAsyncMapping>true</enableAsyncMapping>
</bindings>
iv.Asynchron Client  to WS HelloServ : 

slm.abdennour.HelloServImpl_Service service = new slm.abdennour.HelloServImpl_Service();
slm.abdennour.HelloServImpl port = service.getHelloServImplPort();

String name = "Abdennour";
port.sayHello(name, new AsyncHandler<SayHello>() {

      public void handleResponse(Response<SayHello> res) {
                if (!res.isCancelled() && res.isDone()) {
                   try {
                        SayHello value = res.get();
                       // System.out.println(value.isSayHello());
                     } catch (Exception e) {
                     e.printStackTrace();
                     }
                 }
     }
 });
 try {
      Thread.sleep(10000);
 } catch (InterruptedException e) {
     e.printStackTrace();
 }
  System.out.println("Finish");
 }
d

4.Annotations:
# @ WebService: POJO that implements a Web Service (it's needed )
# @ WebMethod: Setting an operation
# @ WebParam: Setting a message
# @ WebResult: Set an output message
# @ WebFault: Setting a message fault
* Annotate Java Class =>to define implementation of Web Service .
*Annotate Java Interface=>to define a description of Web Service .

Attributes of the @ WebService annotation:
a# String name: name of the Web Service
b# EndpointInterface String: name of the interface describing the Web Service
c# String portname: port
d# String serviceName name of service Web Service
e# String targetNamespace: the namespace of Web Service
f# String wsdlLocation: the location of the WSDL describing the Web Service

Attributes of the annotation@ WebMethod
=>Class Method ---> Web Service Operation # String action: the action of the operation. In the case of a SOAP binding, this determines the value of the SOAP Action.
# Boolean exclude: specifies that the method should not be exposed as an operation.Do not use in a Java interface.
# String operationName: specifies the name of the attribute namedéfini in the operation element of the WSDL document.


Attributes of the annotation@ WebParam 
=>Describes the relationship between ::
                        an input parameter of a method && a message from an operation
# Boolean header: specifies whether the parameter must be passed in the message header (true) or in the body (false)
# WebParam.Mode mode: specifies the type of access to the parameter (IN, OUT or INOUT)
# String name: name of the parameter
# PartName String: name of wsdl: part representing this parameter
# String targetNamespace: namespace of this parameter .
(we have also @ WebResult  :the same attributes as @ WebParam expect mode)

5.wsimport vs  wsgen:
- The wsimport tool is used to parse an existing Web Services Description Language (WSDL) file and generate required files (JAX-WS portable artifacts) for web service client to access the published web services. (it's available in $JDK/bin)
-The wsgen tool is used to parse an existing web service implementation class and generates required files (JAX-WS portable artifacts) for web service deployment.
wsimport tool Example : 
  i.Server -Publish Web Service - WSDL  :
  ii.Client - Access the published Service:
$wsimport -keep -verbose http://localhost:8080/helloWebService/HelloServImpl?wsdl


wsgen Example : 

Use cases

2 common use cases for wsgen tool :
  1. Generates JAX-WS portable artifacts (Java files) for web service deployment.
  2. Generates WSDL and xsd files, for testing or web service client development.
Let’s see a web service implementation class, quite simple, just a method to return a string.
File : ServerInfo.java
package slm.abdennour.ws;
 
import javax.jws.WebMethod;
import javax.jws.WebService;
 
@WebService
public class ServerInfo{
 
 @WebMethod
 public String getIpAddress() {
 
  return "10.10.10.10";
 
 }
 
}

1. Generates JAX-WS portable artifacts (Java files)

To generate all the JAX-WS portable artifacts for above web service implementation class (ServerInfo.java), use following command :
Command : wsgen usage
D:\>wsgen -verbose -keep -cp . slm.abdennour.ws.ServerInfo
 
Note:   ap round: 1
[ProcessedMethods Class: slm.abdennour.ws.ServerInfo]
[should process method: getIpAddress hasWebMethods: true ]
[endpointReferencesInterface: false]
[declaring class has WebSevice: true]
[returning: true]
[WrapperGen - method: getIpAddress()]
[method.getDeclaringType(): slm.abdennour.ws.ServerInfo]
[requestWrapper: slm.abdennour.ws.jaxws.GetIpAddress]
[ProcessedMethods Class: java.lang.Object]
slm\abdennour\ws\jaxws\GetIpAddress.java
slm\abdennour\ws\jaxws\GetIpAddressResponse.java
Note:   ap round: 2
In this case, it generated four files :
  1. slm\abdennour\ws\jaxws\GetIpAddress.java
  2. slm\abdennour\ws\jaxws\GetIpAddress.class
  3. slm\abdennour\ws\jaxws\GetIpAddressResponse.java
  4. slm\abdennour\ws\jaxws\GetIpAddressResponse.class




6.Handler:
- See Part2
7.Java6 &EJB
-See Part3




1 comment: