Details

    • Type: Improvement Improvement
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.0
    • Fix Version/s: 1.1.1
    • Component/s: Core
    • Labels:
      None
    • Number of attachments :
      0

      Description

      With the current implementation of Client, there are some issues. This JIRA is to collect the various thoughts and to discuss how to move forward.

        Activity

        Hide
        Mika Goeckel added a comment -

        Issue #1: Client is a one shot object, what I mean is, that it is neither thread safe nor multi-request capable if used asynchronously, because it wrappes the matching point for the response to the request. If you send several asynchrounos requests in a row, you'd need a fresh client for every request which leads to initialisation overhead.

        Show
        Mika Goeckel added a comment - Issue #1: Client is a one shot object, what I mean is, that it is neither thread safe nor multi-request capable if used asynchronously, because it wrappes the matching point for the response to the request. If you send several asynchrounos requests in a row, you'd need a fresh client for every request which leads to initialisation overhead.
        Hide
        Mika Goeckel added a comment -

        Issue #2: Client uses CommonsHttpClient underneath (with httptransport) which would enable it to maintain a session. But there is no way to keep the instance of the CommonsHttpClient, so the session handling capabilities can't be used. Neither can the connection pooling capabilities be used which would improve performance.

        Show
        Mika Goeckel added a comment - Issue #2: Client uses CommonsHttpClient underneath (with httptransport) which would enable it to maintain a session. But there is no way to keep the instance of the CommonsHttpClient, so the session handling capabilities can't be used. Neither can the connection pooling capabilities be used which would improve performance.
        Hide
        Dan Diephouse added a comment -

        Mika, I don't think its possible to make Client multithreaded safe. Christoph and I were talking last night and it needs to maintain state for asynchronous transports. I am inclined to mark this issue as closed and keep things this way Any objections/thoughts?

        Show
        Dan Diephouse added a comment - Mika, I don't think its possible to make Client multithreaded safe. Christoph and I were talking last night and it needs to maintain state for asynchronous transports. I am inclined to mark this issue as closed and keep things this way Any objections/thoughts?
        Hide
        Andres Bernasconi added a comment -

        Hi,

        I'm no xfire developer so I'm not sure if I can be a part of this discussion. My thought is that you MUST have a multithreaded-capable client. What if an application makes several requests to a service? it could be even the same service? I can not afford to get an exception back. Also AXIS is multithreaded so it can deffinetly be done.

        I'm using synchronous web service calls to an XFire web service (simple echo example) and I'm trying to create some load to see how it behaves, but my code throws exceptions all over.

        Here is the stacktrace:

        
        org.codehaus.xfire.XFireRuntimeException: Could not invoke service.. Nested exception is org.codehaus.xfire.fault.XFireFault: Unexpected character 'w' (code 119) in prolog; expected '<'
         at [row,col {unknown-source}]: [1,129]
        org.codehaus.xfire.fault.XFireFault: Unexpected character 'w' (code 119) in prolog; expected '<'
         at [row,col {unknown-source}]: [1,129]
        	at org.codehaus.xfire.fault.XFireFault.createFault(XFireFault.java:89)
        	at org.codehaus.xfire.client.Client.onReceive(Client.java:467)
        	at org.codehaus.xfire.transport.http.HttpChannel.sendViaClient(HttpChannel.java:182)
        	at org.codehaus.xfire.transport.http.HttpChannel.send(HttpChannel.java:67)
        	at org.codehaus.xfire.handler.OutMessageSender.invoke(OutMessageSender.java:26)
        	at org.codehaus.xfire.handler.HandlerPipeline.invoke(HandlerPipeline.java:98)
        	at org.codehaus.xfire.client.Client.invoke(Client.java:360)
        	at org.codehaus.xfire.client.XFireProxy.handleRequest(XFireProxy.java:77)
        	at org.codehaus.xfire.client.XFireProxy.invoke(XFireProxy.java:57)
        	at $Proxy1.echo(Unknown Source)
        	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        	at java.lang.reflect.Method.invoke(Unknown Source)
        	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:335)
        	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:181)
        	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:148)
        	at com.verizon.snm.performance.PerformanceInterceptor.invoke(PerformanceInterceptor.java:18)
        	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
        	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176)
        	at $Proxy0.echo(Unknown Source)
        	at com.verizon.snm.echo.EchoServiceClientTest.performTest(EchoServiceClientTest.java:71)
        	at com.verizon.snm.echo.EchoServiceClientTest.run(EchoServiceClientTest.java:66)
        	at java.lang.Thread.run(Unknown Source)
        Caused by: com.ctc.wstx.exc.WstxUnexpectedCharException: Unexpected character 'w' (code 119) in prolog; expected '<'
         at [row,col {unknown-source}]: [1,129]
        	at com.ctc.wstx.sr.StreamScanner.throwUnexpectedChar(StreamScanner.java:600)
        	at com.ctc.wstx.sr.BasicStreamReader.nextFromProlog(BasicStreamReader.java:1889)
        	at com.ctc.wstx.sr.BasicStreamReader.next(BasicStreamReader.java:1026)
        	at org.codehaus.xfire.soap.handler.ReadHeadersHandler.invoke(ReadHeadersHandler.java:44)
        	at org.codehaus.xfire.handler.HandlerPipeline.invoke(HandlerPipeline.java:98)
        	at org.codehaus.xfire.client.Client.onReceive(Client.java:450)
        	... 22 more
        

        This exception happens when two (or more) threads invoke the line on Client.java:450 (version 1.1) at the same time.

                    recvContext.setInPipeline(inPipe);
                    
                    inPipe.invoke(context); //<------------ this line
                    
                    MessageInfo msgInfo = exchange.getOperation().getOutputMessage();
        

        In my humble user opinion, this is a must to be fixed.
        My 2 cents.
        Regards,
        Andrés B.

        Show
        Andres Bernasconi added a comment - Hi, I'm no xfire developer so I'm not sure if I can be a part of this discussion. My thought is that you MUST have a multithreaded-capable client. What if an application makes several requests to a service? it could be even the same service? I can not afford to get an exception back. Also AXIS is multithreaded so it can deffinetly be done. I'm using synchronous web service calls to an XFire web service (simple echo example) and I'm trying to create some load to see how it behaves, but my code throws exceptions all over. Here is the stacktrace: org.codehaus.xfire.XFireRuntimeException: Could not invoke service.. Nested exception is org.codehaus.xfire.fault.XFireFault: Unexpected character 'w' (code 119) in prolog; expected '<' at [row,col {unknown-source}]: [1,129] org.codehaus.xfire.fault.XFireFault: Unexpected character 'w' (code 119) in prolog; expected '<' at [row,col {unknown-source}]: [1,129] at org.codehaus.xfire.fault.XFireFault.createFault(XFireFault.java:89) at org.codehaus.xfire.client.Client.onReceive(Client.java:467) at org.codehaus.xfire.transport.http.HttpChannel.sendViaClient(HttpChannel.java:182) at org.codehaus.xfire.transport.http.HttpChannel.send(HttpChannel.java:67) at org.codehaus.xfire.handler.OutMessageSender.invoke(OutMessageSender.java:26) at org.codehaus.xfire.handler.HandlerPipeline.invoke(HandlerPipeline.java:98) at org.codehaus.xfire.client.Client.invoke(Client.java:360) at org.codehaus.xfire.client.XFireProxy.handleRequest(XFireProxy.java:77) at org.codehaus.xfire.client.XFireProxy.invoke(XFireProxy.java:57) at $Proxy1.echo(Unknown Source) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:335) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:181) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:148) at com.verizon.snm.performance.PerformanceInterceptor.invoke(PerformanceInterceptor.java:18) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176) at $Proxy0.echo(Unknown Source) at com.verizon.snm.echo.EchoServiceClientTest.performTest(EchoServiceClientTest.java:71) at com.verizon.snm.echo.EchoServiceClientTest.run(EchoServiceClientTest.java:66) at java.lang. Thread .run(Unknown Source) Caused by: com.ctc.wstx.exc.WstxUnexpectedCharException: Unexpected character 'w' (code 119) in prolog; expected '<' at [row,col {unknown-source}]: [1,129] at com.ctc.wstx.sr.StreamScanner.throwUnexpectedChar(StreamScanner.java:600) at com.ctc.wstx.sr.BasicStreamReader.nextFromProlog(BasicStreamReader.java:1889) at com.ctc.wstx.sr.BasicStreamReader.next(BasicStreamReader.java:1026) at org.codehaus.xfire.soap.handler.ReadHeadersHandler.invoke(ReadHeadersHandler.java:44) at org.codehaus.xfire.handler.HandlerPipeline.invoke(HandlerPipeline.java:98) at org.codehaus.xfire.client.Client.onReceive(Client.java:450) ... 22 more This exception happens when two (or more) threads invoke the line on Client.java:450 (version 1.1) at the same time. recvContext.setInPipeline(inPipe); inPipe.invoke(context); //<------------ this line MessageInfo msgInfo = exchange.getOperation().getOutputMessage(); In my humble user opinion, this is a must to be fixed. My 2 cents. Regards, Andrés B.
        Hide
        Holger Hoffstätte added a comment -

        Hi, I'm with the Mule ESB project and fixed our XFire multithreading yesterday (http://jira.symphonysoft.com/browse/MULE-820) so I can maybe add my point of view.
        It is important to distinguish between "thread-safe" and "concurrent". I agree that it would be nice to have the Client threadsafe instead of letting it explode, though I don't know how difficult it would be to synchronize on all shared state for all operations.
        It would certainly be easier than to make the Client truly concurrent, which is not such a good idea as it first sounds. Applications that are in control of their concurrency requirements can easily add a pool of Client objects that are acquired per thread's request and then returned; this approach is actually much better since usually SOAP calls are pretty expensive in terms of latency, and the last thing you want is hundreds of web sessions smashing into your SOAP service at the same time. The pool provides a much more adaptable/tuneable solution for the applications' concurrency behaviour as an internally concurrent Client object could ever manage itself.

        Show
        Holger Hoffstätte added a comment - Hi, I'm with the Mule ESB project and fixed our XFire multithreading yesterday ( http://jira.symphonysoft.com/browse/MULE-820 ) so I can maybe add my point of view. It is important to distinguish between "thread-safe" and "concurrent". I agree that it would be nice to have the Client threadsafe instead of letting it explode, though I don't know how difficult it would be to synchronize on all shared state for all operations. It would certainly be easier than to make the Client truly concurrent , which is not such a good idea as it first sounds. Applications that are in control of their concurrency requirements can easily add a pool of Client objects that are acquired per thread's request and then returned; this approach is actually much better since usually SOAP calls are pretty expensive in terms of latency, and the last thing you want is hundreds of web sessions smashing into your SOAP service at the same time. The pool provides a much more adaptable/tuneable solution for the applications' concurrency behaviour as an internally concurrent Client object could ever manage itself.
        Hide
        Dan Diephouse added a comment -

        I finished making the client multithreaded. Yay!

        Show
        Dan Diephouse added a comment - I finished making the client multithreaded. Yay!
        Hide
        Holger Hoffstätte added a comment -

        I looked at the new Client class and it is still not threadsafe. The access to the static "invocations" ArrayList is not synchronized, so two Threads calling invoke() at the same time have an (admittedly narrow) window for causing a ConcurrentModificationException in add() or remove(). The ArrayList may also not be the best data structure since this it will cause endless linear searches and array copying. I don't understand enough about the Invocations and why they need to be kept/ordered etc. but a sync HashSet might be more sound overall.
        Just a suggestion

        Show
        Holger Hoffstätte added a comment - I looked at the new Client class and it is still not threadsafe. The access to the static "invocations" ArrayList is not synchronized, so two Threads calling invoke() at the same time have an (admittedly narrow) window for causing a ConcurrentModificationException in add() or remove(). The ArrayList may also not be the best data structure since this it will cause endless linear searches and array copying. I don't understand enough about the Invocations and why they need to be kept/ordered etc. but a sync HashSet might be more sound overall. Just a suggestion
        Hide
        Dan Diephouse added a comment -

        reopening this as Holger pointed out a bug.

        Show
        Dan Diephouse added a comment - reopening this as Holger pointed out a bug.
        Hide
        Dan Diephouse added a comment -

        Alright, I fixed the threading issue, but it probably still isn't ideal because there is a synchronized:

        http://svn.xfire.codehaus.org/changelog/xfire/?cs=1612

        But, I'm closing this issue for now and we can revisit the sync.

        Show
        Dan Diephouse added a comment - Alright, I fixed the threading issue, but it probably still isn't ideal because there is a synchronized: http://svn.xfire.codehaus.org/changelog/xfire/?cs=1612 But, I'm closing this issue for now and we can revisit the sync.

          People

          • Assignee:
            Mika Goeckel
            Reporter:
            Mika Goeckel
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: