Hi,
I have been using custom exceptions for nearly 2 years now and it always worked fine for me (since 1.2-RC2 I think).
But I start from the WSDL and have the java classes generated. I find it easier to maintain 1 file and have 30 java classes generated than the opposite. Once you understand a WSDL it is really easy to add parameters and operations.
so my custom exception structure is:
<complexType name="WSException">
<sequence>
<element name="errorCode" type="xsd:int" nillable="false"/>
<element name="errorMessage" type="xsd:string" nillable="true"/>
<element name="trace" type="xsd:string" nillable="true"/>
</sequence>
</complexType>
<sequence>
<element name="errorCode" type="xsd:int" nillable="false"/>
<element name="errorMessage" type="xsd:string" nillable="true"/>
<element name="trace" type="xsd:string" nillable="true"/>
</sequence>
</complexType>
I get the flowwing generated for me:
public class WSException extends org.apache.axis.AxisFault implements java.io.Serializable {...}
And then when I use axis as a client too, the method throws back that exception that I can catch directly (nothing to cast).
However there can be a small problem. Since I have a lot of WebServices, I wanted to reuse the WSException in all of them, so I defined it in its own XSD file, in its own namespace. ie: the exception is defined in namespace A and the WebService namespace is B.
When the exception is returned, the namespace is A, when it should be B (because the operation is in B, it is in the SOAP standard). So I had to define a new constructor to override this problem:
public WSException(String namespace) {
super(new javax.xml.namespace.QName(namespace, "WSException"), null, null, null);
}
super(new javax.xml.namespace.QName(namespace, "WSException"), null, null, null);
}
Since I use axis 1.2-RC3 to generate my java classes, I don't know if this problem has been fixed in later versions.
I use Axis, gSOAP and ActiveBPEL and all of them can handle my custom exception.
Hope it can help,
Daniel
On 8/4/06, Eric Borisow <[EMAIL PROTECTED]> wrote:
Derek,
Thanks for the reply, but I have found the answer. I
found most of the answer in the Axis samples\faults
directory, but they leave out some info. I will post
what I found so it will hopefully help someone else.
1. Your Exception should extend Exception and not
RemoteException.
This should be done for a few reasons:
a) It is the approach that the samples use.
b) You probably would rather extend Exception than
RemoteException as a general programming practice.
c) I, personally, did not seem to get this working if
I used RemoteException. Axis gives you a
RemoteException that is your class, but I could not
find a way to correctly cast it back to my Exception.
2. Your Exception must have a constructor that accepts
all of the properties to be set.
There is a technical reason here that I read in one of
the posts out there, but I can't remember where it is.
It was something about Axis needing to be able to set
these properties in the Constructor and not in a
setter. Here is my sample Exception:
import java.io.Serializable;
public class TestException extends Exception
implements Serializable
{
private String someError;
public TestException() {}
public TestException(String someError)
{
this.someError = someError;
}
public String getSomeError()
{
return this.someError;
}
public void setSomeError(String someError)
{
this.someError = someError;
}
}
3. Your service should throw RemoteException and the
custom Exception.
Here is a sample:
import java.rmi.RemoteException;
public interface IServiceTest
{
public void throwError() throws RemoteException,
TestException;
}
4. Catch AxisFault in your client.
If you're using the stubs generated by Axis, you don't
need to worry about this, but if you're using what I
like to call the manual method, then you need to catch
it as an AxisFault.
Here is the sample code:
import java.io.StringWriter;
import java.net.URL;
import java.rmi.RemoteException;
import javax.xml.namespace.QName;
import javax.xml.rpc.Call;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceFactory;
import javax.xml.rpc.encoding.TypeMapping;
import javax.xml.rpc.encoding.TypeMappingRegistry ;
import org.apache.axis.AxisFault;
import
org.apache.axis.encoding.ser.BeanDeserializerFactory;
import
org.apache.axis.encoding.ser.BeanSerializerFactory;
import org.apache.xml.serialize.OutputFormat ;
import org.apache.xml.serialize.XMLSerializer;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.spx.services.TestException;
public class ManualServiceTest
{
/**
* @param args
*/
public static void main(String[] args)
{
try
{
ServiceFactory serviceFactory =
ServiceFactory.newInstance();
Service service =
serviceFactory.createService(new
QName("urn:axisexceptiontest", "ServiceService"));
Call call = (Call)
service.createCall();
String endpointURL =
" http://localhost:8080/axisexceptiontest/services/axisexceptiontest";
call.setTargetEndpointAddress(new
URL(endpointURL).toString());
call.setOperationName( new
QName("urn:axisexceptiontest", "throwError") );
TypeMappingRegistry registry =
service.getTypeMappingRegistry();
TypeMapping map =
registry.getDefaultTypeMapping();
// Don't forget to register your exception!!!
QName faultQName = new
QName("urn:axisexceptiontest", "TestException");
map.register(TestException.class,
faultQName,
new BeanSerializerFactory(TestException.class,
faultQName),
new BeanDeserializerFactory(TestException.class,
faultQName));
call.invoke(new Object[] { });
}
catch(AxisFault fault)
{
System.out.println("Error type is Axis
Fault");
System.out.println ("Fault actor : "+
fault.getFaultActor());
System.out.println("Fault string: "+
fault.getFaultString());
System.out.println("Fault reason: "+
fault.getFaultReason ());
System.out.println("Fault code: "+
fault.getFaultCode());
Object cause = fault.getCause();
if (cause != null)
{
System.out.println ("Class of cause is:
" + cause.getClass().getName());
if (cause instanceof TestException)
{
TestException myEx =
(TestException) cause;
System.out.println("Error message
from my exception: " + myEx.getSomeError());
}
}
}
}
}
Finally, here was my server-config.wsdd:
<?xml version=" 1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java=" http://xml.apache.org/axis/wsdd/providers/java">
<globalConfiguration>
<parameter name="adminPassword" value="admin"/>
<parameter name="sendMultiRefs" value="false"/>
<parameter name="sendXsiTypes" value="true"/>
<parameter name="sendXMLDeclaration" value="true"/>
<parameter name="dotNetSoapEncFix" value="true"/>
</globalConfiguration>
<handler name="LocalResponder"
type="java:org.apache.axis.transport.local.LocalResponder"/>
<handler name="URLMapper"
type="java:org.apache.axis.handlers.http.URLMapper "/>
<handler name="Authenticate"
type="java:org.apache.axis.handlers.SimpleAuthenticationHandler"/>
<handler name="MsgDispatcher"
type="java:org.apache.axis.providers.java.MsgProvider "/>
<handler name="RPCDispatcher"
type="java:org.apache.axis.providers.java.RPCProvider"/>
<service name="axisexceptiontest" provider="java:RPC"
style="rpc" use="encoded">
<parameter name="allowedMethods" value="*"/>
<parameter name="wsdlPortType" value="Service"/>
<parameter name="className"
value="com.spx.services.Service "/>
<parameter name="wsdlServicePort"
value="axisexceptiontest"/>
<parameter name="wsdlTargetNamespace"
value="urn:axisexceptiontest"/>
<parameter name="wsdlServiceElement"
value="ServiceService"/>
<beanMapping qname="ns:TestException"
xmlns:ns="urn:axisexceptiontest"
languageSpecificType="java:com.spx.services.TestException "/>
</service>
<service name="AdminService" provider="java:MSG">
<parameter name="allowedMethods"
value="AdminService"/>
<parameter name="enableRemoteAdmin" value="true"/>
<parameter name="className"
value="org.apache.axis.utils.Admin"/>
<namespace>http://xml.apache.org/axis/wsdd/</namespace>
</service>
<service name="Version" provider="java:RPC">
<parameter name="allowedMethods"
value="getVersion"/>
<parameter name="className"
value="org.apache.axis.Version"/>
</service>
<transport name="http">
<requestFlow>
<handler type="URLMapper"/>
<handler
type="java:org.apache.axis.handlers.http.HTTPAuthHandler "/>
</requestFlow>
</transport>
<transport name="local">
<responseFlow>
<handler type="LocalResponder"/>
</responseFlow>
</transport>
</deployment>
I hope this helps someone else.
Thanks,
Eric
--- Derek <[EMAIL PROTECTED]> wrote:
> In general, you cannot send arbitrary exceptions to
> remote clients, since
> Axis (or most other client/server communication
> protocols) has no idea how
> to serialize/deserialize an arbitrary exception that
> you might have created
> so that it can be transmitted to a remote client.
> You should probably only
> be sending subclasses of RemoteException, and
> probably should include very
> limited, if any, additional information in the
> exception class itself. I
> suggest that you make sure that your TestException
> extends RemoteException,
> not just Exception.
>
> I am not sure how this works if a RemoteException
> has a 'cause' field which
> is not a RemoteException. I am not an expert in what
> RemoteException is
> capable of, but I think I know enough to understand
> that what you are trying
> to do (throw an exception that is not derived from
> RemoteException from
> server to client) is not, in general, possible.
>
> Derek
>
>
>
> > -----Original Message-----
> > From: Eric Borisow [mailto:[EMAIL PROTECTED]]
> > Sent: Thursday, August 03, 2006 6:33 AM
> > To: [email protected]
> > Subject: Re: Question about handling custom
> exceptions in Axis 1.3
> >
> >
> > I tried using this line:
> >
> > TestException myEx = (TestException) gbe;
> >
> > But, it won't even compile. It gives me the
> error:
> > Cannot cast from RemoteException to TestException.
> Is
> > there something I am missing?
> >
> > Thanks,
> > Eric
> >
> > --- xu cai <[EMAIL PROTECTED]> wrote:
> >
> > > AxisFault extends from RemoteException, I think
> you
> > > can simply cast
> > > RemoteException to your customized exception.
> hope
> > > it works.
> > >
> > > -jeff
> > >
> > >
> > > On 8/3/06, Eric Borisow <[EMAIL PROTECTED]>
> wrote:
> > > >
> > > > Hi,
> > > >
> > > > I have been trying to piece together the best
> way
> > > to
> > > > generate and consume a custom exception with
> Axis
> > > > 1_3. I have created a test with an interface,
> a
> > > > service implementation of the interface and an
> > > > Exception.
> > > >
> > > > When I generate the wsdl using java2wsdl, the
> wsdl
> > > > contains a reference to the TestException
> class as
> > > a
> > > > fault of the service. When I call the
> service, it
> > > > returns an AxisFault containing information
> about
> > > the
> > > > fault. My question is... what can I do with
> that
> > RemoteException to
> > > > get my exception out of it? I
> > > have
> > > > seen some other articles where it seems you
> should
> > > > just be able to catch your custom exception
> but
> > > all I
> > > > ever get is RemoteException which I then have
> to
> > > > convert to an AxisFault but I still don't get
> > > access
> > > > to my exception per se. See below for my
> code.
> > > >
> > > > Thanks,
> > > > Eric
> > > >
> > > > Interface:
> > > >
> > > > public interface IServiceTest
> > > > {
> > > > public void throwError() throws
> TestException;
> > > > }
> > > >
> > > > Service implementation:
> > > >
> > > > public class Service implements IServiceTest
> > > > {
> > > >
> > > > public void throwError() throws
> TestException
> > > > {
> > > > throw new TestException();
> > > > }
> > > >
> > > > }
> > > >
> > > > Exception:
> > > >
> > > > import java.io.Serializable;
> > > >
> > > > public class TestException extends Exception
> > > > implements Serializable
> > > > {
> > > > private String someError;
> > > >
> > > > public TestException() {}
> > > >
> > > > public TestException(String someError)
> > > > {
> > > > this.someError = someError;
> > > > }
> > > >
> > > > public String getSomeError()
> > > > {
> > > > return someError;
> > > > }
> > > >
> > > > public void setSomeError(String someError)
> > > > {
> > > > this.someError = someError;
> > > > }
> > > >
> > > >
> > > > }
> > > >
> > > > wsdl:
> > > >
> > > > <?xml version="1.0" encoding="UTF-8"?>
> > > > <wsdl:definitions
> > > > targetNamespace="http://services.spx.com "
> > > > xmlns:impl="http://services.spx.com"
> > > > xmlns:intf="http://services.spx.com"
> > > >
> xmlns:apachesoap="http://xml.apache.org/xml-soap"
> > > >
> > >
> >
>
xmlns:wsdlsoap=" http://schemas.xmlsoap.org/wsdl/soap/"
> > > >
> > >
> >
>
xmlns:soapenc=" http://schemas.xmlsoap.org/soap/encoding/"
> > > > xmlns:xsd="http://www.w3.org/2001/XMLSchema"
> > > > xmlns:wsdl=" http://schemas.xmlsoap.org/wsdl/">
> > > > <!--WSDL created by Apache Axis version: 1.3
> > > > Built on Oct 05, 2005 (05:23:37 EDT)-->
> > > > <wsdl:types>
> > > > <schema
> xmlns="http://www.w3.org/2001/XMLSchema"
> > > > targetNamespace="http://services.spx.com ">
> > > > <import
> > > >
> > >
> >
>
namespace="http://schemas.xmlsoap.org/soap/encoding/ "/>
> > > > <complexType name="TestException">
> > > > <sequence>
> > > > <element name="someError" nillable="true"
> type="xsd:string"/>
> > > > </sequence>
> > > > </complexType>
> > > > </schema>
> > > > </wsdl:types>
> > > > <wsdl:message name="TestException">
> > > > <wsdl:part name="fault"
> > > > type="impl:TestException"/>
> > > > </wsdl:message>
> > > > <wsdl:message name="throwErrorRequest">
>
=== message truncated ===
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
