Hi, I am looking for Spring/Summer - 2015 Internships. I am also interested in full time opportunities starting June 2015. My Resume

Search This Blog

Loading...

Thursday, 4 April 2013

Learning web services

In the various programming environments supported by Java, I have found web-services to be the most difficult to penetrate (That and JNDI) . The thing is there are several web-service providers in the Java community. They all make various claims, add to already vague terminology and almost always leave a novice reader confused.
So when I got a chance to implement web services using Spring's web service framework, I was pleasantly surprised with the well explained Spring docs. And while learning some cool stuff, I also realized that Spring web services is quite different from some of the other implementations.
So when I got the chance today, I decided  to do some investigation on few of these frameworks. I have earlier blogged on how Spring allows us to expose our application as a web service
Spring's web service implementation is not related to JAX-WS. Spring's implementation as we saw, only supports contract first development. There are several advantages to the same. In the words of Spring web services creator Arjen Poutsma
 "lot of the interoperability issues that people have with Web services disappear when they use a contract-first development style. That is why contract-first is generally considered to be a best practice. You are basically designing a XML API: the fact that you implement that API using Java is just an implementation detail which no client should care about. 
Secondly, Spring Web Services provides a loose coupling between contract and implementation: there is no wsdl2java tool which directly ties the contract to a class; instead, you implement endpoints which handle the incoming XML in any way you want to (DOM, SAX, StAX, or even XML marshaling techniques such as JAXB, Castor, JIBX, or XMLBeans). The way you map incoming request to the endpoints is completely up to you: by default, we supply mappings that are based on message content, or the SOAPAction header. The main idea is that you're not handling method calls, but rather XML messages" 
While contract first development has its strong points, there may be scenarios where you would like to try a code first style. With Spring this is not possible. Also Spring does not implement JAX-WS.
What is JAX-WS ?
The Java API for XML Web Services (JAX-WS) is a Java programming language API for creating web service. Just as we have JDBC as a standard API for interacting with various databases - something that the different database vendors implement, we have JAX-WS as the standard for creating web-services. JAX-WS is implemented by various vendors including:
  • JAX-WS Reference Implementation (RI) 
  • Apache CXF 
  • JBossWS 
  • GlassFish Metro 
  • Apache Axis2 
Each of these implementations have their own peculiarities, additional functionalities, useful tools, tips and tricks. JAX-WS Reference Implementation (RI) is something that is available in Java SE itself. In our JRE library. So to create a webservice we do not need to have a server installed and a war deployed. From the net:
One justification for including JAX-WS 2.0 as part of Java SE 6.0 instead of Java EE 5 is that web service delivery with JAX-WS 2.0 does not require a servlet or EJB container. This makes HTTP more or less an equal peer of RMI as an intrinsic protocol for distributed computing on the Java platform, and further extends the reach of web service
The related classes of this internal server can be found in com.sun.net.httpserver package. This means that we can run web services with just a java implementation. Of course all this is a part of the RI and we probably won't find the RI implementation used in industry applications. However RI does have some advantages:
  • Useful if we do not need the full power of a commercial HTTP server and servlet or EJB container 
  • The Endpoint class provides a convenient mechanism for components in software or systems in tightly controlled environment to easily communicate through web services. 
  • Easy to prototype and to develop production web services to be finally deployed in Java EE containers. 
  • Can be used to mock or simulate web services,allowing us to decouple client development and test from service delivery 
So what of the remaining implementations?
Metro was developed using the same code base of RI. CXF is an Apache implementation that implementation that supports a variety of protocols including JAX-WS. It has in fact been coded using Spring. JBossWS is the Web Services Framework for the JBoss application server. Axis2 is another Apache project that enjoys considerable support. There are several other providers too. This link gives a much more detailed comparison of the same.
With the whole variety available I decided to start with the RI implementation itself. Create a simple code first webservice. I created a simple project in eclipse.
The first step was to create a service.
@WebService()
public interface IEchoService {
    
    /**
     * Method will echo back the received input
     * @param message
     * @return {@link String}
     */
    public String echo(String message);
}
The implementation class for the same is:
@WebService(endpointInterface = "com.sample.service.IEchoService",
 targetNamespace = "http://www.sample.com/service")
public class EchoService implements IEchoService {
    @WebMethod
    @Override
    public String echo(String message) {
        System.out.println("received input " + message);
        return message;
    }
}
This is the class that we have exposed as a webservice. The WebService annotation indicates the interface is to be used as the SEI (Endpoint for the service) and also specifies the target namespace for all xml entities associated with this webservice.
Now that the service has been created we need to publish it. As discussed earlier the Java SE includes a small server implementation that can be used to publish the webservice. We do not need any server implementation for this purpose.
public static void main(String[] args) {
    Endpoint endpoint = Endpoint.publish("http://localhost:9090/service/echo",
                   new EchoService());
    System.out.println("Webservice published via endpoint " + endpoint);
}
As seen above publishing our webservice to a particular URL is single line of code. If we were to run this then the console indicates the below:
Mar 26, 2013 3:35:16 PM com.sun.xml.internal.ws.model.RuntimeModeler getRequestWrapperClass
INFO: Dynamically creating request wrapper Class com.sample.service.jaxws.Echo
Mar 26, 2013 3:35:16 PM com.sun.xml.internal.ws.model.RuntimeModeler getResponseWrapperClass
INFO: Dynamically creating response wrapper bean Class com.sample.service.jaxws.EchoResponse
Webservice published via endpoint com.sun.xml.internal.ws.transport.http.server.EndpointImpl@22ab57
As seen, the request and response classes that we needed for the webservice are automatically generated by the RI.
I checked in the bin folder:
If we need to see the source code we can use the wsgen tool from JDK. The wsdl for the webservice can be accessed at http://localhost:9090/service/echo?wsdl
The next step is to test the webservice. I decided to create a java client for the same. For a java client we would need the stubs to be available. Also the JAXB objects of the schema – this helps the client avoid dealing in XML.
JDK includes the wsimport tool. Running the below command on the prompt
wsimport http://localhost:9090/helloservice/hello?wsdl
results in a host of classes being created :
The Echo and EchoResponse are used to represent the web service request and response. The ObjectFactory class includes this code. The Interface has been made available at the client too. The client code now can use the request and response wrappers to test the service
public static void main(String[] args) {
        EchoServiceService service = new EchoServiceService();
        
         System.out.println("Retrieving the port from  the following service: " + service);
         for (Iterator<QName> iterator = service.getPorts(); iterator.hasNext();) {
             QName type = (QName) iterator.next();
                System.out.println(type);
            }
         IEchoService port = service.getEchoServicePort();
         System.out.println(port.echo("Are you alive"));
    }
The code initially displays all the ports available at the service. It then gets access to the stub and makes the call. The result is as below:
Retrieving the port from  the following service: com.sample.service.EchoServiceService@1d85f79
{http://www.sample.com/service}EchoServicePort
Are you alive
That completes an RI based implementation of a JAX-WS code first web-service. The same is not available in Spring web services.
References:
http://www.infoq.com/articles/arjen-poutsma-spring-ws 
http://docs.oracle.com/javaee/5/tutorial/doc/bnayn.html
http://today.java.net/pub/a/today/2007/07/03/jax-ws-web-services-without-ee-containers.html 
http://predic8.com/axis2-cxf-jax-ws-comparison.htm
http://stackoverflow.com/questions/11566609/difference-between-jax-ws-axis2-cxf
http://www.ibm.com/developerworks/library/j-jws8/
Hope this helps.

5 comments:

  1. Hello, I love reading through your blog, I wanted to leave a little comment to support. Wish you best of luck for all your best efforts web development companies in dubai

    ReplyDelete
  2. I really enjoyed this post. You recount this theme very well. I actually relish reading your blog and I will decisively bookmark it! hold up the interesting posts!

    ReplyDelete
  3. T&T Web Services is very important for a freelancer. A good freelancer should know about New update of web services,

    ReplyDelete
  4. This blog Is very informative, I am really pleased to post my comment on this blog. It helped me with ocean of knowledge so I really believe you will do much better in the future. Good job web master.
    Web service development

    ReplyDelete