8

私はCamelを初めて使用し、Camelを使用して以下のユースケースをどのように実装できるか疑問に思っています.

REST Web サービスがあり、callA と callB の 2 つのサービス操作があるとします。これで、この実際の Web サービス URL に到達する前にクライアント要求をインターセプトする ESB レイヤーが前面に配置されました。

今、私はこのようなことをしようとしています - クライアントが実際に呼び出す ESB で URL を公開します。ESB では、このサービス呼び出しをプロキシするだけの Camel の Jetty コンポーネントを使用しています。この URL を /my-service/scan/ としましょう

このリクエスト @ESB を受け取ったら、これら 2 つの REST エンドポイント (callA と callB) を呼び出したいと思います -> 応答を取得します - resA と resB -> 単一の応答オブジェクト resScan に集約します -> クライアントに戻ります。

私が今持っているのは -

<route id="MyServiceScanRoute">
<from uri="jetty:http://{host}.{port}./my-service/scan/?matchOnUriPrefix=true&amp;bridgeEndpoint=true"/>
<!-- Set service specific headers, monitoring etc. -->  
<!-- Call performScan -->
<to uri="direct:performScan"/>
</route>

<route id="SubRoute_performScan">
<from uri="direct:performScan"/>
<!--  HOW DO I??
Make callA, callB service calls. 
Get their responses resA, resB.
Aggregate these responses to resScan
 -->
</route>
4

2 に答える 2

16

I think that you unnecessarily complicate the solution a little bit. :) In my humble opinion the best way to call two independed remote web services and concatenate the results is to:

The routing for the solution above may look like:

from("direct:serviceFacade")
  .multicast(new GroupedExchangeAggregationStrategy()).parallelProcessing()
    .enrich("http://google.com?q=Foo").enrich("http://google.com?q=Bar")
  .end();

Exchange passed to the direct:serviceFacadeResponse will contain property Exchange.GROUPED_EXCHANGE set to list of results of calls to your services (Google Search in my example).

And that's how could you wire the direct:serviceFacade to Jetty endpoint:

from("jetty:http://0.0.0.0:8080/myapp/myComplexService").enrich("direct:serviceFacade").setBody(property(Exchange.GROUPED_EXCHANGE));

Now all HTTP requests to the service URL exposed by you on ESB using Jetty component will generate responses concatenated from the two calls to the subservices.

Further considerations regarding the dynamic part of messages and endpoints

In many cases using static URL in endpoints is insufficient to achieve what you need. You may also need to prepare payload before passing it to each web service.

Generally speaking - the type of routing used to achieve dynamic endpoints or payloads parameters in highly dependent on the component you use to consume web services (HTTP, CXFRS, Restlet, RSS, etc). Each component varies in the degree and a way in which you can configure it dynamically.

If your endpoints/payloads should be affected dynamically you could also consider the following options:

Preprocess copy of exchange passed to each endpoint using the onPrepareRef option of the Multicast endpoint. You can use it to refer to the custom processor that will modify the payload before passing it to the Multicast's endpoints. This may be good way to compose onPrepareRef with Exchange.HTTP_URI header of HTTP component.

Use Recipient List (which also offers parallelProcessing as the Multicast does) to dynamically create the REST endpoints URLs.

Use Splitter pattern (with parallelProcessing enabled) to split the request into smaller messages dedicated to each service. Once again this option could work pretty well with Exchange.HTTP_URI header of HTTP component. This will work only if both sub-services can be defined using the same endpoint type.

As you can see Camel is pretty flexible and offers you to achieve your goal in many ways. Consider the context of your problem and choose the solution that fits you the best.

If you show me more concrete examples of REST URLs you want to call on each request to the aggregation service I could advice you which solution I will choose and how to implement it. The particularly important is to know which part of the request is dynamic. I also need to know which service consumer you want to use (it will depend on the type of data you will receive from the services).

于 2012-05-21T12:56:42.383 に答える
2

これは、Content Enricher パターンを使用する必要がある良い例のようです。ここに記載

<from uri="direct:performScan"/>
   <enrich uri="ServiceA_Uri_Here" strategyRef="aggregateRequestAndA"/>
   <enrich uri="ServiceA_Uri_Here" strategyRef="aggregateAandB"/>
</route>

アグリゲーション戦略は Java で書かなければなりません (または、おそらく何らかのスクリプト言語、Scala/groovy? - しかし、試したことはありません)。

集約戦略は、1 つのメソッドを実装する必要がある org.apache.camel.processor.aggregate.AggregationStrategy を実装する Bean である必要があります。

Exchange aggregate(Exchange oldExchange, Exchange newExchange);

そのため、要求をエンリッチ サービス呼び出しからの応答とマージするのはあなた次第です。callA と callB の両方があるため、2 回実行する必要があります。UseLatestAggregationStrategy と UseOriginalAggregationStrategy. 名前は非常に自明です。

幸運を

于 2012-05-16T09:09:09.397 に答える