Axis2
  1. Axis2
  2. AXIS2-5062

Connection is not released while using JAXWS client API

    Details

      Description

      1. Using Dispatch API
      A bit more description for my case, the server side is a simple web service, for the client side, the codes are something like :
      --->
      Service service = new HelloService();
      Dispatch dispatchJaxb = service.createDispatch(PORT_QNAME, JAXBContext.newInstance(org.test.ObjectFactory.class),
      javax.xml.ws.Service.Mode.PAYLOAD);
      dispatchJaxb.invokeOneWay(new HelloRequest());
      <---

      After adding some code fragments in the finally block of BaseDispatch.invokeOneWay method, it looks to me work fine.
      --->
      try {
      if (requestMsgCtx != null && requestMsgCtx.getAxisMessageContext() != null) {
      org.apache.axis2.context.MessageContext axisMsgCtx = requestMsgCtx.getAxisMessageContext();
      if (axisMsgCtx.getTransportOut() != null && axisMsgCtx.getTransportOut().getSender() != null)

      { axisMsgCtx.getTransportOut().getSender().cleanup(axisMsgCtx); }

      }
      } catch (Exception ignore) {
      }
      <---

      I also googled this issue, and do found a lot of information for the same timeout exception, also read some related codes
      a. In the HttpSender, there is a method named cleanup, which is used to release the connection, but it has the precondition to configure the AUTO_RELEASE_CONNECTION. And actually I did not see other setting configurations in the Axis2 codes, and think that it should be configured by the users in the Options ?
      b. Some posts in the mail list recommended to call the getTransport().cleanup() in the Axis2 specific client codes. And in the testing scenario above, since the standard JAX-WS API is used, suppose that Axis2 should do this ?
      And very appreciated with any comment ? Thanks.

      2. I might find another connection leak while using JAXWS API on client side. In the scenario below :
      For the server side, it requires basic authentication.

      The client codes are something like :
      HelloPort helloPort = (HelloPort)service.getPort(HelloPort.class);
      helloPort.echo("hello");

      The client codes did not set the user name and password by the BindingProvider interface, so the server return a 404 to the client side, then the method HttpSender.handleResponse will enter the fourth block :
      private void handleResponse(MessageContext msgContext,
      HttpMethodBase method) throws IOException {
      int statusCode = method.getStatusCode();
      log.trace("Handling response - " + statusCode);
      if (statusCode == HttpStatus.SC_OK)

      { // Save the HttpMethod so that we can release the connection when cleaning up msgContext.setProperty(HTTPConstants.HTTP_METHOD, method); processResponse(method, msgContext); }

      else if (statusCode == HttpStatus.SC_ACCEPTED)

      { /* When an HTTP 202 Accepted code has been received, this will be the case of an execution * of an in-only operation. In such a scenario, the HTTP response headers should be returned, * i.e. session cookies. */ obtainHTTPHeaderInformation(method, msgContext); // Since we don't expect any content with a 202 response, we must release the connection method.releaseConnection(); }

      else if (statusCode == HttpStatus.SC_INTERNAL_SERVER_ERROR ||
      statusCode == HttpStatus.SC_BAD_REQUEST) {
      // Save the HttpMethod so that we can release the connection when cleaning up
      msgContext.setProperty(HTTPConstants.HTTP_METHOD, method);
      Header contenttypeHeader =
      method.getResponseHeader(HTTPConstants.HEADER_CONTENT_TYPE);
      String value = null;
      if (contenttypeHeader != null)

      { value = contenttypeHeader.getValue(); }

      OperationContext opContext = msgContext.getOperationContext();
      if(opContext!=null){
      MessageContext inMessageContext =
      opContext.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
      if(inMessageContext!=null)

      { inMessageContext.setProcessingFault(true); }

      }
      if (value != null)

      { processResponse(method, msgContext); }

      if (org.apache.axis2.util.Utils.isClientThreadNonBlockingPropertySet(msgContext))

      { throw new AxisFault(Messages.getMessage("transportError", String.valueOf(statusCode), method.getStatusText())); }

      } else

      { throw new AxisFault(Messages.getMessage("transportError", <--- Running here String.valueOf(statusCode), method.getStatusText())); }

      }

      The stack trace is :

      org.apache.axis2.AxisFault: Transport error: 403 Error: Forbidden
      at org.apache.axis2.transport.http.HTTPSender.handleResponse(HTTPSender.java:309)
      at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:194)
      at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:75)
      at org.apache.axis2.transport.http.CommonsHTTPTransportSender.writeMessageWithCommons(CommonsHTTPTransportSender.java:404)
      at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(CommonsHTTPTransportSender.java:231)
      at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:443)
      at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:406)
      at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:229)
      at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165)
      at org.apache.axis2.jaxws.core.controller.impl.AxisInvocationController.execute(AxisInvocationController.java:578)
      at org.apache.axis2.jaxws.core.controller.impl.AxisInvocationController.doInvoke(AxisInvocationController.java:127)
      at org.apache.axis2.jaxws.core.controller.impl.InvocationControllerImpl.invoke(InvocationControllerImpl.java:93)
      at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invokeSEIMethod(JAXWSProxyHandler.java:377)
      at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invoke(JAXWSProxyHandler.java:174)
      at $Proxy89.helloPort(Unknown Source)
      at org.test.HelloServlet.doPost(HelloServlet.java:113)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:595)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:306)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
      at org.apache.geronimo.tomcat.security.SecurityValve.invoke(SecurityValve.java:87)
      at org.apache.geronimo.tomcat.security.jacc.JACCSecurityValve.invoke(JACCSecurityValve.java:54)
      at org.apache.geronimo.tomcat.GeronimoStandardContext$SystemMethodValve.invoke(GeronimoStandardContext.java:700)
      at org.apache.geronimo.tomcat.valve.GeronimoBeforeAfterValve.invoke(GeronimoBeforeAfterValve.java:48)
      at org.apache.geronimo.tomcat.valve.ProtectedTargetValve.invoke(ProtectedTargetValve.java:53)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
      at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:550)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:380)
      at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
      at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
      at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)
      at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:288)
      at org.apache.geronimo.pool.ThreadPool$1.run(ThreadPool.java:243)
      at org.apache.geronimo.pool.ThreadPool$ContextClassLoaderRunnable.run(ThreadPool.java:373)
      at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
      at java.lang.Thread.run(Thread.java:662)

      Thanks.

        Activity

        Hide
        Ivan added a comment -

        Attach two patch files.

        Show
        Ivan added a comment - Attach two patch files.
        Hide
        Andreas Veithen added a comment -

        I believe that the problem with 403 responses is the same as in AXIS2-5093, for which I am preparing fixes for 1.5.6, 1.6.1 and 1.7.0. Can you check that?

        There may still be a problem if invokeOneWay is used to invoke a service that actually doesn't return HTTP 202, but e.g. a SOAP fault.

        Show
        Andreas Veithen added a comment - I believe that the problem with 403 responses is the same as in AXIS2-5093 , for which I am preparing fixes for 1.5.6, 1.6.1 and 1.7.0. Can you check that? There may still be a problem if invokeOneWay is used to invoke a service that actually doesn't return HTTP 202, but e.g. a SOAP fault.
        Hide
        Ivan added a comment - - edited

        Hi, Andreas, I have not tried the changes, but from the stack trace, the second issue should be fixed.
        I have a question for it, I might not understand the Axis2 logic clearly , is there a scenario that the clients which uses Axis2 API directly would wish to read something from the connection if any problem happens ? With current changes, the connection is automatically closed for those unknown errors. I am thinking that, only while working with JAX-WS API, the users would not interact with the underlying http connection. That is why I close the changes in the jaxws API call. And from those discussions in the past, it seems that the community always recommended to users to close the connection explicitly in each web service all. Thanks.

        Show
        Ivan added a comment - - edited Hi, Andreas, I have not tried the changes, but from the stack trace, the second issue should be fixed. I have a question for it, I might not understand the Axis2 logic clearly , is there a scenario that the clients which uses Axis2 API directly would wish to read something from the connection if any problem happens ? With current changes, the connection is automatically closed for those unknown errors. I am thinking that, only while working with JAX-WS API, the users would not interact with the underlying http connection. That is why I close the changes in the jaxws API call. And from those discussions in the past, it seems that the community always recommended to users to close the connection explicitly in each web service all. Thanks.
        Hide
        Andreas Veithen added a comment -

        In the case of an 404 (or similar) error, the response content will generally be HTML and can't be processed. Anyways, in Axis2 1.6.0 the HTTP transport neither processes the response (i.e. there is no call to processResponse) nor stores the HttpMethod in the message context. That means that it is impossible that there is existing application code that does something with the response. In that case it is better to release the connection immediately.

        What worries me more about the JAX-WS code is that for request-response invocations, it doesn't use the TransportSender#cleanup API but relies on a completely different way to release the connection. Namely, it assumes that (1) the message builder wraps the input stream in a DetachableInputStream and that (2) the transport performs cleanup automatically when the input stream has been consumed. That currently works (at least for SOAP over HTTP), but AFAIK none of these two assumptions is covered by anything in the API documentation.

        Show
        Andreas Veithen added a comment - In the case of an 404 (or similar) error, the response content will generally be HTML and can't be processed. Anyways, in Axis2 1.6.0 the HTTP transport neither processes the response (i.e. there is no call to processResponse) nor stores the HttpMethod in the message context. That means that it is impossible that there is existing application code that does something with the response. In that case it is better to release the connection immediately. What worries me more about the JAX-WS code is that for request-response invocations, it doesn't use the TransportSender#cleanup API but relies on a completely different way to release the connection. Namely, it assumes that (1) the message builder wraps the input stream in a DetachableInputStream and that (2) the transport performs cleanup automatically when the input stream has been consumed. That currently works (at least for SOAP over HTTP), but AFAIK none of these two assumptions is covered by anything in the API documentation.
        Hide
        Hudson added a comment -

        Integrated in Axis2 #922 (See https://builds.apache.org/job/Axis2/922/)
        Added a test case providing evidence for the issue described in AXIS2-5062.

        veithen :
        Files :

        • /axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/dispatch/SOAPMessageDispatchTests.java
        Show
        Hudson added a comment - Integrated in Axis2 #922 (See https://builds.apache.org/job/Axis2/922/ ) Added a test case providing evidence for the issue described in AXIS2-5062 . veithen : Files : /axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/dispatch/SOAPMessageDispatchTests.java
        Hide
        Hudson added a comment -

        Integrated in Axis2 #923 (See https://builds.apache.org/job/Axis2/923/)
        AXIS2-5062:

        • Committed the patch for BaseDispatch provided by Ivan.
        • Enabled the corresponding test case.

        veithen :
        Files :

        • /axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/dispatch/SOAPMessageDispatchTests.java
        • /axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/client/dispatch/BaseDispatch.java
        Show
        Hudson added a comment - Integrated in Axis2 #923 (See https://builds.apache.org/job/Axis2/923/ ) AXIS2-5062 : Committed the patch for BaseDispatch provided by Ivan. Enabled the corresponding test case. veithen : Files : /axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/dispatch/SOAPMessageDispatchTests.java /axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/client/dispatch/BaseDispatch.java
        Hide
        Andreas Veithen added a comment -

        I think that the problem is solved. Can you check, so that we can then merge the changes to the 1.6 branch?

        Show
        Andreas Veithen added a comment - I think that the problem is solved. Can you check, so that we can then merge the changes to the 1.6 branch?
        Hide
        Ivan added a comment -

        Hi, Andreas, just tried the changes, the results seems to be OK, thanks for checking this.

        Show
        Ivan added a comment - Hi, Andreas, just tried the changes, the results seems to be OK, thanks for checking this.
        Hide
        Hudson added a comment -

        Integrated in axis2-1.6 #70 (See https://builds.apache.org/job/axis2-1.6/70/)
        AXIS2-5062: Merged r1157517 and r1157535 to the 1.6 branch.

        veithen :
        Files :

        • /axis/axis2/java/core/branches/1_6/modules/jaxws-integration/test/org/apache/axis2/jaxws/dispatch/SOAPMessageDispatchTests.java
        • /axis/axis2/java/core/branches/1_6/modules/jaxws/src/org/apache/axis2/jaxws/client/dispatch/BaseDispatch.java
        • /axis/axis2/java/core/branches/1_6
        Show
        Hudson added a comment - Integrated in axis2-1.6 #70 (See https://builds.apache.org/job/axis2-1.6/70/ ) AXIS2-5062 : Merged r1157517 and r1157535 to the 1.6 branch. veithen : Files : /axis/axis2/java/core/branches/1_6/modules/jaxws-integration/test/org/apache/axis2/jaxws/dispatch/SOAPMessageDispatchTests.java /axis/axis2/java/core/branches/1_6/modules/jaxws/src/org/apache/axis2/jaxws/client/dispatch/BaseDispatch.java /axis/axis2/java/core/branches/1_6

          People

          • Assignee:
            Andreas Veithen
            Reporter:
            Ivan
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development