[WSO2 ESB] [4.9.0] NPE在发送回时重复

时间:2016-04-08 08:22:27

标签: nullpointerexception iterator wso2 wso2esb

新手在WSO2 ESB上,我们开始将它作为ESB的中心点,但我们通过做一个简单的案例来面对一个真正的问题:/

这是我写的api(based on that simple),即使我们的用例不同,也会向您展示我的问题。

  1. 用户
  2. <?xml version="1.0" encoding="UTF-8" ?>
    <api context="/services/users" name="ListUsersAPI" xmlns="http://ws.apache.org/ns/synapse">
      <resource methods="GET" protocol="http" url-mapping="/*">
        <inSequence>
          <payloadFactory media-type="json">
            <format>{ "persons":{ "person":[ { "Id":"1", "givenName":"ajith", "lastName":"vitharana", "age":"25", "contactInfos":[ { "InfoId":"1", "department":"1", "contactType":"email", "value":"ajith@abc.org" }, { "InfoId":"2", "department":"1", "contactType":"mobile",
              "value":"111111111" }, { "InfoId":"3", "department":"1", "contactType":"home", "value":"Magic Dr,USA" } ] }, { "Id":"2", "givenName":"shammi", "lastName":"jagasingha", "age":"30", "contactInfos":[ { "InfoId":"1", "department":"1", "contactType":"email",
              "value":"shammi@abc.org" }, { "InfoId":"2", "department":"1", "contactType":"mobile", "value":"2222222222" }, { "InfoId":"3", "department":"1", "contactType":"home", "value":"Magic Dr,USA" } ] } ] }}</format>
            <args/>
          </payloadFactory>
          <property action="remove" name="NO_ENTITY_BODY" scope="axis2" />
          <property name="messageType" scope="axis2" type="STRING" value="application/json" />
          <respond/>
        </inSequence>
        <outSequence/>
        <faultSequence/>
      </resource>
    </api>

    1. 角色
    2. <?xml version="1.0" encoding="UTF-8" ?>
      <api context="/services/roles" name="UserRolesAPI" xmlns="http://ws.apache.org/ns/synapse">
        <resource methods="GET" protocol="http" uri-template="/{personid}">
          <inSequence>
            <filter regex="1" source="get-property('uri.var.personid')">
              <then>
                <payloadFactory media-type="json">
                  <format>{ "Id":1, "roles":[ { "roleId":1, "personKey":1, "role":"Deverloper" }, { "roleId":2, "personKey":1, "role":"Engineer" } ]}</format>
                  <args/>
                </payloadFactory>
                <property action="remove" name="NO_ENTITY_BODY" scope="axis2" />
                <property name="messageType" scope="axis2" type="STRING" value="application/json" />
                <respond/>
              </then>
              <else/>
            </filter>
            <filter regex="2" source="get-property('uri.var.personid')">
              <then>
                <payloadFactory media-type="json">
                  <format>{"personId": 2,"roles": [{ "personRoleId": 1, "personKey": 2, "role": "Manager" },{ "personRoleId": 2, "personKey": 2, "role": "QA" }]}</format>
                  <args/>
                </payloadFactory>
                <property action="remove" name="NO_ENTITY_BODY" scope="axis2" />
                <property name="messageType" scope="axis2" type="STRING" value="application/json" />
                <respond/>
              </then>
              <else/>
            </filter>
          </inSequence>
          <outSequence/>
          <faultSequence/>
        </resource>
      </api>

      1. 最后,主要的一个,调用第一个,然后迭代
      2. <?xml version="1.0" encoding="UTF-8" ?>
        <api context="/userdetails" name="UserDetailsAPI" xmlns="http://ws.apache.org/ns/synapse">
          <resource methods="GET" protocol="http">
            <inSequence>
              <call>
                <endpoint>
                  <http method="get" trace="disable" uri-template="http://localhost:8280/services/users" />
                </endpoint>
              </call>
              <iterate attachPath="//jsonObject/persons" expression="//jsonObject/persons/person" id="it1" preservePayload="true" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
                <target>
                  <sequence>
                    <property expression="$body/jsonObject/persons/person/Id" name="uri.var.Id" scope="default" type="STRING" xmlns:ns="http://org.apache.synapse/xsd" />
                    <property expression="$body//jsonObject//person" name="response1" scope="default" type="STRING" xmlns:ns="http://org.apache.synapse/xsd" />
                    <call>
                      <endpoint>
                        <http method="get" trace="disable" uri-template="http://localhost:8280/services/roles/{uri.var.Id}" />
                      </endpoint>
                    </call>
                    <loopback/>
                  </sequence>
                </target>
              </iterate>
            </inSequence>
            <outSequence>
              <send/>
            </outSequence>
            <faultSequence>
              <sequence key="fault" />
            </faultSequence>
          </resource>
        </api>

        执行最后一个api(http://localhost:8280/userdetails)导致以下NPE:

        20160408T101619.566 org.apache.synapse.transport.passthru.PassThroughHttpSender.handleException(PassThroughHttpSender.java:609) [PassThroughMessageProcessor-14] PassThroughHttpSender - Failed to submit the response
        java.lang.NullPointerException
            at org.apache.synapse.transport.passthru.util.SourceResponseFactory.create(SourceResponseFactory.java:64)
            at org.apache.synapse.transport.passthru.PassThroughHttpSender.submitResponse(PassThroughHttpSender.java:462)
            at org.apache.synapse.transport.passthru.PassThroughHttpSender.invoke(PassThroughHttpSender.java:267)
            at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:442)
            at org.apache.synapse.core.axis2.Axis2Sender.sendBack(Axis2Sender.java:212)
            at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.send(Axis2SynapseEnvironment.java:444)
            at org.apache.synapse.mediators.builtin.SendMediator.mediate(SendMediator.java:102)
            at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:81)
            at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:48)
            at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:149)
            at org.apache.synapse.rest.Resource.process(Resource.java:297)
            at org.apache.synapse.rest.API.process(API.java:335)
            at org.apache.synapse.rest.RESTRequestHandler.dispatchToAPI(RESTRequestHandler.java:97)
            at org.apache.synapse.rest.RESTRequestHandler.process(RESTRequestHandler.java:52)
            at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:266)
            at org.apache.synapse.mediators.builtin.LoopBackMediator.mediate(LoopBackMediator.java:55)
            at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:81)
            at org.apache.synapse.mediators.eip.splitter.IterateMediator.mediate(IterateMediator.java:241)
            at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:267)
            at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.mediateFromContinuationStateStack(Axis2SynapseEnvironment.java:679)
            at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:244)
            at org.apache.synapse.core.axis2.SynapseCallbackReceiver.handleMessage(SynapseCallbackReceiver.java:529)
            at org.apache.synapse.core.axis2.SynapseCallbackReceiver.receive(SynapseCallbackReceiver.java:172)
            at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
            at org.apache.synapse.transport.passthru.ClientWorker.run(ClientWorker.java:251)
            at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
            at java.lang.Thread.run(Thread.java:745)
        20160408T101619.576 org.apache.synapse.core.axis2.Axis2Sender.handleException(Axis2Sender.java:246) [PassThroughMessageProcessor-14]     Axis2Sender - Accept:*/*,Accept-Encoding:gzip, deflate, sdch,Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,Cache-Control:no-cache,Content-Type:application/json; charset=UTF-8,Host:localhost:8280,Postman-Token:3bfb96b7-0c31-964e-8c37-3b5dbd222efe,<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><jsonObject><Id>1</Id><roles><roleId>1</roleId><personKey>1</personKey><role>Deverloper</role></roles><roles><roleId>2</roleId><personKey>1</personKey><role>Engineer</role></roles></jsonObject></soapenv:Body></soapenv:Envelope> Unexpected error sending message back
        org.apache.axis2.AxisFault: Failed to submit the response
            at org.apache.synapse.transport.passthru.PassThroughHttpSender.handleException(PassThroughHttpSender.java:610)
            at org.apache.synapse.transport.passthru.PassThroughHttpSender.invoke(PassThroughHttpSender.java:269)
            at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:442)
            at org.apache.synapse.core.axis2.Axis2Sender.sendBack(Axis2Sender.java:212)
            at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.send(Axis2SynapseEnvironment.java:444)
            at org.apache.synapse.mediators.builtin.SendMediator.mediate(SendMediator.java:102)
            at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:81)
            at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:48)
            at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:149)
            at org.apache.synapse.rest.Resource.process(Resource.java:297)
            at org.apache.synapse.rest.API.process(API.java:335)
            at org.apache.synapse.rest.RESTRequestHandler.dispatchToAPI(RESTRequestHandler.java:97)
            at org.apache.synapse.rest.RESTRequestHandler.process(RESTRequestHandler.java:52)
            at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:266)
            at org.apache.synapse.mediators.builtin.LoopBackMediator.mediate(LoopBackMediator.java:55)
            at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:81)
            at org.apache.synapse.mediators.eip.splitter.IterateMediator.mediate(IterateMediator.java:241)
            at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:267)
            at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.mediateFromContinuationStateStack(Axis2SynapseEnvironment.java:679)
            at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:244)
            at org.apache.synapse.core.axis2.SynapseCallbackReceiver.handleMessage(SynapseCallbackReceiver.java:529)
            at org.apache.synapse.core.axis2.SynapseCallbackReceiver.receive(SynapseCallbackReceiver.java:172)
            at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
            at org.apache.synapse.transport.passthru.ClientWorker.run(ClientWorker.java:251)
            at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
            at java.lang.Thread.run(Thread.java:745)
        Caused by: java.lang.NullPointerException
            at org.apache.synapse.transport.passthru.util.SourceResponseFactory.create(SourceResponseFactory.java:64)
            at org.apache.synapse.transport.passthru.PassThroughHttpSender.submitResponse(PassThroughHttpSender.java:462)
            at org.apache.synapse.transport.passthru.PassThroughHttpSender.invoke(PassThroughHttpSender.java:267)
            ... 26 more
        

        我担心,这与here相同(但不确定)。 在我们决定放弃wso2之前,请您帮助我快速避免吗? 更好的方法是通过答案修复第三部分(userdetails)。

        非常感谢!

1 个答案:

答案 0 :(得分:2)

在这种情况下,您的环回在迭代介体内部,并且每次迭代时都调用outSequence。

如果你将loopback mediator从迭代中移出,如下所示,这应该将迭代的最后一个响应发送给客户端。如果要聚合迭代中的响应,则应使用aggregate mediator [1]                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            [1] https://docs.wso2.com/display/ESB490/Aggregate+Mediator

<强>更新

不幸的是上面的解决方案不起作用,因为每次迭代完成时,流程仍然继续,所以即使我们在迭代之外有一个环回,我们也会多次调用outSequence。我们必须使用聚合才能使用完整条件来触发outSequence一次。请看下面的配置。

<api xmlns="http://ws.apache.org/ns/synapse" name="UserDetailsAPI" context="/userdetails">
   <resource methods="GET">
      <inSequence>
         <call>
            <endpoint>
               <http trace="disable" method="GET" uri-template="http://localhost:8280/services/users"/>
            </endpoint>
         </call>
         <iterate xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" id="it1" preservePayload="true" attachPath="//jsonObject/persons" expression="//jsonObject/persons/person">
            <target>
               <sequence>
                  <property xmlns:ns="http://org.apache.synapse/xsd" name="uri.var.Id" expression="$body/jsonObject/persons/person/Id" scope="default" type="STRING"/>
                  <property xmlns:ns="http://org.apache.synapse/xsd" name="response1" expression="$body//jsonObject//person" scope="default" type="STRING"/>
                  <call>
                     <endpoint>
                        <http trace="disable" method="GET" uri-template="http://localhost:8280/services/roles/{uri.var.Id}"/>
                     </endpoint>
                  </call>
               </sequence>
            </target>
         </iterate>
         <aggregate id="it1">
            <completeCondition>
               <messageCount min="-1" max="-1"/>
            </completeCondition>
            <onComplete expression="//jsonObject">
               <loopback/>
            </onComplete>
         </aggregate>
      </inSequence>
      <outSequence>
         <send/>
      </outSequence>
      <faultSequence>
         <sequence key="fault"/>
      </faultSequence>
   </resource>
</api>