4 Replies Latest reply on Dec 2, 2010 1:28 AM by rohit.macherla

    Effective way of forming a WebService client

    rohit.macherla

      Which is more effective way of forming a WebService client out of the following ?

      1. Having the Service and Port objects of the generated Java artifacts (after importing the WSDL) as method-local objects. Example :
        public class TestWS {
        ...
        private void testLocal() {
        wsdlImportedPackage.TargetService localService = new wsdlImportedPackage.TargetService();
        wsdlImportedPackage.TargetServicePort localPort = localService.getTargetServicePort();
        wsdlImportedPackage.TargetResponse response = localPort.invoke();
        ...
        }
        }
        

      2. Having the Service and Port objects of the generated Java artifacts as static global. Example :
        public class TestWS {
        ...
        wsdlImportedPackage.TargetService globalService = null;
        wsdlImportedPackage.TargetServicePort globalPort = null;
        static {
        globalService = new wsdlImportedPackage.TargetService();
        globalPort = globalService.getTargetServicePort();
        }
        private void testGlobal() {
        wsdlImportedPackage.TargetResponse response = globalPort.invoke();
        ...
        }
        }


      When the testLocal() method is load tested, it is observed that the code localPort = localService.getTargetServicePort() resulted in the entire WSDL being fetched and parsed and (probably) JAXB objects created for each invocation of test() method. However, load test of testGlobal() method resulted in only one full parse of WSDL, which occured when the class was loaded, as expected since the getTargetServicePort() is in the static block. Thus the testGlobal() looks efficient, what with reducing the Garbage collection (no need of collecting the service, port and other java objects which were derived from WSDL once the method is over since they are global) and network access time to download the WSDL and parse it.

      Assumption to be considered:
      * No table locking or resource locking occurs from the webservice.
      * The target WSDL doesn't change.
      * The getTargetServicePort() has the code to get the QName, etc., i.e., the relevant WS client code.

      Will a single Port object be able to handle all the requests properly without any deadlocks ? (From my testing, I give it a nod, but it may depend on the WebService code as well)
      Is there any other better way to cache the WSDL or stop the server from accessing the WSDL always for generating the Java artifacts, provided that the target WSDL doesn't change ?
      I am unable to get proper documents from where I could find out what the getWebServicePort() method is supposed to do.

       

      Furthermore, during load testing testLocal(), we found that the processing threads (which are found in tomcat console, i.e., http://JBOSS_IP:Port/status) of TargetService remain active even after they sent the response. These threads are of type:

      GET /TargetServiceManagement-war/TargetService?wsdl HTTP/1.1

      Such threads are active for a long time and when the thread count comes down we find that the following messages appear in the log:

      17:47:37,938 ERROR [RequestHandlerImpl] Cannot close output stream

      There are as many of such statements as there are such active threads. I am not able to understand whether this is a code issue or not, because it occurs only for our vendor API's. For a custom built API, such issue doesn't arise.

      These tests were performed on JBoss 4.2.3 server and the code was developed using NetBeans 6.8 (but development environment shouldn't matter I guess).

       

      So two questions here: What is the best away among the two?  and What does this RequestHandlerImpl error mean ?

       

      Thanks for your time.

        • 1. Re: Effective way of forming a WebService client
          asoldano

          Depending on the usage of your client code, please take a look at the FAQ regarding thread safety of client artifacts: http://community.jboss.org/wiki/JBossWS-FAQ#What_client_artifacts_are_thread_safe

           

          Generally speaking, a widely used strategy is creating a Service just once, then create a pool of proxies to be used by the client.

           

          Regarding the Cannot close output stream message, it's difficult to tell what's happening exactly; generally speaking consider moving to recent JBoss AS / WS versions.

          • 2. Re: Effective way of forming a WebService client
            rohit.macherla

            Thanks Alessio Soldano.

             

            If I may follow it up with another question, is there any way that we can cache the WSDL, since each invocation of getPort (...)  (via the JAX-WS JBossWS-Native) involves a full parse of the WSDL ? Whats happening in this case is : Many invocations of the client WebService. As it involves invoking another WebService, each of the getPort(...) calls resulted in :

            1. connecting to the target WSDL location: This can be verified as the WSDL parsing fails when the target host is down. What I mean is, there is no need to connect to the target host and then download the WSDL, if we know that its not gonna change. When I say "WSDL parsing fails", I mean that there are no WSDL parsing statements in the DEBUG log and Exception is thrown before such parsing happens.
            2. full parse of WSDL: I find the full WSDL printed in the DEBUG log. Probably this is followed by a conversion of XML to Java artefacts, but this is unnecessary time taking operation (in my view) since the target WSDL is the same anyway.

            Additionally, I find many open file descriptors accessing the WSDL in the server/<configuration>/data/wsdl/TargetWS/TargetWS001.wsdl (i.e., the WSDL created when I deploy the TargetWS. Though this seems contradictory to the point 1 listed above).

             

            Message was edited by: Rohit Macherla

            • 3. Re: Effective way of forming a WebService client
              smeverts

              I am having a similar problem, did you ever find out the answers to your questions?

               

              Scott

              • 4. Re: Effective way of forming a WebService client
                rohit.macherla

                Hi Scott,

                 

                I have found a quite wierd solution. Actually, I just stumbled upon it. We were using NetBeans 6.0.1 for WebService development. The major issue was that threads were not released properly and still hung around for a lot of time with the Tomcat status as :

                 

                 GET /TargetServiceManagement-war/TargetService?wsdl HTTP/1.1
                

                 

                Another important one : Target WSDL parsing happening for each time a WS is invoked.

                Shifting to NetBeans 6.8 has solved the issue. No other modifications were made to JBoss server. I have redeployed the code with NetBeans 6.0.1 and tested again and found that the threads still hung. But with NetBeans 6.8 code (no changes in the java files that we have written. None at all), no hung threads are noticed.

                Supecting that there has to be some changes in XML files, I've compared their contents and there are changes in the jax-ws.xml. There are a lot of <wsimport-options> present in the NetBeans 6.8 version code, which probably might be stopping the re-parse of full WSDL.

                 

                The following are the options added in the new version jax-ws.xml :

                      <wsimport-options>
                        <wsimport-option>
                          <wsimport-option-name>extension</wsimport-option-name>
                          <wsimport-option-value>true</wsimport-option-value>
                        </wsimport-option>
                        <wsimport-option>
                          <wsimport-option-name>verbose</wsimport-option-name>
                          <wsimport-option-value>true</wsimport-option-value>
                        </wsimport-option>
                        <wsimport-option>
                          <wsimport-option-name>wsdlLocation</wsimport-option-name> 
                          <wsimport-option-value>http://JBOSS:8080/war/Service?wsdl</wsimport-option-value>
                         </wsimport-option>
                        <wsimport-option>
                          <wsimport-option-name>xendorsed</wsimport-option-name>
                          <wsimport-option-value>true</wsimport-option-value>
                        </wsimport-option>
                        <wsimport-option>
                          <wsimport-option-name>package</wsimport-option-name>
                          <wsimport-option-value>SOcreation</wsimport-option-value>
                        </wsimport-option>
                        <wsimport-option>
                          <wsimport-option-name>target</wsimport-option-name>
                          <wsimport-option-value>2.1</wsimport-option-value>
                        </wsimport-option>
                      </wsimport-options>

                 

                I don't know how the threads hanging thing is fixed. But its fixed with the NetBeans 6.8 version developed code.

                 

                If someone knows answers to these things, please post them here.