Sunday, August 28, 2011

Layers versus Tiers

There is one question that is often confused in design/architectural considerations namely - Tiers versus Layers.
Here we try to analyze the difference between the 2.
Layers: A Layer is considered to be a discrete, orthogonal area of concern within an application. A layer generally would be a logical section of the code that deals with unique features. For example a persistence layer would deal with all the code related to database operations in a section of the code. This way it is easy to divide the work and isolate problems. If we have any change related to a database we know which part of the code gets affected and we can isolate the area of concern.
The other features of layers are:
1. Layers are conceptual boundaries and are not necessarily physically isolated. More often than not the layers would be placed in the same VM.
2. Thinking in layers can help conceptualize the flow through an application and help in more organized design.

Tiers: By contrast a tier is best thought of as a physical deployment of the layers. Thinking in tiers is more related to system administration and architectural decision making where it helps us decide what would be the different server, V.M. and other hardware requirements. Mostly multiple layers are mapped onto a tier.

The best example of a tiered architecture is a 3 tiered architecture where we deal with client-server-database.
In contrast the 3 layered architecture deals with the 3 layers in the form Controller-Service-DAO layers at the server side.


Tuesday, April 19, 2011

Simple JAX-WS Client example


    In my previous articles I have discussed server side code of a web service which deals essentially with publishing a web service. However in most of the business situation that one comes across the role is of a web service client rather than a web service provider. This articles deals with the creation of a web service client using JAX-WS.

    In JAX-WS clients are of 2 types. a) Static Clients b) Dynamic Clients.

Static Clients – The more commonly developed clients, these clients are generally developed by creating auto-generated code on the WSDL provided. These are specific to a WSDL hence the provider cannot be changed at runtime.

Dynamic Client – The lesser common of the two forms of clients, used when developing a client dynamically at runtime. This method is used when we may want to change our web service provider at runtime (or for REST services since they do not have a WSDL).

In this article we discuss the creation of a Static Client. The brief process of creation of a static client is highlighted below:

Step 1. Identify the WSDL location of the service provider

Step 2. Run the auto generate tool, to generate the artifacts/ stubs that are needed to create a web service client.

Step 3. Create the client code that will create the request object and then call the service using the stubs created in Step 2.

Let us try to create a sample code for a Web Service Client for the HelloWorld service that we created here. For my case, the service is deployed on Glassfish and the WSDL is located at the following location: http://localhost:8080/JAXWSHelloWorld/HelloWorld?wsdl

To create the stubs/artifacts use the wsimport command available with the web service provider (in my case Glassfish or Java 6). Though the name may vary with different providers the basic syntax normally remains the same. Run the command to create a list of artifacts as given below:

Command: wsimport -s src -keep -d build\classes -verbose -p com.jaxws.helloworld.client http://localhost:8080/JAXWSHelloWorld/HelloWorld?wsdl

The parameters / arguments which have been passed are:

ArgumentDescription
-s [folder]Location to place the generated .java source files
-d [folder]Location to place the generated class files
-keepInstructs wsimport to keep the generated source files and not delete them
-verboseTo output the trace logs in stdout (to debug / follow)
-p [package name]To use a custom package name for generated classes. The default value would be taken from the target namespace if this is not specified

 

On running the above command the following files are generated. Please note the files generated below will vary according to WSDL.

File NamePurpose
package-info.javaThis defines the mapping between the namespace and package name as an annotation
ObjectFactory.javaThis factory class which is used to create request and response objects.
HelloWorldEndpoint.javaThe SEI (Service Endpoint Interface) generated to map the WSDL port. It makes all the exposed operations available to the client.
HelloWorld.javaThe Service class which implements the code for the SEI, allowing us to call the remote server (web service provider) to get the response. This class takes the request in object form, marshals it into XML, sends the XML / SOAP to service, gets back the response as XML/SOAP, un-marshals it to an object and gives us back.
Greet.java

GreetResponse.java
The Request and Response objects that are created.

 

The above generated files are called stubs and are used to access the web service. A sample simple program to access the service is shown below:

public
class HelloWorldClient {

    @WebServiceRef(wsdlLocation="http://localhost:8080/JAXWSHelloWorld/HelloWorld?wsdl")

    private HelloWorldEndpoint helloWorld;


    public static void main(String[] args) {

        HelloWorldClient client = new HelloWorldClient();

        if(client.helloWorld==null){

            HelloWorld helloWrldService = new HelloWorld();

            client.helloWorld = helloWrldService.getHelloWorldEndpointPort();

        }

        String resp = client.helloWorld.greet("Aditya", "Keyal");

        System.out.println(resp);

    }

}

The above code is a standalone main program which is used to access the web service. There are few points to be noted here. The SEI member variable has an annotation @WebServiceRef added. If deployed in a web service container (i.e. if this piece of code was present in a Servlet instead of a standalone main program and the Servlet deployed in the same glassfish server as the service) then the SEI Implementation [HelloWorld.java] is used to automoatically look up the "Port" which is then injected through dependency injection. In this program since I have used a main program I had to create an instance of HelloWorld.java and assign the port to the SEI variable.

In the next article I will create a Dynamic client for the sample service.

Thursday, March 24, 2011

JAXWS annotations

In the previous post I discussed how to create a simple JAX-WS enabled web service. For accomplishing the same we used the following 2 annotations:

  1. @WebService
  2. @WebMethod

By using the above 2 annotations and a number of pre-defined defaults for annotations not added we were able to generate a WSDL mapping to the Java implementation. In case we wish to customize the WSDL generated, JAX-WS gives us a set of annotations that can be used. The different annotations come from 3 different JSR's and can be used to customize the different parts of the WSDL. The different JSR's are:

  1. Web Services Metadata Annotations (JSR 181)
  2. JAX-WS Annotations (JSR 224)
  3. JAX-WS Common Annotations (JSR 250)

One point worth noting here is that these annotations are useful in customizing the WSDL file but not the JAXB binding part of it. If we want to customize the JAXB binding (i.e. the XSD Schema details) we need to add JAXB annotations on the JAXB classes (request/response parameters).

To get a list of each of the annotations in JAXWS please refer the following site.

Wednesday, March 16, 2011

JAX-WS Hello World Example

    In this article I provide a step-by-step illustrated example on creating a simple Hell World Service example by using JAX-WS.

Service – Hello World service exposing one method called greet. The method implementation accepts a first name and a last name and returns a greeting string.

Stack – JAX-WS with Glassfish Server, Eclipse for development.



Procedure:

Step 1: Create a Dynamic Web Project in eclipse, with the name "JAXWSHelloWorld".





Step 2: Create a simple implementation class called com.jaxws.example.HelloWorldEndpoint. It will contain a single public method called greet() which accepts 2 strings (firstname and lastName) and returns a greeting message. Then annotate the class with the @WebService annotation and the greet method with @WebMethod annotation.

The @WebService has the serviceName attribute. The value of this attribute is the name of the service in the WSDL and also the URL at which the service is available.

The @WebMethod has the attribute operationName. The value of this attribute is the name of the operation defined in the WSDL.

Please note these are not mandatory and are used only for reference/ease of debugging.

The sample source is given below.



Note: The values attributes of annotation are optional. More details on what they mean will be explained later.


Step 3: Create the related resources (JAXB binding files, WSDL and schema files and corresponding classes). For the run the wsgen bat available with JDK 1.6 or Glassfish with the following parameters:

wsgen –verbose –cp build/classes –s src –wsdl –r WebContent\WEB-INF\wsdl –d build\classes com.jaxws.example.HelloWorldEndpoint

-verbose : prints the operation being executed

- cp <folder> : the location of the base folder where the class file of the Endpoint (HelloWorldEndpoint) is located.

-s <folder> : the location where the generated source files (JAXB binding) are stored

-wsdl : specifies that the WSDL should be generated

-r <folder> : the location of the folder where the resources/artifacts will be generated

-d <folder> : the location of the folder where the generated class files (of JAXB Binding and JAXWS files) will be kept.





Step 4: Deploy the application on the server (Glassfish). To deploy the application, import the glassfish server into eclipse and then just simply right click the project choose Run As > Server. When the server starts monitor the logs. In the logs you will see a line about the WebService Endpoint successfully deployed and the location of the endpoint.

Note: The location is of the format -> http://url:portNumber/applicationName/serviceName[Of Endpoint]





Step 5: The web service is deployed. Hit the URL of the endpoint specified during deployment [http://locahost:8080/JAXWSHelloWorld/HelloWorld] in my case. You should be able to see a dynamically generated page detailing the service and operations exposed.






Step 6: The Web service is now deployed. To confirm check the WSDL deployed the link for which is available on the generated screen. [http://localhost:8080/JAXWSHelloWorld/HelloWorld?wsdl] in my case.



This is a generated WSDL by the JAXWS implementation (Glassfish in my case). The Service is of the type document/literal [wrapped]. The XSD is also available.

Step 7: To test the service, use Web Service Explorer available with eclipse or SOAPUI and set the endpoint to the location of the endpoint. The sample request response in my case are as given below.

 Request:  
 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://example.jaxws.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">  
   <soapenv:Body>  
    <q0:greet>  
      <arg0>Aditya</arg0>  
      <arg1>Keyal</arg1>  
    </q0:greet>  
   </soapenv:Body>  
 </soapenv:Envelope>  

 Response  
 <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">  
   <S:Body>  
    <ns2:greetResponse xmlns:ns2="http://example.jaxws.com/">  
      <return>Hello AdityaKeyal</return>  
    </ns2:greetResponse>  
   </S:Body>  
 </S:Envelope>  


The above example is available for download here. It is a complete eclipse project. Just download and import into eclipse and build then deploy on Glassfish for it to run.