【问题标题】:Mule ESB dynamically set Endpoint PathMule ESB 动态设置端点路径
【发布时间】:2012-10-27 01:35:40
【问题描述】:

我正在尝试构建一个 Web 服务,该服务接受许多用于构建 Bing 查询 API 路径的变量。出于某种原因,如果我构建 URI,我的流程会识别出新 URI 已正确分配给有效负载,但是当我将有效负载分配给出站 HTTP 端点时,它会失败。

<flow name="BingQuery" doc:name="BingQuery">
        <http:inbound-endpoint exchange-pattern="one-way" host="localhost" port="8082" doc:name="HTTP" />
       <set-variable variableName="query" doc:name="Variable" value="#[header:INBOUND:query]"/>
       <set-variable variableName="numResults" doc:name="Variable" value="#[header:INBOUND:top]"/>
       <set-variable variableName="offsetResults" doc:name="Variable" value="#[header:INBOUND:offset]"/>
       <scripting:component doc:name="Groovy">
           <scripting:script engine="Groovy">
               <scripting:text><![CDATA[def query = message.getInvocationProperty("query")
                def numResults = message.getInvocationProperty("numResults")
                def offsetResults = message.getInvocationProperty("offsetResults")
                def path = "Data.ashx/Bing/Search/v1/Web?Query=" + "$query" + "&amp;WebFileType=%27PDF%27&amp;\$top=" + "$numResults" + "&amp;\$skip=" + "$offsetResults" + "&amp;\$format=Json"
                    println "$path"
                    message.setProperty("pathVar","$path")
                    return null;]]></scripting:text>
           </scripting:script>
       </scripting:component> 
       <logger level="INFO" doc:name="Logger" message="#[header:OUTBOUND:pathVar]"/> 
        <https:outbound-endpoint exchange-pattern="request-response"
            host="api.datamarket.azure.com" port="443" path="#[header:OUTBOUND:pathVar]"
            user="*****" password="******"
            doc:name="Bing" /> ...

我得到的例外是

ERROR 2012-10-25 14:14:26,250 [[poll_directory].BingQuery.stage1.02] org.mule.exception.DefaultMessagingExceptionStrategy: 
********************************************************************************
Message               : Failed to transform from "json" to "java.util.Map"
Code                  : MULE_ERROR-65110
--------------------------------------------------------------------------------
Exception stack is:
1. Unexpected character ('T' (code 84)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
at [Source: java.io.InputStreamReader@73b62d67; line: 1, column: 2] (org.codehaus.jackson.JsonParseException)
 org.codehaus.jackson.JsonParser:1291 (null)
2. Failed to transform from "json" to "java.util.Map" (org.mule.api.transformer.TransformerException)
 org.mule.module.json.transformers.JsonToObject:136 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/transformer/TransformerException.html)
--------------------------------------------------------------------------------
Root Exception stack trace:
org.codehaus.jackson.JsonParseException: Unexpected character ('T' (code 84)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
at [Source: java.io.InputStreamReader@73b62d67; line: 1, column: 2]
    at org.codehaus.jackson.JsonParser._constructError(JsonParser.java:1291)
    at org.codehaus.jackson.impl.JsonParserMinimalBase._reportError(JsonParserMinimalBase.java:385)
    at org.codehaus.jackson.impl.JsonParserMinimalBase._reportUnexpectedChar(JsonParserMinimalBase.java:306)
   + 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************

它不能正常工作肯定有一个简单的原因,我确信这只是因为我还不知道 Mule 中的正确语法。我也知道使用 MEL 和 Groovy 可能有更好的方法来做到这一点,但我对 MEL 还不够熟悉,无法做到这一点。

解决方案

原来 User 属性和 Password 属性的某些字符在发送之前已被编码。在传递给用户和密码属性之前将该密钥放入变量中可以防止这种情况并导致成功。

<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:json="http://www.mulesoft.org/schema/mule/json"
    xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns:http="http://www.mulesoft.org/schema/mule/http"
    xmlns:https="http://www.mulesoft.org/schema/mule/https" xmlns:file="http://www.mulesoft.org/schema/mule/file"
    xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
    xmlns:spring="http://www.springframework.org/schema/beans" xmlns:core="http://www.mulesoft.org/schema/mule/core"
    version="CE-3.3.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd 
http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd 
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd 
http://www.mulesoft.org/schema/mule/https http://www.mulesoft.org/schema/mule/https/current/mule-https.xsd 
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd 
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd 
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd 
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd ">
    <configuration doc:name="Configuration">
        <expression-language>
            <import class="org.mule.util.StringUtils" />
        </expression-language>
    </configuration>
    <flow name="BingQuery" doc:name="BingQuery">
        <http:inbound-endpoint exchange-pattern="one-way" host="localhost" port="8082" doc:name="HTTP" />
       <set-variable variableName="query" doc:name="Variable" value="#[header:INBOUND:query]"/>
       <set-variable variableName="numResults" doc:name="Variable" value="#[header:INBOUND:top]"/>
       <set-variable variableName="offsetResults" doc:name="Variable" value="#[header:INBOUND:offset]"/>
        <scripting:component doc:name="Groovy">
          <scripting:script engine="Groovy">
              <scripting:text><![CDATA[def query = message.getInvocationProperty("query")
               def numResults = message.getInvocationProperty("numResults")
               def offsetResults = message.getInvocationProperty("offsetResults")
               def path = "Data.ashx/Bing/Search/v1/Web?Query=" + "$query" + "&WebFileType=%27PDF%27&\$top=" + "$numResults" + "&\$skip=" + "$offsetResults" + "&\$format=Json"
                   println "$path"
                   message.setProperty("pathVar","$path")
                   message.setProperty("APIIdentifier","*****")
                   return null;]]></scripting:text>
          </scripting:script>
      </scripting:component>
        <https:outbound-endpoint exchange-pattern="request-response"
            host="api.datamarket.azure.com" port="443" path="#[header:OUTBOUND:pathVar]"
            user="#[header:OUTBOUND:APIIdentifier]" password="#[header:OUTBOUND:APIIdentifier]"
            doc:name="Bing" />
        <json:json-to-object-transformer
            returnClass="java.util.Map" doc:name="JSON to Object" />
        <expression-transformer expression="#[message.payload.d.results]"
            doc:name="Expression" />
        <collection-splitter doc:name="Collection Splitter" />
        <vm:outbound-endpoint exchange-pattern="one-way"
            path="fileWriter" doc:name="VM" />
    </flow>
    <flow name="RestProcessor" doc:name="RestProcessor">
        <vm:inbound-endpoint exchange-pattern="one-way"
            path="fileWriter" doc:name="VM" />
        <set-variable variableName="fileName" value="#[message.payload.ID].pdf"
            doc:name="Variable" />
        <http:rest-service-component
            serviceUrl="#[joinChar=message.payload.Url.contains('?')?'&amp;':'?' ; StringUtils.join(new String[]{message.payload.Url,(String)joinChar,'followRedirects=true'})]"
            httpMethod="GET">
           <http:error-filter> 
               <expression-filter expression="#[Integer.valueOf(message.inboundProperties['http.status']) &gt;= 400]"></expression-filter> 
           </http:error-filter>
        </http:rest-service-component>
        <file:outbound-endpoint path="/home/administrator/Documents"
            outputPattern="#[flowVars.fileName]" responseTimeout="10000"
            mimeType="application/pdf" doc:name="File" />
    </flow>
</mule>

【问题讨论】:

    标签: esb mule


    【解决方案1】:

    这里是用 MEL 重写的流程的开始(这对我有用,尽管我针对测试端点而不是 Bing 进行了测试)。

    请注意,我还在出站 HTTPS 端点上将方法设置为 GET:

    <flow name="BingQuery">
        <http:inbound-endpoint exchange-pattern="one-way"
            host="localhost" port="8082" />
        <set-variable variableName="query"
            value="#[message.inboundProperties.query]" />
        <set-variable variableName="numResults"
            value="#[message.inboundProperties.top]" />
        <set-variable variableName="offsetResults"
            value="#[message.inboundProperties.offset]" />
        <expression-component>
            flowVars['bingQuery'] =
                'Data.ashx/Bing/Search/v1/Web?Query=' + query
              + '&amp;WebFileType=%27PDF%27&amp;$top=' + numResults
              + '&amp;$skip=' + offsetResults
              + '&amp;$format=Json';
            payload = null;
        </expression-component>
        <logger level="ERROR" message="#[bingQuery]" />
        <http:outbound-endpoint exchange-pattern="request-response"
            method="GET"
            host="api.datamarket.azure.com" port="443" path="#[bingQuery]"
            user="*****" password="******" />
    

    如果querynumResultsoffsetResults 变量未在流程的其他地方使用,我建议将用于创建它们的表达式直接内联到expression-component

    【讨论】:

    • 我们记录了 #[payload] 并且它正在踢出正确的路径字符串,但由于某种原因,即使将方法设置为 GET,我们仍然会收到相同的错误。如果我们只是为路径输入字符串文字,它就可以正常工作。
    • 我刚刚更新了我的脚本并得到了同样的错误。记录 #[header:OUTBOUND:pathVar] 给出与以前相同的字符串,但路径失败。
    • 发布了我们的最终解决方案,但您的意见帮助我们调试并最终解决了我们的问题。原来这是 API 密钥的编码问题。除非我们给您我们的 API 密钥,否则您可能不会发现这是一件愚蠢的事情。再次感谢大卫!
    • 哦...我没有粘贴最新的更改,但是我们使用了 MEL 而不是我们最初拥有的 Groovy。也谢谢你。是时候花一些时间在 MEL 上了。
    猜你喜欢
    • 2012-12-28
    • 2014-09-12
    • 1970-01-01
    • 1970-01-01
    • 2017-04-08
    • 2013-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多