JAX-WS Custom Exception with FaultBean in TomEE and WebSphere Application Server

Posted on

In our last post we were able to deploy a simple JAX-WS service on both TomEE and WebSphere Application Server.

JAX-WS Specification suggests that three thing should be followed for us to implement Custom Exception as SOAP Fault.

WrapperException(String message, FaultBean faultInfo) A constructor where WrapperException
is replaced with the name of the generated wrapper exception and FaultBean is replaced by the
name of the generated fault bean.
WrapperException(String message, FaultBean faultInfo, Throwable cause) A constructor
whereWrapperException is replaced with the name of the generated wrapper exception and FaultBean
is replaced by the name of the generated fault bean. The last argument, cause, may be used to convey
protocol specific fault information, see section 6.4.1.
FaultBean getFaultInfo() Getter to obtain the fault information, where FaultBean is replaced by the
name of the generated fault bean.

But as it turns out to be this is not very restrictive and not honored across Application Server. Let’s take the IMyService.java and MyServiceImpl.java from previous post and then we will modify the exception part.

Our updated Exception class will have a faultBean which will accept errorCode and errorMessage.

First the exception class MyException.java, in below code we have introduced a new class MyExceptionBean which holds our errorCode and errorMessage. We initialize this class with values which are passed to the constructor of our MyException.

package com.test.mumz.soap.soapexp;

import javax.xml.ws.WebFault;

/**
 * The Class MyException.
 * 
 * @author prabhat.jha
 */
@WebFault(name = "MyException")
public class MyException extends Exception {

	/** The Constant serialVersionUID. */
	private static final long	serialVersionUID	= -861826770198517502L;

	/** The my exception bean. */
	private MyExceptionBean		faultBean			= null;

	/**
	 * Instantiates a new my exception.
	 * 
	 * @param errorCode
	 *            the error code
	 * @param message
	 *            the message
	 */
	public MyException(String errorCode, String message) {
		prepareFaultBean(errorCode, message);
	}

	/**
	 * Instantiates a new my exception.
	 * 
	 * @param errorCode
	 *            the error code
	 * @param message
	 *            the message
	 * @param cause
	 *            the cause
	 */
	public MyException(String errorCode, String message, Throwable cause) {
		super(message, cause);
		prepareFaultBean(errorCode, message);
	}


	/**
	 * Adds the exception details.
	 *
	 * @param errorCode            the error code
	 * @param errorMessage            the error message
	 * @return the my exception
	 */
	private void prepareFaultBean(String errorCode, String errorMessage) {
		this.faultBean = new MyExceptionBean(errorCode, errorMessage);
	}
	
	/**
	 * Gets the fault bean.
	 *
	 * @return the fault bean
	 */
	public MyExceptionBean getFaultBean() {
		return faultBean;
	}
}

Next is our MyExceptionBean.java which is POJO and holds errorCode and errorMessage.

package com.test.mumz.soap.soapexp;

/**
 * The Class MyExceptionBean.
 * 
 * @author prabhat.jha
 */
public class MyExceptionBean {

	/** The error code. */
	private String	errorCode		= null;

	/** The error message. */
	private String	errorMessage	= null;

	/**
	 * Instantiates a new my exception bean.
	 * 
	 * @param errorCode
	 *            the error code
	 * @param errorMessage
	 *            the error message
	 */
	public MyExceptionBean(String errorCode, String errorMessage) {
		this.errorCode = errorCode;
		this.errorMessage = errorMessage;
	}

	/**
	 * @return the errorCode
	 */
	public String getErrorCode() {
		return errorCode;
	}

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

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

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

Next deploy it in TomEE and use SoapUI to test. Sample Input and Output are given below
Input

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mpr="http://mprabhat.com/">
   <soapenv:Header/>
   <soapenv:Body>
      <mpr:sayHello>
         <arg0></arg0>
      </mpr:sayHello>
   </soapenv:Body>
</soapenv:Envelope>

Output

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <soap:Fault>
         <faultcode>soap:Server</faultcode>
         <faultstring>Fault occurred while processing.</faultstring>
         <detail>
            <ns1:MyException xmlns:ns1="http://mprabhat.com/">
               <faultBean xsi:type="ns2:myExceptionBean" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://mprabhat.com/">
                  <errorCode>Code</errorCode>
                  <errorMessage>Message</errorMessage>
               </faultBean>
            </ns1:MyException>
         </detail>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

Brilliant everything works perfectly???? Wait let’s deploy it in WebSphere now. Please follow the same steps as described in previous post and then run with above input.

This is not to show demerit or loop hole in the spec or by the implementation provider, this is just another way of doing it but I would say follow the spec the chances of this not working is higher then the spec.

  • If you provide both getFaultInfo and getFaultBean in above MyException, you will find that control will always come to getFaultInfo. So the spec is honored 🙂
  • If in MyExceptionBean you remove getter and setters you will not see any Soap Fault but if you make your fields public it will again work ;), I know it’s simple Java bean specification.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s