This is the first article where I discuss details or issues using wsc (JAVA) on an Oracle WebLogic platform to integrate Customer Legacy systems with Salesforce CRM.
In some environments (specifically the WLS 10.3.5 used as production environment at my current Customer) the wsc infrastructure throws a ConnectionException
(com.sforce.ws.ConnectionException: Unexpected element
) in situations where it should actually return a Fault (com.sforce.soap.enterprise.fault.ApiFault
).
I have tried to mock a similar environment in order to demonstrate the problem to no avail.
But, I have discovered why the problem arises – it has to do with the infrastructure related to the Transport.isSuccessful()
.
The exception is similar to the one below:
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 ... |
The problem is that the code in SoapConnection
(com.sforce.ws.transport.SoapConnection:146
) gets confused by the Transport
object returning true from the isSuccessful()
method. Then it goes on to create the expected response type in the bind()
method, which fails because it does not expect a Fault…
My first solution (described in sfdc-wsc: Issue 64) was to hack the bind()
method to handle unexpected Faults and not just the expected return type…
That hack was not optimum as the real issue was not discovered – basically because of lack of an environment where I could debug the issue.
After a while it became obvious that the real problem was that the Transport
object returned “success” even if the infrastructure returned Fault. This again is related to the jre specific implementations of the HttpURLConnection
…
The JavaDoc is not clear on this, but some implementations throw an IOException
on getInputStream()
and some does not, when the server returns an error. I.e the code below is not stable across different environments/implementations:
191 192 193 194 195 196 197 198 199 200 201 202 203 204 | public InputStream getContent() throws IOException { InputStream in; try { successful = true; in = connection.getInputStream(); } catch (IOException e) { successful = false; in = connection.getErrorStream(); if (in == null) { throw e; } } ... |
Basically the successful
flag is left as true even if the service returns an error.
Changing the above lines of code of the getContent()
method in the JdkHttpTransport
class (com.sforce.ws.transport.JdkHttpTransport:191
) seems to make the code robust, as it does not set the flag based on a possible exception, but from determining the HTTP response code from the server:
191 192 193 194 195 196 197 198 199 200 201 202 203 204 | 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; ... |
This solution has been added in the comments to the issue and we can hope it gets included in a future version of the wsc tool 🙂
HI Jesper,
I am seeing this with an older version of the WSC-22 on a Weblogic Server. Can you confirm that this was resolved by newer releases of the Web Services Connector? Or do I have to implement your proposed solution?
Thanks in advance for your reply!
Steve B
Yes, I fixed it in “my” wsc-23 located at http://code.google.com/p/sfdc-wsc/downloads/list
Please note that this is a fork of the official wsc located at: https://github.com/forcedotcom/wsc
Brgds
Danish Paul