The SoapConnection
java class sports a private static inner Exception
, the SessionTimedOutException
. This Exception
is used internally only to quickly pass control from the parseDetail()
method back to the send()
method.
This is bad practice, using an Exception to control flow of execution. And in this case the infrastructure is doing exception handling in the first place… There has to be a better way.
First thing is to remove the SessionTimedOutException
private static inner class.
Then change the parseDetail()
method as follows to always just throw the correct exception:
228 229 230 231 232 233 234 235 | try { e = (ConnectionException) typeMapper.readObject(xin, info, ConnectionException.class); if (e instanceof SoapFaultException) { ((SoapFaultException)e).setFaultCode(faultCode); } } catch (ConnectionException ce) { throw new ConnectionException("Failed to parse detail: " + xin + " due to: " + ce, ce.getCause()); } |
Biggest modification is to be in the send()
method. But before we do that we’re introducing a little convenience method: isSessionTimedOutFault()
. This basically implements the test that before was in the hack in the parseDetail()
method above:
private boolean isSessionTimedOutFault(SoapFaultException sfe) { return "INVALID_SESSION_ID".equals(sfe.getFaultCode().getLocalPart()) && sfe.getMessage() != null && (sfe.getMessage().contains("Session timed out") || sfe.getMessage().contains("Session not found")); } |
Now we’re ready to modify the send()
method. Not only do we get rid of the SessionTimedOutException
and simplify the implementation, we also fix a minor bug in reporting the calculated request period if the second operation try after the SessionRenewer
has done its work fails with a SocketTimeoutException
:
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | public XMLizable send(String soapAction, QName requestElement, XMLizable request, QName responseElement, Class<?> responseType) throws ConnectionException { long startTime = 0; try { boolean firstTime = true; while(true) { try { startTime = System.currentTimeMillis(); Transport transport = newTransport(config); OutputStream out = transport.connect(url, soapAction); sendRequest(out, request, requestElement); InputStream in = transport.getContent(); return receive(transport, responseElement, responseType, in); } catch (SoapFaultException se) { if (config.getSessionRenewer() != null && firstTime && isSessionTimedOutFault(se)) { SessionRenewer.SessionRenewalHeader sessionHeader = config.getSessionRenewer().renewSession(config); if (sessionHeader != null) { addHeader(sessionHeader.name, sessionHeader.headerElement); } } else { throw se; } } firstTime = false; } } catch (SocketTimeoutException e) { long timeTaken = System.currentTimeMillis() - startTime; throw new RequestTimedOutException("Request to " + url + " timed out. TimeTaken=" + timeTaken + " ConnectionTimeout=" + config.getConnectionTimeout() + " ReadTimeout=" + config.getReadTimeout(), e); } catch (IOException e) { throw new ConnectionException("Failed to send request to " + url, e); } } |
This has not yet been added as feature to the WSC issues list – I’m awaiting them to respond to the other requests I’ve added 🙂