Friday 2 December 2016

How to handle JAX-WS Exceptions and Faults

How to handle JAX-WS Exceptions and Faults



How to handle JAX-WS Exceptions and Faults



This post will  discusses the JAX-WS mapping of WSDL faults to Java exceptions,  Java exceptions to WSDL faults.

To unserstand the concept of handling faults and exceptions in webservices, you should have a basic knowledge on how to create JAX-WS web services and clients. You may find the following posts helpful.

Creating SOAP Web Services using JAX-WS
Testing the SOAP web services using SOAP UI

Tools required:

1. Eclipse
2. Tomcat 6 or above version
3. Java 1.6 or above verson.

What is  JAX-WS Fault Handing and Exception Handling:

The JAX-WS Specification demands that mapped exception must be annotated with a javax.xml.ws.WebFault (@WebFault) annotation. A wsdl:fault element is mapped to this Java exception . A wsdl:fault element refers to a wsdl:message that contains a single part and is mapped to a Java bean, called a fault bean , which is just a POJO class which has only setter and getter methods. The exception class should have two constructors and a getter method (to obtain fault details) as follows

InvalidRequestFault(String message, ServiceFault faultInfo)
InvalidRequestFault(String message, ServiceFault  faultInfo, Throwable cause)
ServiceFault getFaultInfo()

Where, WrapperException is the name of the Exception class and FaultBean is the fault bean POJO.

JAX-WS Exception Handling and JAX-WS SOAP Fault Handling Example

Now, let us create a web service and custom exception class to handle JAX-WS exception and SOAP faults.

Web Service SEI and Implementation Classes are as fallows:

SEI: AirportService.java

package com.javasourceworld.webservice;

import javax.jws.WebMethod;
import javax.jws.WebService;

@WebService
public interface AirportService {
      @WebMethod
      String findAirportNames(String countryCode);
}

Implementation:


package com.javasourceworld.webservice;

import javax.jws.WebMethod;
import javax.jws.WebService;

@WebService(endpointInterface = "com.javasourceworld.webservice.AirportService")
public class AirportServiceImpl implements AirportService{

      AirportUtility utility;
     
      public AirportServiceImpl(){
            utility = new AirportUtility();
            utility.loadAirports();
      }

      @Override
      @WebMethod
      public  String findAirportNames(String countryCode) throws 
                                         InvalidRequestFault {
            
          Airport airport = utility.findAirports(countryCode);
              StringBuilder bd = new StringBuilder();
            if(airport != null){
                  bd.append("Airport Name: ").append(" ").
                  append(airport.getAirportCode()).append(";  ").
                  append("City Name: ").append(airport.getCityName());
                return bd.toString();
            }else{
                  ServiceFault fault = new ServiceFault();
                  fault.setErrorcode("1234");
                  fault.setErrorDescription("My Service Error");
                  throw new InvalidRequestFault("1234","My Service Error: The 
                           given country is not found");
            }
          
      }  
}

In the above  implementation class, the findAirportNames() web service method throws InvalidRequestFault(customized exception) if the incoming countrycode is invalid. 

Otherwise the service method returns airport name info to the consumer.

ServiceFault.java

This is the fault bean POJO class required by the JAXB runtime to process exceptions.

package com.javasourceworld.webservice;

public class ServiceFault {
      private String errorcode;
      private String errorDescription;
      /**
       * @return the errorcode
       */
      public String getErrorcode() {
            return errorcode;
      }
      /**
       * @param errorcode the errorcode to set
       */
      public void setErrorcode(String errorcode) {
            this.errorcode = errorcode;
      }
      /**
       * @return the errorDescription
       */
      public String getErrorDescription() {
            return errorDescription;
      }
      /**
       * @param errorDescription the errorDescription to set
       */
      public void setErrorDescription(String errorDescription) {
            this.errorDescription = errorDescription;
      }

}

Custom Exception class InvalidRequestFault.java

This class is required to be annotated with @WebFault annotation.


package com.javasourceworld.webservice;

import javax.xml.ws.WebFault;

@WebFault(name="ServiceFault", targetNamespace="http://webservice.javasourceworld.com/")
public class InvalidRequestFault extends Exception {
      /**
       *
       */
      private static final long serialVersionUID = -6647544772732631037L;
     
      private ServiceFault fault;
      /**
       *
       */
      public InvalidRequestFault() {
      }
      /**
       *
       * @param fault
       */
      protected InvalidRequestFault(ServiceFault fault) {
        super(fault.getErrorDescription());
        this.fault = fault;
     }
      /**
       *
       * @param message
       * @param faultInfo
       */
      public InvalidRequestFault(String message, ServiceFault faultInfo){
            super(message);
        this.fault = faultInfo;
      }
      /**
       *
       * @param message
       * @param faultInfo
       * @param cause
       */
      public InvalidRequestFault(String message, ServiceFault faultInfo,         
                 Throwable cause){
            super(message,cause);
        this.fault = faultInfo;
      }
      /**
       *
       * @return
       */
      public ServiceFault getFaultInfo(){
            return fault;
      }
     
      /**
       * @param message
       */
      public InvalidRequestFault(String message) {
            super(message);
      }
      /**
       * @param message
       */
      public InvalidRequestFault(String code, String message) {
            super(message);
            this.fault = new ServiceFault();
          this.fault.setErrorDescription(message);
          this.fault.setErrorcode(code);
      }

      /**
       * @param cause
       */
      public InvalidRequestFault(Throwable cause) {
            super(cause);
            // TODO Auto-generated constructor stub
      }

      /**
       * @param message
       * @param cause
       */
      public InvalidRequestFault(String message, Throwable cause) {
            super(message, cause);
            // TODO Auto-generated constructor stub
      }
}

You can create the WSDL of the above service, by using the “wsgen” tool or the web container will create one for you, if you package and deploy the service to a web container such as tomcat.  Read the below article to know more about how to do that.


In this post, we are creating our wsdl using the web container such as tomcat, we will get the wsdl from the host location and copy it to the .wsdl file, and we test that using SOAP UI.

Now deploying the service in tomcat.

Hosted wsdl will be as shown below with the fault elements:

Click on the image to see it clearly.





Note:

While running/ hosting the JAX-WS service faults if JAX-WS 2.2 on top of JDK 6 with tomcat , we may come across the fallowing error on deployment
java.lang.NoSuchMethodError: javax.xml.ws.WebFault.messageName()Ljava/lang/String
To solve that fallow the below link:

java.lang.NoSuchMethodError: javax.xml.ws.WebFault.messageName()Ljava/lang/String


Now we will copy this wsdl to a file with the extension of wsdl.

To test it in SOAP UI, load the wsdl to the created project and run the request by giving the end point url.

For detail overview on testing the web service in SOAP UI, read the fallowing post that will be helpful in understanding the current concept.

Testing the SOAP web services using SOAP UI

After loading the wsdl and ran it in the soap UI, the view of the request and response will be as shown in the below image. For a clear view double click on the image.




 Now we will trigger a request with valid and invalid data and will see the difference.

Testing with the valid request:

Passing the countryCode as 'IN', which is valid and show the response with the airport  details

Request:




Response:



Testing with aninvalid request:

Passing the countryCode as 'AA', which is invalid and show the response with the fault details

Request:













Response:











As shown in the above image, in the <ns2:ServiceFault> elemente, <errorDescription> and <errorcode> are showing the fault info with the meaning ful message instead with no response.

This is the way we handle the faults and exceptions in the web services when using JAX-WS API.

Read:
Creating SOAP Web Services using JAX-WS
Difference between SOAP and REST web services
java.lang.NoSuchMethodError: javax.xml.ws.WebFault.messageName()Ljava/lang/String


No comments:

Post a Comment