-1

Please check the code below. What the code does is use firstHttpConn to check the response code and open secondHttpConn. If the response code is 401, add a basic auth header to secondHttpConn. Then post the data and read the response.

However, the code throws Cannot write output after reading input error. I checked other questions on Stack Overflow like this one and I am sure I did not make the same mistakes.

//I hate using Java 6 and HttpURLConnection, but the code is for a very old system.
private static XmlObject callWebService(String soapMessage, String webServiceEndpoint, String soapAction) throws Exception {
    XmlObject resultXMLObject;
    HttpURLConnection firstHttpConn = null;
    HttpURLConnection secondHttpConn = null;

    try {
        byte[] streamoutByteArray = soapMessage.getBytes("UTF-8");

        URL url = new URL(webServiceEndpoint);
        firstHttpConn = (HttpURLConnection) url.openConnection();
        firstHttpConn.connect();

        if (firstHttpConn.getResponseCode() == 401) {
            firstHttpConn.disconnect();
            secondHttpConn = (HttpURLConnection) url.openConnection();
            secondHttpConn.setRequestProperty("Authorization", "Basic " + getBasicAuth());
        } else {
            firstHttpConn.disconnect();
            secondHttpConn = (HttpURLConnection) url.openConnection();
        }

        secondHttpConn.setConnectTimeout(30000);
        secondHttpConn.setReadTimeout(300000);
        secondHttpConn.setRequestProperty("Content-Length", String.valueOf(streamoutByteArray.length));
        secondHttpConn.setRequestProperty("Content-Type", "text/xml; charset=UTF-8);
        secondHttpConn.setRequestProperty("SOAPAction", soapAction);
        secondHttpConn.setRequestMethod("POST");
        secondHttpConn.setDoOutput(true);
        secondHttpConn.setDoInput(true);

        OutputStream out = secondHttpConn.getOutputStream();
        out.write(streamoutByteArray);
        out.close();

        //Line 238 below.
        InputStreamReader isr = new InputStreamReader(secondHttpConn.getInputStream());
        BufferedReader in = new BufferedReader(isr);
        String inputLine;
        StringBuffer sb = new StringBuffer();

        while ((inputLine = in.readLine()) != null)
            sb.append(inputLine).append("\n");

        in.close();
        resultXMLObject = XmlObject.Factory.parse(sb.toString());
    } finally {
        if (firstHttpConn != null)
            firstHttpConn.disconnect();
        if (secondHttpConn != null)
            secondHttpConn.disconnect();
    }

    return resultXMLObject;
}

The log:

Caused By: java.net.ProtocolException: Cannot write output after reading input.
        at weblogic.net.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:271)
        at org.company.member.esb.webservice.WebServiceClient.callWebService(WebServiceClient.java:238)
        at org.company.member.esb.webservice.WebServiceClient.invokeWebserviceV01(WebServiceClient.java:132)
        at sun.reflect.GeneratedMethodAccessor711.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        Truncated. see log file for complete stacktrace

Anyone knows why? Thanks.

6324
  • 4,678
  • 8
  • 34
  • 63
  • @luk2302 I don't think it matters because I added `connect()` before and it threw the same error. – 6324 Oct 02 '17 at 15:55
  • Ah, I overlooked that you created a second connection. Sorry. Now I do not know of the top of my head what might be wrong. You should probably add the stacktrace you receive to the question. – luk2302 Oct 02 '17 at 15:58
  • @luk2302 Added. There is nothing much in the log :( – 6324 Oct 02 '17 at 16:01
  • The exception is thrown at `weblogic.net.http.HttpURLConnection.getOutputStream` I don't see how it's possible that it's thrown at the line you showed which gets the `InputStream` – Oleg Oct 02 '17 at 16:14
  • @Oleg Yeah it is weird because line 238 points to the line which gets the `InputStream.` – 6324 Oct 02 '17 at 16:15
  • Try to debug it and see what's going on. – Oleg Oct 02 '17 at 16:17
  • Perhaps because `url` is re-used. Try creating a new instance: `secondHttpConn = (HttpURLConnection) (new URL(webServiceEndpoint)).openConnection();` – Andrew S Oct 02 '17 at 16:17
  • @Oleg I also want to debug. But the code is "older than my grandpa" and I am not able to set it up running it on my laptop. I have to deploy it to the old system to run every time, which takes 2 hours or so. – 6324 Oct 02 '17 at 16:21
  • @YilongWang you can always just isolate a small block of code like the one in the question and just run that, anywhere. – eis Oct 02 '17 at 16:22
  • @AndrewS Let me give a try using another `Url`. – 6324 Oct 02 '17 at 16:25

1 Answers1

0

You're not running the code you pasted here. You can see the lines do not match, as there is HttpURLConnection.getOutputStream in the stack trace, but you claim

//Line 238 below.
InputStreamReader isr = new InputStreamReader(secondHttpConn.getInputStream());

so code is different for stack trace and your paste.

I don't see a problem with the code you've pasted here.

eis
  • 51,991
  • 13
  • 150
  • 199
  • I do think the code matches. Let me isolate the code and run that on my local machine. – 6324 Oct 02 '17 at 16:23
  • 2
    it's not a matter of opinion, that line does not call getOutputStream() so it does not match. – eis Oct 02 '17 at 16:25
  • Yes you are right. The grandpa system did not pick up my latest code. It took me some time to find it out. :) – 6324 Oct 04 '17 at 21:35