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:

  1. The Spring Framework is a lightweight framework for developing Java enterprise applications. It provides high performing, easily testable and reusable code. Spring handles the infrastructure as the underlying framework so that you can focus on your application.Spring is modular in design, thereby making creation, handling and linking of individual components so much easier. Spring implements Model View Container(MVC) design pattern.
    spring custom validator example

    ReplyDelete