8 Replies Latest reply on Jan 30, 2008 5:51 AM by Guillaume Nodet

    Wiretap between cxf-bc and cxf-se

    Martin Murphy Novice

      Should it be possible for me to place a eip:wiretap between a cxf-bc and cxf-se. I was interested in seeing if the message on the NMR between these two points was normalized or if it was still the SOAP message. I used the cxf-wsdl-first demo and took the message in and set the inListener to a JMS queue and this was normalized. The cxf-se was set as the target and I can see using jconsole that the message does reach this endpoint, but the client gets a SOAP fault back.

       

      In the servicemix console, I can see that this was caused by a null pointer expection in the cxf service engine:

       

      Caused by: java.lang.NullPointerException

              at org.apache.servicemix.cxfse.CxfSeEndpoint.process(CxfSeEndpoint.java:173)

              at org.apache.servicemix.common.AsyncBaseLifeCycle.doProcess(AsyncBaseLifeCycle.java:538)

              at org.apache.servicemix.common.AsyncBaseLifeCycle.processExchange(AsyncBaseLifeCycle.java:490)

              at org.apache.servicemix.common.BaseLifeCycle.onMessageExchange(BaseLifeCycle.java:46)

              at org.apache.servicemix.jbi.messaging.DeliveryChannelImpl.processInBound(DeliveryChannelImpl.java:610)

              at org.apache.servicemix.jbi.nmr.flow.AbstractFlow.doRouting(AbstractFlow.java:170)

              at org.apache.servicemix.jbi.nmr.flow.seda.SedaFlow.doRouting(SedaFlow.java:167)

              at org.apache.servicemix.jbi.nmr.flow.seda.SedaQueue$1.run(SedaQueue.java:134)

              at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)

              at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)

              at java.lang.Thread.run(Thread.java:595)

       

      I'm using 3.3.0.6, so I think the null pointer is on:

       

              JBIDestination jbiDestination = jbiTransportFactory

                      .getDestination(exchange.getService().toString()

                              + exchange.getInterfaceName().toString());

       

      I wonder if somehow insert the wiretap for an in-out has resulted in a problem in send back the result?

      This worked fine until I added the wiretap

       

      Perhaps I need to specify more information in my wiretap target. How would I specify interface name?

        <eip:wire-tap service="person:wiretapIn" endpoint="endpoint">

          <eip:target>

            <eip:exchange-target service="person:PersonService" />

          </eip:target>

          <eip:inListener>

            <eip:exchange-target service="test:jmsWiretapOut" />

          </eip:inListener>

        </eip:wire-tap>

       

      Thanks!

      - Martin

        • 1. Re: Wiretap between cxf-bc and cxf-se
          Martin Murphy Novice

          For some reason the stack trace :

           

          Caused by: java.lang.NullPointerException

                  at org.apache.servicemix.cxfse.CxfSeEndpoint.process(CxfSeEndpoint.java:173)

                  at org.apache.servicemix.common.AsyncBaseLifeCycle.doProcess(AsyncBaseLifeCycle.java:538)

                  at org.apache.servicemix.common.AsyncBaseLifeCycle.processExchange(AsyncBaseLifeCycle.java:490)

                  at org.apache.servicemix.common.BaseLifeCycle.onMessageExchange(BaseLifeCycle.java:46)

                  at org.apache.servicemix.jbi.messaging.DeliveryChannelImpl.processInBound(DeliveryChannelImpl.java:610)

                  at org.apache.servicemix.jbi.nmr.flow.AbstractFlow.doRouting(AbstractFlow.java:170)

                  at org.apache.servicemix.jbi.nmr.flow.seda.SedaFlow.doRouting(SedaFlow.java:167)

                  at org.apache.servicemix.jbi.nmr.flow.seda.SedaQueue$1.run(SedaQueue.java:134)

                  at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)

                  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)

                  at java.lang.Thread.run(Thread.java:595)

           

          And the line that throws this from CxfSeEndpoint.process() was truncated last time:

           

                  JBIDestination jbiDestination = jbiTransportFactory

                          .getDestination(exchange.getService().toString()

                                  + exchange.getInterfaceName().toString());

           

           

           

          • 2. Re: Wiretap between cxf-bc and cxf-se
            Martin Murphy Novice

            I'm not sure why, but I appear to be having a problem pasting, it seems fine when I save but disappears when I post.

             

            I had a look at the schema for the eip component and realised that I should pass in the interface QName as an attribute "interface" on the eip:exchange-target element. I've gotten past the first null pointer exception, but now I'm seeing a new one in the CXF JBIWrapperInInterceptor, so this is probably the wrong forum for this now.

             

            If someone can confirm this should work I'll continue debugging to find my config errors.

            • 3. Re: Wiretap between cxf-bc and cxf-se
              Chris Custine Newbie

              Hi Martin,

              First of all, to get your code and stacktraces to appear correctly, you can enclose them with code macros in the plain text editor like this:

               

              \

              junit.framework.AssertionFailedError: null
                  at junit.framework.Assert.fail(Assert.java:47)
                  at junit.framework.Assert.assertTrue(Assert.java:20)
                  at junit.framework.Assert.assertNotNull(Assert.java:214)
                  at junit.framework.Assert.assertNotNull(Assert.java:207)
              <missing part of stack trace>
              \

               

              Which then shows up like this

               

              junit.framework.AssertionFailedError: null
                  at junit.framework.Assert.fail(Assert.java:47)
                  at junit.framework.Assert.assertTrue(Assert.java:20)
                  at junit.framework.Assert.assertNotNull(Assert.java:214)
                  at junit.framework.Assert.assertNotNull(Assert.java:207)
              

               

              I am not sure that a wiretap will work between the cxf bc and se, but feel free to post the current exceptions you are getting and we will take a look at them.

               

              Thanks,

              Chris

              • 4. Re: Wiretap between cxf-bc and cxf-se
                Martin Murphy Novice

                Thanks for the reply Chris, here's my current stack trace, as you can see its in the CXF interceptor now. So I'm going to debug this before posting to the Fuse Services Framework forum.

                 

                30-Jan-2008 07:44:43 org.apache.cxf.phase.PhaseInterceptorChain doIntercept
                INFO: Interceptor has thrown exception, unwinding now
                java.lang.NullPointerException
                        at org.apache.cxf.binding.jbi.interceptor.JBIWrapperInInterceptor.handleMessage(JBIWrapperInInterceptor.java:105)
                        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:207)
                        at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:73)
                        at org.apache.cxf.transport.jbi.JBIDispatcherUtil.dispatch(JBIDispatcherUtil.java:148)
                        at org.apache.servicemix.cxfse.CxfSeEndpoint.process(CxfSeEndpoint.java:180)
                        at org.apache.servicemix.common.AsyncBaseLifeCycle.doProcess(AsyncBaseLifeCycle.java:538)
                        at org.apache.servicemix.common.AsyncBaseLifeCycle.processExchange(AsyncBaseLifeCycle.java:490)
                        at org.apache.servicemix.common.BaseLifeCycle.onMessageExchange(BaseLifeCycle.java:46)
                        at org.apache.servicemix.jbi.messaging.DeliveryChannelImpl.processInBound(DeliveryChannelImpl.java:610)
                        at org.apache.servicemix.jbi.nmr.flow.AbstractFlow.doRouting(AbstractFlow.java:170)
                        at org.apache.servicemix.jbi.nmr.flow.seda.SedaFlow.doRouting(SedaFlow.java:167)
                        at org.apache.servicemix.jbi.nmr.flow.seda.SedaQueue$1.run(SedaQueue.java:134)
                        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
                        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
                        at java.lang.Thread.run(Thread.java:595)
                30-Jan-2008 07:44:43 org.apache.cxf.transport.jbi.JBIDestinationOutputStream commitOutputMessage
                SEVERE: error sending Out message
                java.lang.ClassCastException: java.lang.NullPointerException
                        at org.apache.cxf.transport.jbi.JBIDestinationOutputStream.commitOutputMessage(JBIDestinationOutputStream.java:89)
                        at org.apache.cxf.transport.jbi.JBIDestinationOutputStream.doClose(JBIDestinationOutputStream.java:62)
                        at org.apache.cxf.io.CachedOutputStream.close(CachedOutputStream.java:119)
                        at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:66)
                        at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
                        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:207)
                        at org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:90)
                        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:224)
                        at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:73)
                        at org.apache.cxf.transport.jbi.JBIDispatcherUtil.dispatch(JBIDispatcherUtil.java:148)
                        at org.apache.servicemix.cxfse.CxfSeEndpoint.process(CxfSeEndpoint.java:180)
                        at org.apache.servicemix.common.AsyncBaseLifeCycle.doProcess(AsyncBaseLifeCycle.java:538)
                        at org.apache.servicemix.common.AsyncBaseLifeCycle.processExchange(AsyncBaseLifeCycle.java:490)
                        at org.apache.servicemix.common.BaseLifeCycle.onMessageExchange(BaseLifeCycle.java:46)
                        at org.apache.servicemix.jbi.messaging.DeliveryChannelImpl.processInBound(DeliveryChannelImpl.java:610)
                        at org.apache.servicemix.jbi.nmr.flow.AbstractFlow.doRouting(AbstractFlow.java:170)
                        at org.apache.servicemix.jbi.nmr.flow.seda.SedaFlow.doRouting(SedaFlow.java:167)
                        at org.apache.servicemix.jbi.nmr.flow.seda.SedaQueue$1.run(SedaQueue.java:134)
                        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
                        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
                        at java.lang.Thread.run(Thread.java:595)
                30-Jan-2008 07:44:53 org.apache.cxf.phase.PhaseInterceptorChain doIntercept
                INFO: Interceptor has thrown exception, unwinding now
                org.apache.cxf.interceptor.Fault
                        at org.apache.servicemix.cxfbc.CxfBcConsumer$JbiPostInvokerInterceptor.handleMessage(CxfBcConsumer.java:428)
                        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:207)
                        at org.apache.cxf.phase.PhaseInterceptorChain.resume(PhaseInterceptorChain.java:184)
                        at org.apache.servicemix.cxfbc.CxfBcConsumer.process(CxfBcConsumer.java:172)
                        at org.apache.servicemix.cxfbc.CxfBcConsumer$JbiInvokerInterceptor.handleMessage(CxfBcConsumer.java:404)
                        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:207)
                        at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:73)
                        at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.serviceRequest(JettyHTTPDestination.java:268)
                        at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:224)
                        at org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:54)
                        at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:712)
                        at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:211)
                        at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139)
                        at org.mortbay.jetty.Server.handle(Server.java:324)
                        at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:506)
                        at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:843)
                        at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:648)
                        at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
                        at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:381)
                        at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:396)
                        at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:442)
                

                 

                The CXF code in this area is:

                 

                            BindingOperationInfo bop = ex.get(BindingOperationInfo.class);
                            DataReader<XMLStreamReader> dr = getDataReader(message);
                            List<Object> parameters = new ArrayList<Object>();
                            reader.next();
                            BindingMessageInfo messageInfo = !isRequestor(message) ? bop.getInput() : bop.getOutput();  //// LINE 105
                

                 

                I've just realised that I can set an operation attribute on the eip:exchange-target element. I'll try that and check back. At the moment my xbean for the wiretap looks like this:

                 

                  <eip:wire-tap service="person:wiretapIn" endpoint="endpoint">
                    <eip:target>
                      <eip:exchange-target service="person:PersonService" interface="person:Person"></eip:exchange-target>
                    </eip:target>
                    <eip:inListener>
                      <eip:exchange-target service="test:jmsWiretapOut"></eip:exchange-target>
                    </eip:inListener>
                  </eip:wire-tap>
                

                 

                • 5. Re: Wiretap between cxf-bc and cxf-se
                  Martin Murphy Novice

                  I finally got this to work after a bit of debugging I spotted that my eip xbean was incomplete. You need to pass the interface and operation in the exchange-target for the wiretap otherwise the cxf-se will not be able to dispatch the message.

                   

                  Here's what a working xbean.xml for a wire-tap between the cxf-wsdl-first example's BC and SE would look like:

                   

                  <?xml version="1.0" encoding="UTF-8"?>
                  <beans xmlns:eip="http://servicemix.apache.org/eip/1.0"
                       xmlns:person="http://servicemix.apache.org/samples/cxf-wsdl-first"
                         xmlns:test="http://test">
                    <eip:wire-tap service="person:wiretapIn" endpoint="endpoint">
                      <eip:target>
                        <eip:exchange-target service="person:PersonService" interface="person:Person" operation="person:GetPerson"></eip:exchange-target>
                      </eip:target>
                      <eip:inListener>
                        <eip:exchange-target service="test:jmsWiretapOut"></eip:exchange-target>
                      </eip:inListener>
                    </eip:wire-tap>
                  </beans>
                  

                   

                  Of course you will also need to update the BC to point to the wire-tap

                   

                  <beans xmlns:cxfbc="http://servicemix.apache.org/cxfbc/1.0"
                         xmlns:person="http://servicemix.apache.org/samples/cxf-wsdl-first">
                    <cxfbc:consumer wsdl="classpath:person.wsdl"
                                        targetService="person:wiretapIn"></cxfbc:consumer>
                  </beans>
                  

                   

                  The listener I have on the wiretap is a JMS queue, but this could be anything really, eg write to a file etc.

                   

                  I've marked this question as answered now, in short you can insert a wiretap between cxf-bc and cxf-se

                  • 6. Re: Wiretap between cxf-bc and cxf-se
                    Guillaume Nodet Newbie

                    I think there is a problem though.

                    If your service defines multiple operations, the same operation will always be called, which will obviously lead to failures.

                    In such case, the wireTap should copy the operation information set by the BC imho.

                    The interface should not be a problem because it is not meant to change from exchange to exchange.

                    • 7. Re: Wiretap between cxf-bc and cxf-se
                      Martin Murphy Novice

                      Yeah, good point. How would I copy the operation from the BC though?

                      • 8. Re: Wiretap between cxf-bc and cxf-se
                        Guillaume Nodet Newbie

                        There's no way currently.  I was implying that the EIP component should be enhanced to allow that.

                        You may want to raise a JIRA issue for that.