axis-java-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Steve Loughran" <stev...@iseran.com>
Subject Re: exception and SOAP fault
Date Thu, 01 May 2003 06:10:12 GMT
This is good -and sorting out exceptions would be a good feature in Axis1.
2-including documenting what on earth is going on.

With this patch, what happens at the WSDL generation time? Is there any
warning as to what goes over? What about interop? What do other
languages/platforms see? Something they have to deserialize, I suppose.

----- Original Message -----
From: "David Green" <david.green@maketechnologies.com>
To: <axis-user@ws.apache.org>
Cc: <axis-dev@xml.apache.org>
Sent: Wednesday, April 30, 2003 13:39
Subject: RE: exception and SOAP fault


I've confirmed that:

1. I can throw any exception inheriting from java.lang.Exception and have a
SOAP fault with data and exception class providing that a
serializer/deserializer are registered for the class of the exception.
2. Previous behaviour is maintained for exceptions that don't inherit from
AxisFault, and for which there is no serializer registered.
3. Previous behaviour for exceptions inheriting from AxisFault is
maintained.

This means that no axis-specific code is required in my JAX-RPC service
implementation.

It seems like what I produced previously is actually not enough.  After some
testing, the following patch seems to be working.
Any feedback would be welcome.


Index: java/src/org/apache/axis/AxisFault.java
===================================================================
RCS file: /home/cvspublic/xml-axis/java/src/org/apache/axis/AxisFault.java,v
retrieving revision 1.74
diff -r1.74 AxisFault.java
108c108
<
---
>
258c258
<         }
---
>         }
267a268
>         boolean haveTypeDetailMapping = false;
271c272,288
<             addFaultDetail(Constants.QNAME_FAULTDETAIL_EXCEPTIONNAME,
---
>           haveTypeDetailMapping = true;
>         }
>         if (!haveTypeDetailMapping) {
>           MessageContext context = MessageContext.getCurrentContext();
>           if (context != null) {
>             try {
>               if
(context.getTypeMapping().getSerializer(target.getClass()) != null) {
>                 haveTypeDetailMapping = true;
>               }
>             } catch (Exception e) {
>               // swallow this exception, since we're just trying to
>               // determine if we have a serializer.
>             }
>           }
>         }
>         if (haveTypeDetailMapping) {
>           addFaultDetail(Constants.QNAME_FAULTDETAIL_EXCEPTIONNAME,
273a291
>
750a769
>
756c775,788
<         // no data in default Axis fault
---
>       Object detailObject = (getCause()==null)?this:getCause();
>       boolean haveSerializer = false;
>
>       try {
>         if
(context.getTypeMapping().getSerializer(detailObject.getClass())!=null) {
>           haveSerializer = true;
>         }
>       } catch (Exception e) {
>         // swallow this exception, it means that we don't know how to
serialize
>         // the details.
>       }
>       if (haveSerializer) {
>         context.serialize(qname, null, detailObject);
>       }


-----Original Message-----
From: David Green
Sent: Wednesday, April 30, 2003 11:43 AM
To: 'axis-user@ws.apache.org'
Cc: 'axis-dev@xml.apache.org'
Subject: RE: exception and SOAP fault


The following patch to AxisFault ensures that any exception that has a
serializer registered will serialize the exception details
to the SOAP fault without having to have the exception class extend
AxisFault:

Index: java/src/org/apache/axis/AxisFault.java
===================================================================
RCS file: /home/cvspublic/xml-axis/java/src/org/apache/axis/AxisFault.java,v
retrieving revision 1.74
diff -r1.74 AxisFault.java
756c756,768
<         // no data in default Axis fault
---
>       Object detailObject = (getCause()==null)?this:getCause();
>       boolean haveSerializer = false;
>       try {
>         if (context.getTypeMapping().getSerializer(getClass())!=null) {
>           haveSerializer = true;
>         }
>       } catch (Exception e) {
>         // swallow this exception, it means that we don't know how to
serialize
>         // the details.
>       }
>       if (haveSerializer) {
>         context.serialize(qname, null, detailObject);
>       }

I apologize for the cross-post.  It's not clear to me which list should be
used for contributions.

David

-----Original Message-----
From: David Green
Sent: Wednesday, April 30, 2003 11:00 AM
To: axis-user@ws.apache.org
Subject: RE: exception and SOAP fault


Thomas,

Thankyou -- it works.  From what I can tell, all that is needed for faults
with data to work with any exception (not just exceptions that extend
AxisFault) is for the following method to be implemented in AxisFault:


    /**
     *  Writes any exception data to the faultDetails
     * This is for overriding; it is empty in the base AxisFault
     */
    public void writeDetails(QName qname, SerializationContext context)
throws java.io.IOException {
        // no data in default Axis fault
    }

As you can see, the current implementation does nothing.  It seems that the
only reason we get the fault data with the WSDL2Java generated exception is
due to the generated code overriding this method as follows:

    /**
     * Writes the exception data to the faultDetails
     */
    public void writeDetails(javax.xml.namespace.QName qname,
org.apache.axis.encoding.SerializationContext context) throws
java.io.IOException {
        context.serialize(qname, null, this);
    }

Perhaps it's too simplistic, but it seems that a reasonable modification to
AxisFault would solve the problem.  All that would be needed is the
following:

1. AxisFault.initFromException() would save the instance of the exception in
a member variable.
2. AxisFault.writeDetails() would be implemented as follows:


    /**
     *  Writes any exception data to the faultDetails
     * This is for overriding; it is empty in the base AxisFault
     */
    public void writeDetails(QName qname, SerializationContext context)
throws java.io.IOException {
      if (exceptionDetail != null) { // <----- this is the exception that
was saved in initFromException()
        context.serialize(qname, null, exceptionDetail);
      }
    }

In any case, it's possible that I've missed something.  Is there some reason
why this wasn't done already?  In any case, I'm going to try it here to see
if there are any other side effects of doing this.

David


-----Original Message-----
From: David Green
Sent: Wednesday, April 30, 2003 9:43 AM
To: axis-user@ws.apache.org
Subject: RE: exception and SOAP fault


Thomas,

Thankyou very much for your help.  I'll give it a try and let you know how
it goes.

It's a shame that we must use axis-specific code in our exceptions on the
server to make it work.

David

-----Original Message-----
From: Thomas.Rothfuss @ .de []
Sent: Tuesday, April 29, 2003 9:48 PM
To: axis-user@ws.apache.org
Subject: Re: exception and SOAP fault



Hi David,

I started with the WSDL file and created the java classes by using
WSDL2Java.

The exception class itself is derived from AxisFault:
    public class WoodCommanderException  extends org.apache.axis.AxisFault
implements java.io.Serializable

The method throwing the exception is declared like this:
    public Homag.WoodCommander.Soap.Value getValue(java.lang.String in0)
throws java.rmi.RemoteException,
Homag.WoodCommander.Soap.WoodCommanderException

In your case the BusinessException extends the TestException. Perhaps this
may be a problem in Axis. I never tried that.

I already posted my scenario in this mailing list. Here is the pointer:
    http://marc.theaimsgroup.com/?l=axis-user&m=104988960618062&w=2

Hope this will help

Thomas



|---------+---------------------------------->
|         |           "David Green"          |
|         |           <david.green@maketechno|
|         |           logies.com>            |
|         |                                  |
|         |                                  |
|         |                                  |
|         |           30.04.03 03:01         |
|         |           Bitte antworten an     |
|         |           axis-user              |
|         |                                  |
|---------+---------------------------------->

>---------------------------------------------------------------------------
---------------------------------------------------|
  |
|
  |       An:       <axis-user@xml.apache.org>
|
  |       Kopie:
|
  |       Thema:    exception and SOAP fault
|

>---------------------------------------------------------------------------
---------------------------------------------------|



I've been attempting to find documentation on how to have SOAP faults
created from custom exception types on the server, and re-thrown on the
client.

There appear to be several threads on this, none of which have enough
information for me to produce the desired result.  If there is known
documentation on this, can someone please direct me to it?  Otherwise, does
anyone know how to do this?

Desired behavior:

1. Declare a Java class on the server with methods that throw the
appropriate exception type (that preferably inherits from
java.lang.Exception, not AxisFault)
2. Declare the exception class with appropriate get/set methods for all
properties.
3. Whenever necessary, on the server throw an instance of the exception.
4. If necessary configure (using the wsdd file) serializers for the
exception class.
5. If thrown, Axis on the server creates a SOAP fault with sufficient data
that the exception can be re-created on the client side.
6. Generated WSDL contains accurate fault definitions.

So far I've been able to do all of the above except for 5.  The WSDL
appears to be correct, however the fault contains none of the relevant
data.  If the exception class inherits from AxisFault, the fault appears as
follows:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance">
 <soapenv:Body>
  <soapenv:Fault>
   <faultcode>soapenv:Server.generalException</faultcode>
   <faultstring>Internal server error. (ref# 10301)</faultstring>
   <detail>
    <ns1:exceptionName xmlns:ns1="http://xml.apache.org/axis/
">com.maketechnologies.webservice.test.BusinessException</ns1:exceptionName>

   </detail>
  </soapenv:Fault>
 </soapenv:Body>
</soapenv:Envelope>

This causes the client to properly instantiate the BusinessException,
however the BusinessException contains the following information (from
WSDL):

<complexType name="TestException">
  <sequence>
    <element name="message" nillable="true" type="xsd:string" />
  </sequence>
</complexType>
<complexType name="BusinessException">
  <complexContent>
    <extension base="impl:TestException">
      <sequence>
       <element name="errorCode" type="xsd:int" />
      </sequence>
    </extension>
  </complexContent>
</complexType>

As you can see, the errorCode is not transmitted over the wire.

Any help and/or pointers to documentation would be greatly appreciated.

David







Mime
View raw message