14 Feb 2014

Developing a Soap Service Using Apache Cxf and Jaxb annotations

  •  Advance:
In a passed post, you saw how to developan application using the “MethodTemplate” Design Pattern. Now we’re going to develop a Service tier for this Business tier developed in the past.
In this post, you can find a running application to see how the Service works, using a SOAP implementation built with the Apache cxf library and Jaxb Annotations

Rev: 6.

Also I would like to say, you can deploy this Service in an Application Server (I have selected Tomcat 7.0) and use SoapUI to send request to the Server (I have included a SoapUI Project in the SVN for that purpose)

  •  Explanation
We want to develop a Service Tier for an Existing Business Tier, but we want to reutilize all the code previously developed, also I don’t want to import the code as a jar or as an external Java Project downloaded in the workspace. For that purpose, we have published the Business Tier in the Maven Central Repository. Now you can download the project as a Maven Dependency and use it.

For the checkout of the code, you should know this example was developed as a Maven Project, under 1.7 JDK and Spring 3.0.

For this example I have selected Apache cxf because with a little set of Annotations you could develop a Service as follows

o API Tier
Object
Description
ManageVehicleRequest
This object, represent a request to consume themanageVehicleoperation existing in the Vehicle Service.
ManageVehicleResponse
This object, represent a response from the Service Vehicle after themanageVehicleoperation has been finished
VehicleService
The definition of our Service including all the operations we want to publish in our SOAP Architechture. In this case, we only have one operation (manageVehicle)

o SERVICE Tier
Object
Description
VehicleServiceImpl
This is only the implementation of our Service.

o CODE snapshots
VehicleService
@WebService(name = "VehicleService")
public interface VehicleService {

 @WebMethod
 String getVersion();

 @WebMethod
 ManageVehicleResponse manageVehicle(ManageVehicleRequest request);

}

As you can see, we only have to use two annotations, the first one, is only to declare our Interface as a Service (with a concrete name). The second annotation is used to indicate what methods must be published within the Service


ManageVehicleRequest
@XmlType(name = "ManageVehicleRequest")
@XmlSeeAlso({ EngineVehicleDTO.class, AnimalVehicleDTO.class })
public class ManageVehicleRequest implements Serializable {

 /**
  * 
  */
 private static final long serialVersionUID = 1144868850362615114L;

 private VehicleDTO vehicle;

 /**
  * @return the vehicle
  */
 public VehicleDTO getVehicle() {
  return vehicle;
 }

 /**
  * @param vehicle
  *            the vehicle to set
  */
 public void setVehicle(VehicleDTO vehicle) {
  this.vehicle = vehicle;
 }

}

This object will be used to pass the information from the outside to the Service. In this case we should include inside this object a VehicleDTO instance.

It’s considered as a good practice to use the @XmlType annotation to give a name to our object. If you don’t follow this tip, you are delegating in the framework the names for all the XML elements within of the namespace used by the Service. And maybe you would have errors at deployment time.

As you can see, VehicleDTO is a parent object of EngineVehicleDTO and AnimalVehicleDTO, our operation has to work with these child objects, this is the purpose followed by the @XmlSeeAlso annotation. This annotation says to the framework that at deployment time, these objects must be part of the WSDL. If you don’t use that annotation, you only could send instances from VehicleDTO.



ManageVehicleResponse
package gazpachito.examples.services.cxf.vehicle.api.response;

import java.io.Serializable;

import javax.xml.bind.annotation.XmlType;

@XmlType(name = "ManageVehicleResponse")
public class ManageVehicleResponse implements Serializable {

 /**
  * 
  */
 private static final long serialVersionUID = -7879894326252286663L;

 private String errorMessage;

 /**
  * @return the errorMessage
  */
 public String getErrorMessage() {
  return errorMessage;
 }

 /**
  * @param errorMessage
  *            the errorMessage to set
  */
 public void setErrorMessage(String errorMessage) {
  this.errorMessage = errorMessage;
 }

}


This object will be used to return the information from the Service to the outside. In this case
we only just want to pass an error message, but in fact, we could return whatever you want, collections or a complex object maybe (with the exception of Maps)



VehicleServiceImpl
public class VehicleServiceImpl implements VehicleService {

 @Autowired
 private VehicleFacade vehicleFacadeImpl;

 @Override
 public String getVersion() {

  String version = ResourceBundle.getBundle("vehicle").getString(
    "vehicle.version");
  return version;
 }

 @Override
 public ManageVehicleResponse manageVehicle(ManageVehicleRequest request) {
  ManageVehicleResponse response = new ManageVehicleResponse();

  if (request != null && request.getVehicle() != null) {

   VehicleEnum template = null;

   if (request.getVehicle() instanceof AnimalVehicleDTO) {
    template = VehicleEnum.ANIMAL;
   } else if (request.getVehicle() instanceof EngineVehicleDTO) {
    template = VehicleEnum.ENGINE;
   }

   try {
    this.vehicleFacadeImpl.manageVehicle(request.getVehicle(),
      template);
   } catch (FacadeException e) {

    response.setErrorMessage(e.getMessage());
   }
  }
  return response;
 }

This is the implementation of our service. As you can see, I only have  used a Spring annotation to inject the facade developed in other post. And we only need to make an implementation for the two operations publisheds in the Interface VehicleService.

About the “getVersion” method, just return the version extracted from a properties file (using the ${project} variable inside this properties file). The “manageVehicle” method only validate the input from the outside before this information sent to Facade


  •    Conclusions

As you can see, using a little set of JAXB annotations, we can develop a WebService based in a SOAP Architecture. In this post I only have introduced enough annotations to show you how to develop a Service in an easy way, but you can use more JAXB annotations and different combinations between them to go further.

But this framework has a weakness. You have to write a little of XML in a configuration file to define the endpoint of all your Services (at least in the version chosen for this example). So you can’t forgive the configuration files and the configuration of the endpoint sometimes is a hard task.

No comments:

Post a Comment