1 Reply Latest reply on Jan 19, 2012 5:25 PM by jfitzpatrick

    Custom exceptions with @WebFault

    kirillica

      Hi there,

       

      I've tried several different combinations with no success, while case seems to be easy.

       

      The thing is: I need custom exception with some additional properties.

       

      If I do smth like this (http://io.typepad.com/eben_hewitt_on_java/tech_notes/), I recieve:

      18:34:44,665 WARN  [org.apache.cxf.jaxws.interceptors.WebFaultOutInterceptor] Exception occurred while writing fault.: org.apache.cxf.interceptor.Fault: Marshalling Error: class package.WebServiceExceptionFaultDto nor any of its super class is known to this context.
           at org.apache.cxf.jaxb.JAXBEncoderDecoder.marshall(JAXBEncoderDecoder.java:254) [:2.3.1-patch-01]
           at org.apache.cxf.jaxb.io.DataWriterImpl.write(DataWriterImpl.java:169) [:2.3.1-patch-01]
           at org.apache.cxf.jaxws.interceptors.WebFaultOutInterceptor.handleMessage(WebFaultOutInterceptor.java:115) [:2.3.1-patch-01]
           at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:255) [:2.3.1-patch-01]
           at org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:99) [:2.3.1-patch-01]
           at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:311) [:2.3.1-patch-01]
           at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:113) [:2.3.1-patch-01]
           at org.apache.cxf.transport.servlet.ServletDestination.invoke(ServletDestination.java:97) [:2.3.1-patch-01]
           at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:461) [:2.3.1-patch-01]
           at org.jboss.wsf.stack.cxf.ServletControllerExt.invoke(ServletControllerExt.java:172) [:3.4.1.GA]
           at org.jboss.wsf.stack.cxf.RequestHandlerImpl.handleHttpRequest(RequestHandlerImpl.java:57) [:3.4.1.GA]
           at org.jboss.wsf.stack.cxf.transport.ServletHelper.callRequestHandler(ServletHelper.java:156) [:3.4.1.GA]
           at org.jboss.wsf.stack.cxf.CXFNonSpringServletExt.invoke(CXFNonSpringServletExt.java:90) [:3.4.1.GA]
           at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:179) [:2.3.1-patch-01]
           at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:103) [:2.3.1-patch-01]
           at javax.servlet.http.HttpServlet.service(HttpServlet.java:754) [:1.0.0.Final]
           at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:159) [:2.3.1-patch-01]
           at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:324) [:6.1.0.Final]
           at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242) [:6.1.0.Final]
           at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [:6.1.0.Final]
           at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:161) [:6.1.0.Final]
           at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java) [:6.1.0.Final]
           at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:181) [:6.1.0.Final]
           at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:593) [:6.1.0.Final]
           at org.jboss.modcluster.catalina.CatalinaContext$RequestListenerValve.event(CatalinaContext.java:285) [:1.1.0.Final]
           at org.jboss.modcluster.catalina.CatalinaContext$RequestListenerValve.invoke(CatalinaContext.java:261) [:1.1.0.Final]
           at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:88) [:6.1.0.Final]
           at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:100) [:6.1.0.Final]
           at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:159) [:6.1.0.Final]
           at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [:6.1.0.Final]
           at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158) [:6.1.0.Final]
           at org.apache.catalina.authenticator.SingleSignOn.invoke(SingleSignOn.java:397) [:6.1.0.Final]
           at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [:6.1.0.Final]
           at org.jboss.web.tomcat.service.request.ActiveRequestResponseCacheValve.invoke(ActiveRequestResponseCacheValve.java:53) [:6.1.0.Final]
           at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:362) [:6.1.0.Final]
           at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [:6.1.0.Final]
           at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:654) [:6.1.0.Final]
           at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:951) [:6.1.0.Final]
           at java.lang.Thread.run(Unknown Source) [:1.6.0_29]
      Caused by: javax.xml.bind.JAXBException: class package.WebServiceExceptionFaultDto nor any of its super class is known to this context.
           at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getBeanInfo(JAXBContextImpl.java:594) [:2.2]
           at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [:1.6.0_29]
           at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) [:1.6.0_29]
           at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) [:1.6.0_29]
           at java.lang.reflect.Method.invoke(Unknown Source) [:1.6.0_29]
           at org.zeroturnaround.jrebel.jaxb.proxy.JaxbContextProxyHandler.invoke(JaxbContextProxyHandler.java:209)
           at com.sun.xml.bind.v2.runtime.JAXBContextImpl_$$_javassist_0.getBeanInfo(JAXBContextImpl_$$_javassist_0.java)
           at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:482) [:2.2]
           at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:315) [:2.2]
           at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:244) [:2.2]
           at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:109) [:1.0.0.Final]
           at org.apache.cxf.jaxb.JAXBEncoderDecoder.writeObject(JAXBEncoderDecoder.java:538) [:2.3.1-patch-01]
           at org.apache.cxf.jaxb.JAXBEncoderDecoder.marshall(JAXBEncoderDecoder.java:243) [:2.3.1-patch-01]
           ... 38 more

       

      Code snippets:

      @WebFault(name = "WebServiceException", targetNamespace = "http://www.ww")
      public class WebServiceException extends Exception {
      
        private static final long serialVersionUID = 6441007395053274685L;
      
        private WebServiceExceptionFaultDto faultInfo;
        
        public WebServiceException(String message, WebServiceExceptionFaultDto faultIFault){
          super(message);
          this.faultInfo = faultIFault;
        }
        
        public WebServiceException(String message, WebServiceExceptionFaultDto faultIFault, Throwable cause){
          super(message, cause);
          this.faultInfo = faultIFault;
        }
      
        public WebServiceExceptionFaultDto getFaultInfo() {
          return faultInfo;
        }
      }
      @XmlRootElement(name = "WebServiceException", namespace = "http://www.ww")
      @XmlType(propOrder = { "message" })
      public class WebServiceExceptionFaultDto {
      
        private String message;
      
        public WebServiceExceptionFaultDto(String message) {
          this.message = message;
        }
      
        public String getMessage() {
          return message;
        }
      
        public void setMessage(String message) {
          this.message = message;
        }
      
      }

      If I do:

      throw new WebServiceException("111", new WebServiceExceptionFaultDto("222"));

      Then in SOAP response I get:

      <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
         <soap:Body>
            <soap:Fault>
               <faultcode>soap:Server</faultcode>
               <faultstring>111</faultstring>
               <detail/>
            </soap:Fault>
         </soap:Body>
      </soap:Envelope>

      And log error like described above. Any Ideas?

       

      Platform: JBoss6.1, Java6

       

      Thanks in advance,

      Kirill

        • 1. Re: Custom exceptions with @WebFault
          jfitzpatrick

          Have you tried defining the fault in your wsdl file and then using wsimport to have the JAXB artifacts generated for you?

           

          Example that I think should work:

           

          wsdl:

           

          <?xml version="1.0" encoding="UTF-8"?>

           

          <definitions

              name="SubtractNumbers"

              targetNamespace="http://duke.example.org"

              xmlns:tns="http://duke.example.org"

              xmlns="http://schemas.xmlsoap.org/wsdl/"

              xmlns:xsd="http://www.w3.org/2001/XMLSchema"

              xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">

              <types>

                  <xsd:schema

                      xmlns="http://www.w3.org/2001/XMLSchema"

                      targetNamespace="http://duke.example.org"

                      elementFormDefault="qualified">

           

                      <complexType name="subtractNumbersResponse">

                          <sequence>

                              <element name="return" type="xsd:int" />

                          </sequence>

                      </complexType>

                      <element name="subtractNumbersResponse" type="tns:subtractNumbersResponse"/>

           

                      <complexType name="subtractNumbers">

                          <sequence>

                              <element name="arg0" type="xsd:int" />

                              <element name="arg1" type="xsd:int" />

                          </sequence>

                      </complexType>

                      <element name="subtractNumbers" type="tns:subtractNumbers"/>

           

                      <element name="permissionDeniedFault">

                          <complexType>

                              <sequence>

                                  <element name="message" type="xsd:string"/>

                              </sequence>

                          </complexType>

                      </element>

           

                  </xsd:schema>

              </types>

              <message name="subtractNumbers">

                  <part name="parameters" element="tns:subtractNumbers" />

              </message>

              <message name="subtractNumbersResponse">

                  <part name="result" element="tns:subtractNumbersResponse" />

              </message>

              <message name="permissionDeniedException">

                  <part name="permissionDeniedFault" element="tns:permissionDeniedFault"/>

              </message>

              <portType name="SubtractNumbersPortType">

                  <operation name="subtractNumbers">

                      <input message="tns:subtractNumbers" />

                      <output message="tns:subtractNumbersResponse" />

                      <fault name="permissionDeniedFault" message="tns:permissionDeniedException" />

                  </operation>

              </portType>

              <binding name="SubtractNumbersBinding" type="tns:SubtractNumbersPortType">

                  <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />

                  <operation name="subtractNumbers">

                      <soap:operation soapAction="" />

                      <input>

                          <soap:body use="literal" />

                      </input>

                      <output>

                          <soap:body use="literal" />

                      </output>

                      <fault name="permissionDeniedFault">

                          <soap:fault use="literal" name="permissionDeniedFault" />

                      </fault>

                  </operation>

              </binding>

              <service name="SubtractNumbersService">

                  <port name="SubtractNumbersPort" binding="tns:SubtractNumbersBinding">

                      <soap:address location="REPLACE_WITH_ACTUAL_URL" />

                  </port>

              </service>

          </definitions>

           

          Generated fault/exception related artificats:

           

          @XmlAccessorType(XmlAccessType.FIELD)

          @XmlType(name = "", propOrder = {

              "message"

          })

          @XmlRootElement(name = "permissionDeniedFault")

          public class PermissionDeniedFault {

           

              @XmlElement(required = true)

              protected String message;

           

              /**

               * Gets the value of the message property.

               *

               * @return

               *     possible object is

               *     {@link String }

               *    

               */

              public String getMessage() {

                  return message;

              }

           

              /**

               * Sets the value of the message property.

               *

               * @param value

               *     allowed object is

               *     {@link String }

               *    

               */

              public void setMessage(String value) {

                  this.message = value;

              }

           

          }

           

          @WebFault(name = "permissionDeniedFault", targetNamespace = "http://duke.example.org")

          public class PermissionDeniedException

              extends Exception

          {

           

              /**

               * Java type that goes as soapenv:Fault detail element.

               *

               */

              private PermissionDeniedFault faultInfo;

           

              /**

               *

               * @param message

               * @param faultInfo

               */

              public PermissionDeniedException(String message, PermissionDeniedFault faultInfo) {

                  super(message);

                  this.faultInfo = faultInfo;

              }

           

              /**

               *

               * @param message

               * @param faultInfo

               * @param cause

               */

              public PermissionDeniedException(String message, PermissionDeniedFault faultInfo, Throwable cause) {

                  super(message, cause);

                  this.faultInfo = faultInfo;

              }

           

              /**

               *

               * @return

               *     returns fault bean: provider.server.PermissionDeniedFault

               */

              public PermissionDeniedFault getFaultInfo() {

                  return faultInfo;

              }

           

          }

           

          Implementation class:

           

          @WebService (serviceName = "SubtractNumbersService",

                  portName = "SubtractNumbersPort",

                  endpointInterface = "provider.server.SubtractNumbersPortType" )

          public class  SubtractNumbersImpl {

           

              public int subtractNumbers(int arg1, int arg2) throws PermissionDeniedException {

              

                    PermissionDeniedFault permissionDeniedFault = new PermissionDeniedFault();

                    permissionDeniedFault.setMessage("Your custom message here explain why permission was denied.");

           

                   throw new PermissionDeniedException("Permission denied.", permissionDeniedFault);

              }

          }