I've done some more investigating on this and this is what I've come up with. Hopefully, this will help others who have run into this same issue :)
All of the following refer to the client. 1) Because of the signature for the Call.invoke methods in the JAX-RPC spec, Axis cannot throw arbitrary checked exceptions. Therefore, it creates and throws AxisFault (which extends RemoteException) in most fault cases. This seems like an oversight in the JAX-RPC spec to me but I'm sure the people who wrote that know more about it than I do ;) 2) If the AxisFault has a "detail" (or "cause") which is an instance of RemoteException, it will throw that instead. That's one of the reasons I was able to get back the desired exception (instead of an AxisFault) when extending RemoteException. 3) When constructing an AxisFault (in the cases of a non-RemoteException server-specific exception), the "detail" on the AxisFault is not properly initialized (it is null). Therefore, there is no way to retrieve the wrapped exception and re-throw it in the client. 4) The "deserialization" of faults happens in the org.apache.axis.message.SOAPFaultBuilder class. The workhorse in that class is the "createFault" method. At one point in this method, we see the following code: AxisFault f = null; ... ... if (f == null && faultData instanceof RemoteException) { f = AxisFault.makeFault((RemoteException)faultData); } In the example I gave in my last email, at this point in the code faultData is an instance of my TestException. In the case where I extended RemoteException, the resulting AxisFault will properly wrap my TestException. When it does not extend RemoteException, this case ends up falling through and a generic AxisFault is created without the wrapped TestException. From what I can tell, this is the cause for the issue in number 3 above. Question for those who know more about this: Is there any reason that we can't do AxisFault.makeFault() for ANY Exception that comes into SOAPFaultBuilder? Are there any exceptions we don't want to wrap into an AxisFault in this manner? I don't have a problem manually unwrapping the exception from the AxisFault and rethrowing it in my client (dynamic proxy would probably work well for this), but it's kind of hard to do when its not there ;) I was just curious about this and was wondering what others thought. I'm new to Axis so I'm not really 100% sure what is going on inside. It seems like I may be able to patch my source to get it to do what I want. Perhaps I should post a question about this on the developer list? Thanks for your time, Eric Westfall -----Original Message----- From: Westfall, Eric Curtis Sent: Wednesday, December 29, 2004 12:36 PM To: [EMAIL PROTECTED] Subject: Service Specific Exception not working Hello, I've searched the list for answers to this issue and I haven't been able to find any satisfactory ones. I'm having trouble getting "Service Specific Exceptions" as defined in the JAX-RPC specification to work properly. If I define a custom exception and have it extend RemoteException, then it works properly. However, if it simply extends Exception, then I end up with an AxisFault in my client, rather than an instance of the thrown exception. For example, here is my exception definition: package test; public class TestException extends Exception implements java.io.Serializable { private String message; public TestException() { super(); } public TestException(String message) { setMessage(message); } public void setMessage(String message) { this.message = message; } public String getMessage() { return message; } } I have a service with a method "testException" whose definition in the service interface is: public void testException() throws RemoteException, TestException; And the implementation looks like this: public void testException() throws TestException { throw new TestException("This is the TestException message"); } If I execute the "testException" method in a client in the above case. I get back an org.apache.axis.AxisFault with the following stack trace on the client (run from a JUnit test): AxisFault faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException faultSubcode: faultString: test.TestException: This is the TestException message faultActor: faultNode: faultDetail: {}test.TestException:<message xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">This is the TestException message</message> {http://xml.apache.org/axis/}hostname:localhostname test.TestException: This is the TestException message at org.apache.axis.message.SOAPFaultBuilder.createFault(SOAPFaultBuilder.ja va:221) at org.apache.axis.message.SOAPFaultBuilder.endElement(SOAPFaultBuilder.jav a:128) at org.apache.axis.encoding.DeserializationContext.endElement(Deserializati onContext.java:1083) at org.apache.crimson.parser.Parser2.maybeElement(Parser2.java:1712) at org.apache.crimson.parser.Parser2.content(Parser2.java:1963) at org.apache.crimson.parser.Parser2.maybeElement(Parser2.java:1691) at org.apache.crimson.parser.Parser2.content(Parser2.java:1963) at org.apache.crimson.parser.Parser2.maybeElement(Parser2.java:1691) at org.apache.crimson.parser.Parser2.parseInternal(Parser2.java:667) at org.apache.crimson.parser.Parser2.parse(Parser2.java:337) at org.apache.crimson.parser.XMLReaderImpl.parse(XMLReaderImpl.java:448) at javax.xml.parsers.SAXParser.parse(SAXParser.java:345) at org.apache.axis.encoding.DeserializationContext.parse(DeserializationCon text.java:226) at org.apache.axis.SOAPPart.getAsSOAPEnvelope(SOAPPart.java:645) at org.apache.axis.Message.getSOAPEnvelope(Message.java:424) at org.apache.axis.handlers.soap.MustUnderstandChecker.invoke(MustUnderstan dChecker.java:62) at org.apache.axis.client.AxisClient.invoke(AxisClient.java:173) at org.apache.axis.client.Call.invokeEngine(Call.java:2719) at org.apache.axis.client.Call.invoke(Call.java:2702) at org.apache.axis.client.Call.invoke(Call.java:2378) at org.apache.axis.client.Call.invoke(Call.java:2301) at org.apache.axis.client.Call.invoke(Call.java:1758) at org.apache.axis.client.AxisClientProxy.invoke(AxisClientProxy.java:163) at $Proxy0.testException(Unknown Source) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.jav a:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessor Impl.java:25) at java.lang.reflect.Method.invoke(Method.java:324) at org.springframework.remoting.rmi.RmiClientInterceptorUtils.doInvoke(RmiC lientInterceptorUtils.java:93) at org.springframework.remoting.rmi.RmiClientInterceptorUtils.invoke(RmiCli entInterceptorUtils.java:62) at org.springframework.remoting.jaxrpc.JaxRpcPortClientInterceptor.invoke(J axRpcPortClientInterceptor.java:290) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Ref lectiveMethodInvocation.java:138) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAo pProxy.java:152) at $Proxy1.testException(Unknown Source) at test.WebServiceProxy.testException(WebServiceProxy.java:62) at test.ExceptionTest.testTestException(ExceptionTest.java:26) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.jav a:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessor Impl.java:25) at java.lang.reflect.Method.invoke(Method.java:324) at junit.framework.TestCase.runTest(TestCase.java:154) at junit.framework.TestCase.runBare(TestCase.java:127) at junit.framework.TestResult$1.protect(TestResult.java:106) at junit.framework.TestResult.runProtected(TestResult.java:124) at junit.framework.TestResult.run(TestResult.java:109) at junit.framework.TestCase.run(TestCase.java:118) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTe stRunner.java:421) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRun ner.java:305) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRu nner.java:186) However, if I change TestException so that it extends RemoteException, then a TestException rather than the above AxisFault is thrown to my client. This is the behaviour I'm looking for, but I don't want my service specific exceptions to extend RemoteException. I'm puzzled as to why this is happening. Are RemoteExceptions handled differently than regular Exceptions in Axis even though the JAX-RPC specification states that they should be supported? I didn't include my server-deploy.wsdd file or my WSDL files in this email. I can include the relevant parts of those if that would help. In my client and on the server I've got TestException set up to be serialized and deserialized using the BeanSerializerFactory (and BeanDeserializerFactory) which I believe is correct. If anybody has any insight into why Exceptions don't work but RemoteExceptions do, I would really appreciate it. I've been trying to figure this out for a while now :) Thanks in advance for your time, Eric Westfall