Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remote SOAP web service keeps breaking connection

Short Description

I'm using JBoss SwitchYard to connect to secured remote SOAP web service. For some reason after the request is sent; remote web service is stopping any further communication; so I'm not receiving a response.

Question

I need an idea or solution what could be a problem here.

Error

Caused by: java.net.SocketException: SocketException invoking https://**********.asmx: Unexpected end of file from server

Description and notes

  • Remote web service is using self-signed certificate; I have imported server certificate into my local truststore + plus I have my other certificate (in my keystore) to identify myself to the remote server.
  • Thanks to -Djavax.net.debug=all SSL debug logs and Wireshark logs I know that both client and server made a successful SSL handshake and client has successfully sent a request.
  • The server also uses IP filtering to allow a direct communication and my IP is whitelisted.
  • If I try to send the same XML request via SoapUI it works just fine and I receive a response. You should take into account that SoapUI only uses keystore; it is set to always trust remote services so no truststore is needed or used.
  • Now comes the funny part. If I use a Fiddler (free web debugging proxy) as a "man in the middle" between my JBoss SwitchYard and remote web service (to see what is happening), suddenly everything works.
  • The only difference between direct connection and using Fiddler as a proxy is that in real connection Connection = Keep-Alive header parameter is used and in Fiddler case, Proxy-Connection = Keep-Alive parameter is used. I don't know is there any other significant difference.
  • If I manually change these header parameters in SoapUI I still receive a successful response. A connection will fail only if I'm missing SOAPAction and Content-Type header parameters, but they are present in each case (and are the same).
  • When I observe this communication via Wireshark only difference I can see is that remote server is stopping further communication (when JBoss Switchyard application is directly communicating with remote web service).
  • I don't have an access to remote logs nor I'm allowed to get them. So I'm working blind.
  • In each case (With or without Fiddler) I'm using a company Proxy to reach remote web Service. This proxy is not a problem because other SwitchYard applications are working just fine.

Tools

  • JBoss EAP 6.4
  • JBoss SwitchYard 2.0.1.redhat-621159
like image 250
Gajotres Avatar asked May 15 '17 08:05

Gajotres


2 Answers

Exception

java.net.SocketException: Unexpected end of file from server

This exception implies that server already accepted your connection, which means your SSL handshake is indeed succeed. But the server closed the connection (by a TCP reset or fin) before you can get the response.

A reset is usually sent in two cases:

  • persistent connection (keep alive connection) with config exceed
  • server restarted lost the connection

Usually, a persistent connection has two config:

Keep-Alive: timeout=15, max=100

timeout means time in seconds, max means max requests.

Connection vs Proxy Connection

Let's compare the three different cases you have described:

  • SoapUI: succeed; ?
  • Direct Connection: fail; Connection = Keep-Alive
  • Fiddler: succeed; Proxy-Connection = Keep-Alive

In the third case, if I understand you right, your persistent connection is from client to proxy and from proxy to server is not clear.

 client----->Proxy----->server

Suggestions

  • try to get the server's persistent connection config from response (like here), to see if direct connection exceed the time or numbers of limit
  • try to not use persistent connection: java -Dhttp.keepalive=false

Ref

  • fin vs rst in tcp
  • keep alive header
like image 61
Tony Avatar answered Nov 19 '22 12:11

Tony


Issue might be due to invalid header or Invalid format of SOAP request, You can try like below code

1 You need HeaderHandlerResolver

 public class HeaderHandlerResolver implements HandlerResolver {

        public List<Handler> getHandlerChain(PortInfo portInfo) {
            List<Handler> handlerChain = new ArrayList<Handler>();

            HeaderHandler hh = new HeaderHandler();

            handlerChain.add(hh);

            return handlerChain;
        }
    }

Then You need to add on HeaderHandler class

 public class HeaderHandler implements SOAPHandler<SOAPMessageContext> {

        public boolean handleMessage(SOAPMessageContext smc) {

            Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

            if (outboundProperty.booleanValue()) {

                SOAPMessage message = smc.getMessage();

                try {

                    SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope();

                    SOAPHeader header = envelope.getHeader();
                    header.setPrefix("soapenv");
                    header.setAttribute("xmlns:wsa", "http://www.w3.org/2005/08/addressing");

                    SOAPElement security =
                            header.addChildElement("Security", "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");

                    SOAPElement usernameToken =
                            security.addChildElement("UsernameToken", "wsse");
                    usernameToken.addAttribute(new QName("xmlns:wsu"), "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");

                    SOAPElement username =
                            usernameToken.addChildElement("Username", "wsse");
                    username.addTextNode("USERNAME");

                    SOAPElement password =
                            usernameToken.addChildElement("Password", "wsse");
                    password.setAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
                    password.addTextNode("PASSWORD");

                    SOAPElement encode =
                            usernameToken.addChildElement("Nonce", "wsse");
                    encode.setAttribute("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
                    encode.addTextNode(generateNonce());

                    Calendar createdTime = new GregorianCalendar(TimeZone.getTimeZone("IST"));
                    Date todayDate = createdTime.getTime();
                    todayDate.setTime(todayDate.getTime()-20000000);

                    SOAPElement created = usernameToken.addChildElement("Created", "wsu");
                    created.addTextNode(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sss'Z'").format(todayDate));

                    SOAPElement action = header.addChildElement("Action", "wsa");
                    //YOUR ACTION URL SHOULD BE in BELOW Text Content
                    action.setTextContent("SET HERE YOUR ACTION URL");

                    message.saveChanges();
                    message.writeTo(System.out);
                    System.out.println("");

                } catch (Exception e) {
                    e.printStackTrace();
                }

            } else {
                try {

                    //This handler does nothing with the response from the Web Service so
                    //we just print out the SOAP message.
                    SOAPMessage message = smc.getMessage();
                    message.writeTo(System.out);
                    System.out.println("");
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }


            return outboundProperty;

        }

        public Set getHeaders() {
            return null;
        }

        public boolean handleFault(SOAPMessageContext context) {
            return true;
        }

        public void close(MessageContext context) {
        }

        private static String generateNonce() throws NoSuchAlgorithmException, NoSuchProviderException, UnsupportedEncodingException {
            String dateTimeString = Long.toString(new Date().getTime());
            byte[] nonceByte = dateTimeString.getBytes();
            return Base64.encodeBase64String(nonceByte);
        }
    }

Now Finally Your Main class for call SOAP service

public class SoapClientClass {

    public static void main(String[] args) {

        ImplService service = new ImplService();
        HeaderHandlerResolver handlerResolver = new HeaderHandlerResolver();
        service.setHandlerResolver(handlerResolver);

        ResponseClass port = service.getPortClass();

        Response response = null;
        try {
            response = port.getServerMehotd("Params");
        } catch (PolicyException_Exception e) {
            e.printStackTrace();
        } catch (ServiceException_Exception e) {
            e.printStackTrace();
        }

        }
    }
}

Also, make sure your generated code from wsdl file uptodate and server location url also correct.

Hope its resolve your problem

like image 1
Piyush Ghediya Avatar answered Nov 19 '22 12:11

Piyush Ghediya