Monday, December 19, 2011

SOAP Web Service

Before we go into the example, let us take a moment and discuss some of the differences between REST and SOAP.  Reviewing http://en.wikipedia.org/wiki/SOAP from wikpedia, we notice that SOAP does not have to be over the http protocol.  We will see from the requests and responses that the SOAP xml is much more verbose, which in turn could produce a performance hit.  There are differences in security, which I'll save for another project, and your company may have already decided on what web service standard to use.  There are several factors which will influence your decision on which to use, but (no pun intended) rest assured, the hype that REST is easier is mitigated by the fact that there are good development tools for SOAP which hide the complexity and therefor somewhat even the playing field in terms of "ease". 

Okay, on with the example:
SOAPDemoWebService.java

package com.sample.service;

import com.sample.PartEntity;
import com.sample.PartEntityFacade;
import com.sample.service.other.Part;
import javax.ejb.EJB;
import javax.ejb.EJBTransactionRolledbackException;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.ejb.Stateless;
import javax.persistence.EntityExistsException;
/** note: needs tools.jar from jdk1.5+ in env to run test so it can compile the source */

/**
 * SOAP DEMO to perform CRUD operations on the Parts table
 * ServiceName = SOAPDemoWebService
 *
 * @author Thomas Dias
 */
@WebService(serviceName = "SOAPDemoWebService")
@Stateless()
public class SOAPDemoWebService {
    @Inject
    PartEntityFacade partEntityFacade;

    @WebMethod(operationName = "create")
    public Part create(@WebParam(name = "name") String name, @WebParam(name = "parentName") String parentName) {
        PartEntity parent = partEntityFacade.findByName(parentName);
        PartEntity newPart = new PartEntity(name, parent);

        // in case there is an error persisting the new part, set the newPart to null
        try {
            partEntityFacade.create(newPart);
        } catch (EntityExistsException e) {
            newPart = null;
        } catch (EJBTransactionRolledbackException e) {
            newPart = null;
        }

        // We are returning a Part, not a PartEntity - convert the PartEntity to a part.
        return new Part(newPart);
    }

    @WebMethod(operationName = "remove")
    public boolean remove(@WebParam(name = "id") Long id) {
        partEntityFacade.remove(id);
        return true;
    }

    @WebMethod(operationName = "find")
    public Part find(@WebParam(name = "name") String name) {
        return new Part(partEntityFacade.findByName(name));
    }
}


Now you may say, "hey, this is a lot smaller then the REST service", but upon closer inspection you'll note, there isn't all the comments, there is an extra method in the REST service to demonstrate creating a part via a get, etc.  So, no, these files are almost the same.

Starting from the top:
@WebService(serviceName = "SOAPDemoWebService")
@Stateless 
We define the class to be a SOAP web service, and declare that it is stateless.  Now remember, a SOAP service doesn't actually have to be stateless, but by definition, a web service is stateless.  So, changing this goes against the standard definition.

Then we inject the same facade to handle database transactions, and then we declare the method name:
    @WebMethod(operationName = "create")
Now here, there is a slight difference, because we are not defining the http method, i.e. GET, PUT, POST..., but instead defining the uri method similar to the @Path.  One minor issue with this is that there is no standard naming convention, so it is up to each developer to decide what the method name will be... as opposed to GET, PUT, POST, DELETE.

We define what parameters are injected from the xml file that was supplied with the call to the http method. 
   ( @WebParam(name = "name") String name,...)
Again we note a difference.  The SOAP interprets XML, we do not have the annotation @Consumes, because it doesn't have those options, no JSON.  The consumption is defined by these @WebParam annotations which will then be turned into the WSDL file (you'll see what I mean later).  

The actual core java code is almost a cut and paste from the REST service.  Now, how hard was that?  I'd say, for this simple web service, there was no difference.  But, the fact that the definition of the services are very similar hide the underlying differences as we'll see when we review the client side.

No comments:

Post a Comment