SOAPExceptionImpl Bad response: 404Not Found if i don't do soapMessage.writeTo(System.out);
Asked Answered
K

3

7

I'm creating a Soap client in java and I'm getting a strange error.

Abstract client

public abstract class AbstractSoapClient {

    private ServerContext context;

    private String path;

    private static final String WSSE = "";
    private static final String CURL = "";
    private static final String CURL_PASSWORD = "";
    private static final String SECURITY_NODE = "";
    private static final String USERNAME_TOKEN = "";
    private static final String USERNAME_NODE = "";
    private static final String PASSWORD_NODE = "";

    public AbstractSoapClient(ServerContext context) {
        this.context = context;
    }

    protected SOAPMessage createRequest(String path) throws SOAPException {
        this.path = assembleEndpoint(path);
        SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
        SOAPConnection soapConnection = soapConnectionFactory.createConnection();
        SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), this.path);
        soapConnection.close();
        return soapResponse;
    }

    protected void setCredentials(SOAPEnvelope envelope) throws SOAPException {
        SOAPHeader tHeader = envelope.getHeader();
        Name tWsseHeaderName = envelope.createName(SECURITY_NODE, WSSE, CURL);

        SOAPHeaderElement tSecurityElement = tHeader.addHeaderElement(tWsseHeaderName);
        tSecurityElement.setMustUnderstand(false);

        Name tUserTokenElementName = envelope.createName(USERNAME_TOKEN, WSSE, CURL);
        SOAPElement tUserTokenElement = tSecurityElement.addChildElement(tUserTokenElementName);
        tUserTokenElement.removeNamespaceDeclaration(WSSE);
        tUserTokenElement.addNamespaceDeclaration("wsu", CURL);
        // user name child
        Name tUsernameElementName = envelope.createName(USERNAME_NODE, WSSE, CURL);
        SOAPElement tUsernameElement = tUserTokenElement.addChildElement(tUsernameElementName);
        tUsernameElement.removeNamespaceDeclaration(WSSE);
        tUsernameElement.addTextNode(context.getUsername());

        // password child
        Name tPasswordElementName = envelope.createName(PASSWORD_NODE, WSSE, CURL);
        SOAPElement tPasswordElement = tUserTokenElement.addChildElement(tPasswordElementName);
        tPasswordElement.removeNamespaceDeclaration(WSSE);
        tPasswordElement.setAttribute("Type", CURL_PASSWORD);
        tPasswordElement.addTextNode(context.getPassword());
    }

    private String assembleEndpoint(String path) {
        return context.getUrl().concat(path);
    }

    protected abstract SOAPMessage createSOAPRequest() throws SOAPException;

    public ServerContext getContext() {
        return context;
    }

    public String getPath() {
        return path;
    }

}

Soap Client implementation

public class SoapClient extends AbstractSoapClient {

    public SoapClient(ServerContext context) {
        super(context);
    }

    @Override
    public SOAPMessage createSOAPRequest() throws SOAPException {
        MessageFactory messageFactory = MessageFactory.newInstance();
        SOAPMessage soapMessage = messageFactory.createMessage();
        SOAPPart soapPart = soapMessage.getSOAPPart();
        SOAPEnvelope envelope = soapPart.getEnvelope();
        setCredentials(envelope);
        buildBody(envelope);
        soapMessage.saveChanges();
        try {
            soapMessage.writeTo(System.out);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return soapMessage;
    }

    private void buildBody(SOAPEnvelope envelope) throws SOAPException {
        envelope.addNamespaceDeclaration("sch", "------");
        SOAPBody soapBody = envelope.getBody();
        SOAPElement soapBodyElem = soapBody.addChildElement("sampleData", "sampleData");
        SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("sampleData");
        soapBodyElem1.addTextNode("sampleData");
        SOAPElement soapBodyElem2 = soapBodyElem.addChildElement("sampleData");
        soapBodyElem2.addTextNode("sampleData");
        SOAPElement soapBodyElem3 = soapBodyElem.addChildElement("sampleData");
        soapBodyElem3.addTextNode("Y");
        SOAPElement soapBodyElem4 = soapBodyElem.addChildElement("sampleData");
        soapBodyElem4.addTextNode("sampleData");
        SOAPElement soapBodyElem5 = soapBodyElem.addChildElement("sampleData");
        soapBodyElem5.addTextNode("sampleData");
        SOAPElement soapBodyElem6 = soapBodyElem.addChildElement("sampleData");
        soapBodyElem6.addTextNode("sampleData");
    }

    public static void main(String[] args) throws SOAPException, IOException {
        SoapClient client = new SoapClient(
                new ServerContext("url", "user", "password"));
        SOAPMessage response = client.createRequest("endpoint");
        response.writeTo(System.out);
    }

}

The strange point is in this part of the code:

try {
                soapMessage.writeTo(System.out);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

If I comment this code that only print the request before to send it I get the following exception:

  ago 12, 2016 12:58:17 PM com.sun.xml.internal.messaging.saaj.client.p2p.HttpSOAPConnection post
    GRAVE: SAAJ0008: respuesta errónea; Not Found
    Exception in thread "main" com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Bad response: (404Not Found
        at com.sun.xml.internal.messaging.saaj.client.p2p.HttpSOAPConnection.call(HttpSOAPConnection.java:149)
        at 
AbstractSoapClient.createRequest(AbstractSoapClient.java:44)
        at SoapClient.main(SoapClient.java:67)
    Caused by: com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Bad response: (404Not Found
        at com.sun.xml.internal.messaging.saaj.client.p2p.HttpSOAPConnection.post(HttpSOAPConnection.java:264)
        at com.sun.xml.internal.messaging.saaj.client.p2p.HttpSOAPConnection.call(HttpSOAPConnection.java:145)
        ... 2 more
    
    CAUSE:
    
    com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Bad response: (404Not Found
        at com.sun.xml.internal.messaging.saaj.client.p2p.HttpSOAPConnection.post(HttpSOAPConnection.java:264)
        at com.sun.xml.internal.messaging.saaj.client.p2p.HttpSOAPConnection.call(HttpSOAPConnection.java:145)
        at AbstractSoapClient.createRequest(AbstractSoapClient.java:44)
        at SoapClient.main(SoapClient.java:67)

But if I don't comment this line I can get the response correctly.
This doesn't make sense: why is it sending a 404Not Found if I don't write the request in the console before sending it?

Kirsch answered 12/8, 2016 at 18:7 Comment(0)
G
3

If you check the writeTo implementation you will see that they add a SOAPAction header.

Try the following:

MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
soapMessage.getMimeHeaders().addHeader("SOAPAction", "\"\"");
Goldbrick answered 15/8, 2016 at 19:15 Comment(2)
But why a writeTo method that only print the request in an stream add headers to the message, Is that really a good practice ?Kirsch
I know it sounds weird, and for sure is not a good practice, however the MessageImpl.writeTo source code does that.Goldbrick
M
0

By default, SOAPMessage interface is implemented by SoapMessageImpl. This implementation has the side effect of adding a SOAPAction header if it's not present.

After calling to writeTo, you can remove it by calling:

soapMessage.getMimeHeaders().removeHeader("SOAPAction");

Having said that, instead of adding extra code only to log the call and response, i suggest to use a proxy instead.

If you're using Eclipse, take a look at the TCP/Monitor View

Muire answered 21/8, 2016 at 18:48 Comment(0)
J
0

Identify the correct "SOAPAction" and then post the request. This will resolve the 404 FileNotFoud Error. eg:

String SOAPAction = "/Service/Service.serviceagent/ServicesEndpoint1/ACTIONNAMEFROMSERVERSIDE";
            httpConn.setRequestProperty("Content-Length", String.valueOf(b.length));
            httpConn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
            httpConn.setRequestProperty("SOAPAction", SOAPAction);
Joshia answered 20/5, 2020 at 6:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.