6 Replies Latest reply on Jun 29, 2006 11:41 AM by jiehuan_li

    Invoking one service after another causing exception in jbpm

    jiehuan_li

      I deployed 2 JSR 181 web services, and I am trying to use jbpm bpel to orchestrate the 2 web services. Both web services accept an input string and return it as the output, and they are individually tested and working fine. Below is my .bpel content:

       <partnerLinks>
       <partnerLink name="jbpmbpelRelation" partnerLinkType="tns:jbpmbpel-front" myRole="frontEnd" />
       <partnerLink name="svcRelation" partnerLinkType="tns:front-svc" partnerRole="svcRole" />
       <partnerLink name="svc2Relation" partnerLinkType="tns:front-svc2" partnerRole="svc2Role" />
       </partnerLinks>
      
       <variables>
       <variable name="connectReq" messageType="jbpmbpel:jbpmbpelInputMessage" />
       <variable name="connectResp" messageType="jbpmbpel:jbpmbpelOutputMessage" />
       <variable name="svcReq" messageType="svc:EndpointInterface_echo" />
       <variable name="svc2Req" messageType="svc2:EndpointInterface2_echo2" />
       <variable name="svcOutputMsg" messageType="svc:EndpointInterface_echoResponse" />
       <variable name="svc2OutputMsg" messageType="svc2:EndpointInterface2_echo2Response" />
       </variables>
      
       <sequence name="mainSequence">
      
       <receive operation="connect" partnerLink="jbpmbpelRelation" portType="jbpmbpel:jbpmbpelFrontEnd"
       variable="connectReq" createInstance="yes" />
      
       <assign name="connectionStart">
       <copy>
       <from variable="connectReq" part="request" />
       <to variable="svcReq" part="String_1" />
       </copy>
       </assign>
      
       <invoke operation="echo" partnerLink="svcRelation" portType="svc:EndpointInterface"
       inputVariable="svcReq" outputVariable="svcOutputMsg" />
      
       <assign name="connectionBetween">
       <copy>
       <from variable="svcOutputMsg" part="result" />
       <to variable="svc2Req" part="String_1" />
       </copy>
       </assign>
      
       <invoke operation="echo2" partnerLink="svc2Relation" portType="svc2:EndpointInterface2"
       inputVariable="svc2Req" outputVariable="svc2OutputMsg" />
      
       <assign name="connectionEnd">
       <copy>
       <from variable="svc2OutputMsg" part="result" />
       <to variable="connectResp" part="result" />
       </copy>
       </assign>
      
       <reply operation="connect" partnerLink="jbpmbpelRelation" portType="jbpmbpel:jbpmbpelFrontEnd" variable="connectResp" />
      
       </sequence>
      


      As you can see, the process accept an input string, hands it over to the first service, then the output of the first service is fed into the second service, and the output of the second service will be returned to the caller. For some reason I am getting the following exception when I am testing the bpel service:

      13:46:39,152 ERROR [StartListener] could not start process instance
      java.lang.reflect.InvocationTargetException
       at sun.reflect.GeneratedMethodAccessor262.invoke(Unknown Source)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:585)
       at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:208)
       at org.jbpm.bpel.def.Receive_$$_javassist_24.accept(Receive_$$_javassist_24.java)
       at org.jbpm.bpel.def.ProcessInstanceStarter.visit(ProcessInstanceStarter.java:82)
       at org.jbpm.bpel.def.Sequence.accept(Sequence.java:84)
       at org.jbpm.bpel.def.ProcessInstanceStarter.visit(ProcessInstanceStarter.java:29)
       at org.jbpm.bpel.def.BpelDefinition.messageReceived(BpelDefinition.java:110)
       at org.jbpm.bpel.relation.jms.StartListener.onMessage(StartListener.java:94)
       at org.jboss.mq.SpyMessageConsumer.run(SpyMessageConsumer.java:694)
       at java.lang.Thread.run(Thread.java:595)
      Caused by: org.jbpm.graph.def.DelegationException
       at org.jbpm.graph.def.GraphElement.raiseException(GraphElement.java:349)
       at org.jbpm.graph.def.GraphElement.raiseException(GraphElement.java:343)
       at org.jbpm.graph.def.GraphElement.raiseException(GraphElement.java:343)
       at org.jbpm.graph.def.GraphElement.raiseException(GraphElement.java:343)
       at org.jbpm.bpel.def.Activity.enter(Activity.java:88)
       at org.jbpm.graph.def.Transition.take(Transition.java:119)
       at org.jbpm.graph.def.Node.leave(Node.java:382)
       at org.jbpm.bpel.def.Activity.leave(Activity.java:148)
       at org.jbpm.bpel.def.ProcessInstanceStarter.visit(ProcessInstanceStarter.java:43)
       at org.jbpm.bpel.def.Receive.accept(Receive.java:64)
       ... 12 more
      Caused by: org.jbpm.graph.def.DelegationException
       at org.jbpm.graph.def.GraphElement.raiseException(GraphElement.java:349)
       at org.jbpm.graph.def.GraphElement.raiseException(GraphElement.java:343)
       at org.jbpm.graph.def.GraphElement.raiseException(GraphElement.java:343)
       at org.jbpm.graph.def.GraphElement.raiseException(GraphElement.java:343)
       at org.jbpm.bpel.def.Activity.enter(Activity.java:88)
       at org.jbpm.graph.def.Transition.take(Transition.java:119)
       at org.jbpm.graph.def.Node.leave(Node.java:382)
       at org.jbpm.bpel.def.Activity.leave(Activity.java:148)
       at org.jbpm.bpel.def.Assign.execute(Assign.java:41)
       at org.jbpm.bpel.def.Activity.enter(Activity.java:83)
       ... 17 more
      Caused by: org.jbpm.graph.def.DelegationException
       at org.jbpm.graph.def.GraphElement.raiseException(GraphElement.java:349)
       at org.jbpm.graph.def.GraphElement.raiseException(GraphElement.java:343)
       at org.jbpm.graph.def.GraphElement.raiseException(GraphElement.java:343)
       at org.jbpm.graph.def.GraphElement.raiseException(GraphElement.java:343)
       at org.jbpm.bpel.def.Activity.enter(Activity.java:88)
       at org.jbpm.graph.def.Transition.take(Transition.java:119)
       at org.jbpm.graph.def.Node.leave(Node.java:382)
       at org.jbpm.bpel.def.Activity.leave(Activity.java:148)
       at org.jbpm.bpel.def.Invoke.execute(Invoke.java:29)
       at org.jbpm.bpel.def.Activity.enter(Activity.java:83)
       ... 22 more
      Caused by: org.jbpm.graph.def.DelegationException
       at org.jbpm.graph.def.GraphElement.raiseException(GraphElement.java:349)
       at org.jbpm.graph.def.GraphElement.raiseException(GraphElement.java:343)
       at org.jbpm.graph.def.GraphElement.raiseException(GraphElement.java:343)
       at org.jbpm.graph.def.GraphElement.raiseException(GraphElement.java:343)
       at org.jbpm.bpel.def.Activity.enter(Activity.java:88)
       at org.jbpm.graph.def.Transition.take(Transition.java:119)
       at org.jbpm.graph.def.Node.leave(Node.java:382)
       at org.jbpm.bpel.def.Activity.leave(Activity.java:148)
       at org.jbpm.bpel.def.Assign.execute(Assign.java:41)
       at org.jbpm.bpel.def.Activity.enter(Activity.java:83)
       ... 27 more
      Caused by: java.lang.NullPointerException
       at org.jbpm.bpel.service.consumer.PortConsumer.writeMessage(PortConsumer.java:154)
       at org.jbpm.bpel.service.consumer.PortConsumer.callImpl(PortConsumer.java:127)
       at org.jbpm.bpel.service.consumer.PortConsumer.call(PortConsumer.java:96)
       at org.jbpm.bpel.relation.jms.JmsRelationService.invoke(JmsRelationService.java:143)
       at org.jbpm.bpel.def.Invoke.execute(Invoke.java:28)
       at org.jbpm.bpel.def.Activity.enter(Activity.java:83)
       ... 32 more
      


      If I remove any one of the two 'invoke' in the .bpel file and make it only in and out of one service, everything works fine.

      What did I miss? Any help would be highly appreciated!

      Jiehuan

        • 1. Re: Invoking one service after another causing exception in
          jiehuan_li

          Just want to clarify, it is causing exception in jbpm bpel. And it is urgent, please help!

          Thanks,
          Jiehuan

          • 2. Re: Invoking one service after another causing exception in
            aguizar

            The statement at PortConsumer.java:154 is:

            // obtain info on the operation as a whole
             SOAPOperation soapOperation = (SOAPOperation) WsdlUtil.getExtension(
             bindOperation.getExtensibilityElements(), SOAPConstants.Q_ELEM_SOAP_OPERATION);

            The only source for a NPE is the bindOperation being null. Earlier on the writeMessage() method:
            BindingOperation bindOperation = binding.getBindingOperation(operation, null, null);

            It looks like your WSDL binding does not include one of the requested operations. The static analysis that jBPM BPEL performs only checks for the operation being present on the port type.

            If this does not help, zip and email your project to me.

            • 3. Re: Invoking one service after another causing exception in
              jiehuan_li

              I found a fix for this. On org.jbpm.bpel.relation.jms.RelationContext, comment out one line like following, and initialize portConsumer to null:

               public PortConsumer getPortConsumer(PartnerLinkInstance instance) {
               Long instanceId = new Long(instance.getId());
               PortConsumer portConsumer = null;
               synchronized (portConsumers) {
               //portConsumer = (PortConsumer) portConsumers.get(instanceId); -- commented out to fix the nullpointer exception.
               if (portConsumer == null) {
               EndpointReference partnerRef = instance.getPartnerReference();
               if (partnerRef == null) {
               partnerRef = createPartnerReference(instance.getDefinition());
               instance.setPartnerReference(partnerRef);
               log.debug("initialized partner reference: instance=" + instance +
               ", reference=" + partnerRef);
               }
               // select a port from the service catalog
               Port port = partnerRef.selectPort(getServiceCatalog());
               log.debug("selected partner port: instance=" + instance + ", port=" + port.getName());
               // create a consumer for that port
               portConsumer = new PortConsumer(port);
               portConsumers.put(instanceId, portConsumer);
               }
               }
               return portConsumer;
               }
              


              The problem was that somehow in my case instance.getId() always returns 0, so the first cached portConsumer was always returned, even when a new one should have been created.

              The fix basicly bypasses the caching mechanism on portConsumers. And now invoking one service after another works. This is probably the laziest fix. I'll dig more into it and see why jbpm always returns instance with instance id set to 0 in this case when I get a chance.

              • 4. Re: Invoking one service after another causing exception in
                aguizar

                From the stack trace above,

                at org.jbpm.bpel.def.ProcessInstanceStarter.visit(ProcessInstanceStarter.java:82)


                the process instance is starting, no transaction has been committed and the partner link instances are still transient.

                A different approach to fix the problem is assigning an ID to the transient instances:

                public PortConsumer getPortConsumer(PartnerLinkInstance instance) {
                 Long instanceId = new Long(getOrAssignId(instance));
                 PortConsumer portConsumer;
                 synchronized (portConsumers) {
                 // retrieve cached port consumer
                 portConsumer = (PortConsumer) portConsumers.get(instanceId);
                 if (portConsumer == null) {
                 // no cached consumer, create one from partner endpoint reference
                 EndpointReference partnerRef = instance.getPartnerReference();
                 if (partnerRef == null) {
                 // no partner reference, create one containing only the port type as selection criterion
                 partnerRef = createPartnerReference(instance.getDefinition());
                 instance.setPartnerReference(partnerRef);
                 log.debug("initialized partner reference: instance=" + instance +
                 ", reference=" + partnerRef);
                 }
                 // select a port from the service catalog with the criteria known at this point
                 Port port = partnerRef.selectPort(getServiceCatalog());
                 log.debug("selected partner port: instance=" + instance + ", port=" + port.getName());
                 // create a consumer for that port
                 portConsumer = new PortConsumer(port);
                 portConsumers.put(instanceId, portConsumer);
                 }
                 }
                 return portConsumer;
                 }


                The code for assigning an identifier is simply:
                private static long getOrAssignId(PartnerLinkInstance instance) {
                 long instanceId = instance.getId();
                 // in case instance is transient, assign an identifier to it
                 if (instanceId == 0L) {
                 Services.assignId(instance);
                 instanceId = instance.getId();
                 }
                 return instanceId;
                 }

                I introduced getOrAssignId() because RelationContext has another method that uses a potentially transient partner link instance:
                private static Object createKey(PartnerLinkInstance partnerLinkInstance,
                 Operation operation, String messageExchange) {
                 return new OutstandingRequest.Key(getOrAssignId(partnerLinkInstance),
                 operation.getName(), messageExchange);
                 }

                It'd be great if you could try these other fixes too.

                • 5. Re: Invoking one service after another causing exception in
                  jiehuan_li
                  • 6. Re: Invoking one service after another causing exception in
                    jiehuan_li

                    Alex, thanks for the pointers. I tried your fix, and it works.