zhangjixing / sfdc-wsc

Automatically exported from code.google.com/p/sfdc-wsc
0 stars 0 forks source link

ConnectionException should have been Fault #64

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
I'm seeing situations where the wsc infrastructure throws a ConnectionException 
when it should have returned a Fault; e.g.:

com.sforce.ws.ConnectionException: Unexpected element. Parser was expecting 
element 'urn:enterprise.soap.sforce.com:upsertResponse' but found 
'http://schemas.xmlsoap.org/soap/envelope/:Fault'
    at com.sforce.ws.bind.TypeMapper.verifyTag(TypeMapper.java:386)
    at com.sforce.ws.transport.SoapConnection.bind(SoapConnection.java:166)
    at com.sforce.ws.transport.SoapConnection.receive(SoapConnection.java:147)
    at com.sforce.ws.transport.SoapConnection.send(SoapConnection.java:98)
    at com.sforce.soap.enterprise.EnterpriseConnection.upsert(EnterpriseConnection.java:856)
    at ...

This happens with wsc-22 on Weblogic 10.3.5, Linux - it does not happen with a 
similar "testbed configuration"...

I have found the issue to be caused by Transport.isSuccessful() returning true, 
even if SFDC returns HTTP code 500. 
Further, this is caused by the "connection.getInputStream()" in the 
JdkHttpTransport not throwing an IOException when the HTTP server returns an 
error:

        try {
            successful = true;
            in = connection.getInputStream(); // <== does *not* throw IOException (line 196)
        } catch (IOException e) {
            successful = false;
            in = connection.getErrorStream();
            if (in == null) {
                throw e;
            }
        }

I've added a hack in "our" SoapConnection to deal with this issue. It could 
probably be done by a more robust implementation of "isSuccessful()" in 
JdkHttpTransport.

The hack is... in SoapConnection.bind():

        try {
            typeMapper.verifyTag(responseElement.getNamespaceURI(),responseElement.getLocalPart(), xin.getNamespace(), xin.getName());
        } catch (final ConnectionException original) {
            // HACK 1: If mapping type to expected fails, expect we're having a fault
            ConnectionException x = original;
            try {
                // create fault from response
                x = createException(xin, true);
            } catch (final ConnectionException ignored) {
                // HACK 2: If it was not a fault, throw the original exception
                throw original;
            }
            // throw fault
            throw x;
        }

...and in SoapConnection.createException():

    private ConnectionException createException(XmlInputStream xin, boolean hack) throws IOException, ConnectionException {
        if (!hack) {
            readSoapEnvelopeStart(xin);
        }

...

See attached.

Hope this might be of help to anyone with similar issues.

Jesper Udby

Original issue reported on code.google.com by jesperudby on 5 Dec 2012 at 9:06

Attachments:

GoogleCodeExporter commented 8 years ago
Hi.

A much simpler approach where only the getContent() method of JdkHttpTransport 
is changed, ref below from line 191:

    public InputStream getContent() throws IOException {
        InputStream in;

        try {
            in = connection.getInputStream();
        } catch (IOException e) {
            in = connection.getErrorStream();
            if (in == null) {
                throw e;
            }
        }

        this.successful = connection.getResponseCode() < 400;
...

See attached.

Regards

Jesper Udby

Original comment by jesperudby on 5 Jan 2013 at 8:41

Attachments:

GoogleCodeExporter commented 8 years ago
Included in 23

Original comment by jesperudby on 31 Jan 2013 at 8:30

GoogleCodeExporter commented 8 years ago
fixed in 23

Original comment by jesperudby on 8 Feb 2013 at 6:37