This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 173668 - generated fault is never thrown , but instead client receive javax.xml.ws.soap.SOAPFaultException
Summary: generated fault is never thrown , but instead client receive javax.xml.ws.soa...
Status: RESOLVED WONTFIX
Alias: None
Product: webservices
Classification: Unclassified
Component: JAX-WS (show other bugs)
Version: 5.x
Hardware: Macintosh All
: P3 blocker (vote)
Assignee: Milan Kuchtiak
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-10-02 22:57 UTC by sandi_ro
Modified: 2009-10-07 12:58 UTC (History)
0 users

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description sandi_ro 2009-10-02 22:57:10 UTC
Exception generated by wsimport in code are never thrown.

Step1 : web application with below web service :

@WebService()
public class WebExTest {

    /**
     * Web service operation
     */
    @WebMethod(operationName = "doTest")
    public int doTest(@WebParam(name = "theCase") int theCase)
            throws MathFault, WebFault
    {
        if(0== theCase){
            return 1;
        }
        if(1==theCase){
            throw new MathFault("MathFault");
        }

        throw new WebFault("WebFault");

    }

}


client app that reference above service:

public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        WebExTestService service = new WebExTestService();
        WebExTest port = service.getWebExTestPort();



        testRun(0, port);
        testRun(1, port);
        testRun(2, port);
    }

    private static void testRun(int theCase, WebExTest port)
    {
        System.out.println("port.doTest("+theCase+")-Start");
        try {
            int res = port.doTest(theCase);
            System.out.println("port.doTest("+theCase+")-no exception");
        } catch (MathFault_Exception ex) {
            System.out.println("port.doTest("+theCase+")-MathFault");
        } catch (WebFault_Exception ex) {
            System.out.println("port.doTest("+theCase+")-WebFault");
        }catch(SOAPFaultException ex){
            System.out.println("port.doTest("+theCase+")-SOAPFaultException: "+ ex.getMessage());
        }
    }

}


actual result console output is:
port.doTest(0)-Start
port.doTest(0)-no exception
port.doTest(1)-Start
port.doTest(1)-SOAPFaultException: MathFault
port.doTest(2)-Start
port.doTest(2)-SOAPFaultException: WebFault


expected result:

port.doTest(0)-Start
port.doTest(0)-no exception
port.doTest(1)-Start
port.doTest(1)-MathFault
port.doTest(2)-Start
port.doTest(2)-WebFault

Analysis:
Navigating to the port.doTest code we find:
    /**
     * 
     * @param theCase
     * @return
     *     returns int
     * @throws MathFault_Exception
     * @throws WebFault_Exception
     */
    @WebMethod
    @WebResult(targetNamespace = "")
    @RequestWrapper(localName = "doTest", targetNamespace = "http://asuhan.com/", className = "com.asuhan.DoTest")
    @ResponseWrapper(localName = "doTestResponse", targetNamespace = "http://asuhan.com/", className = "com.asuhan.DoTestResponse")
    public int doTest(
        @WebParam(name = "theCase", targetNamespace = "")
        int theCase)
        throws MathFault_Exception, WebFault_Exception
    ;


therefore the IDE will offer to add code to handle MathFault_Exception and WebFault_Exception but not SOAPFaultException , 
the behaviour of throwing SOAPEXception is error prone and counterintuitive.
Comment 1 Milan Kuchtiak 2009-10-05 12:37:13 UTC
Looks more like a JAX-WS problem.
Investigating more to detect the real source.  
Comment 2 Milan Kuchtiak 2009-10-05 13:31:45 UTC
What version of JAX-WS do you use ?

Tested with JAX-WS 2.2, and it works.

My generated stub, for the same method, looks a little bit different:

    @WebMethod
    @WebResult(targetNamespace = "")
    @RequestWrapper(localName = "doTest", targetNamespace = "http://math/", className = "math.DoTest")
    @ResponseWrapper(localName = "doTestResponse", targetNamespace = "http://math/", className = "math.DoTestResponse")
    @Action(input = "http://math/MathService/doTestRequest", output = "http://math/MathService/doTestResponse", fault = {
        @FaultAction(className = MathFault_Exception.class, value = "http://math/MathService/doTest/Fault/MathFault"),
        @FaultAction(className = WebFault_Exception.class, value = "http://math/MathService/doTest/Fault/WebFault")
    })
    public int doTest(
        @WebParam(name = "theCase", targetNamespace = "")
        int theCase)
        throws MathFault_Exception, WebFault_Exception
    ;

I guess, this was a JAX-WS issue that was fixed already.
Netbeans cannot do anything with that.
Comment 3 sandi_ro 2009-10-06 09:31:51 UTC
Hi, 

I see, I wonder how many eons will pass until jdk gets updated to provide right tools for developers. Maybe jdk7 will be
better in this respect.

Thanks, 
Andrei.

Comment 4 sandi_ro 2009-10-06 15:33:50 UTC
Hi,

I wonder how to setup jaxws22 to get similar result. Could you successfully deploy on tomcat ? 

I could not find any user friendly ui to switch implementation and I resorted to change the jaxws-build.xml 
If we encounter such problems with different implementations of jaxws then a required item would be to be able to easily
switch them , configure their class paths and other related options. 

Can you point for some instruction on how to change jaxws implementations for netbeans ? 

Thanks, Andrei.
Comment 5 sandi_ro 2009-10-06 15:47:59 UTC
Found the way to reproduce your result:

1) download jaxws22 jar from java 
2) create jaxws22 library
3) remove old jaxws2.1 dependencies from both server and client
4) add jaxws22 library to both server and client
5) on client make sure wsimport task has xendorsed = true in "Edit WebService Editor" -Wsimport options tab 
6) on client change jaxws-build.xml so that classpath points to the new jaxws22 library
7) on server change jaxws-build.xml so that wsgen task has xendorsed = true 
8) on server change jaxws-build.xml so that wsgen clapath encounters first the newly added jaxws22
9) clean server, build server, deploy 
10) clean client, refresh output 


Pretty tedious , time consumming and error prone process. Please enhance netbeans to be able to easily change jaxws
imlementations. ( I add this as enhancement : 173884 )


Thanks, Andrei.
Comment 6 sandi_ro 2009-10-06 17:57:39 UTC
Hi, 

After diging my way to using jaxws2.2 
I get the generated code look like yours example but I stil get SOAP fault instead of expected fault:
javax.xml.ws.soap.SOAPFaultException: 
        at com.sun.xml.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:189)
        at com.sun.xml.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:130)
        at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:119)
        at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:89)
        at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:130)
------------------- <more here> -------


looking in the jaxws22 sources : 
SOAP11Fault.java: 
    protected Throwable getProtocolException() {
        try {
            SOAPFault fault = SOAPVersion.SOAP_11.saajSoapFactory.createFault(faultstring, faultcode);
            if(detail != null){
                Detail d = fault.addDetail();
                for(Element det : detail.getDetails()){
                    Node n = fault.getOwnerDocument().importNode(det, true);
                    d.appendChild(n);
                }
            }
            fault.setFaultActor(faultactor);
            return new SOAPFaultException(fault);
        } catch (SOAPException e) {
            throw new WebServiceException(e);
        }
    }

looks like always returning a SOAPFaultException.
and SOAPFaultBuilder fails to get an exception (ie: CheckedExceptionImpl ce = exceptions.get(detailName); is null in
below methood ):

    public Throwable createException(Map<QName, CheckedExceptionImpl> exceptions) throws JAXBException {
        DetailType dt = getDetail();
        Node detail = null;
        if(dt != null)  detail = dt.getDetail(0);

        //return ProtocolException if the detail is not present or there is no checked exception
        if(detail == null || exceptions == null){
            // No soap detail, doesnt look like its a checked exception
            // throw a protocol exception
            return attachServerException(getProtocolException());
        }

        //check if the detail is a checked exception, if not throw a ProtocolException
        QName detailName = new QName(detail.getNamespaceURI(), detail.getLocalName());
        CheckedExceptionImpl ce = exceptions.get(detailName);
        if (ce == null) {
            //No Checked exception for the received detail QName, throw a SOAPFault exception
            return attachServerException(getProtocolException());

        }

        if (ce.getExceptionType().equals(ExceptionType.UserDefined)) {
            return attachServerException(createUserDefinedException(ce));

        }
        Class exceptionClass = ce.getExceptionClass();
        try {
            Constructor constructor = exceptionClass.getConstructor(String.class, (Class) ce.getDetailType().type);
            Exception exception = (Exception) constructor.newInstance(getFaultString(), getJAXBObject(detail, ce));
            return attachServerException(exception);
        } catch (Exception e) {
            throw new WebServiceException(e);
        }
    }

Therefore I think that jaxws2.2 does not properly fix the issue. Please consider reopening this . 

Thanks, Andrei.
Comment 7 Milan Kuchtiak 2009-10-07 12:58:57 UTC
Tested with Tomcat - no problem. What version of JDK do you use ?

May be I am wrong, but these strange results may be caused by not using endorsed mechanism.

Looks like your WS Client project uses JAX-WS API from JDK (JAX-WS 2.0 or JAX-WS 2.1), not the one added on project
classpath.
try to set-up JVM Option -Djava.endorsed.dirs=JAX_WS_2.2/lib (in J2SE project properties -> Run -> VM Option)