How does one Set the “Pick” Expression for Apache Camel's FlexibleAggregationStrategy in Spring XML?

 ̄綄美尐妖づ 提交于 2019-12-06 10:11:36

问题


I am attempting to configure an Apache Camel route in Spring XML using Apache Camel 2.14. The route will involve either an <aggregator> or an <enrich>/<pollEnrich>; I'm not yet experienced enough with Camel to know which EIP will be most useful. Either way, I'm going to need an aggregationStrategy. My end goal involves creating a Camel route for a client who wants the routes configured in XML.

By searching around the Internet, I learned of the existence of a Camel class called FlexibleAggregationStrategy. The things I found claim, and I quote, "It allows you to quickly whip up an AggregationStrategy that is capable of performing the most typical aggregation duties, with zero Java code." This sounds useful to me, since we want as much of the configuration in XML as possible. As such, it would be nice to avoid writing my own AggregationStrategy in Java. The problem is, I can't figure out how to use a FlexibleAggregationStrategy.

From what I can tell, the FlexibleAggregationStrategy picks elements from messages to aggregate using an Expression called pickExpression, and filters out messages that match the Predicate conditionPredicate. So, I assume I need to have a way to set these values in my Spring XML. Unfortunately, I haven't been able to get the following blocks of code work:

Property name set to pickExpression, value as element:

<bean id="FlexibleAggregationStrategy"
    class="org.apache.camel.util.toolbox.FlexibleAggregationStrategy">
    <property name="pickExpression">
        <xpath>
            //ID
        </xpath>
    </property>
</bean>

Property name set to pick, value as element:

<bean id="FlexibleAggregationStrategy"
    class="org.apache.camel.util.toolbox.FlexibleAggregationStrategy">
    <property name="pick">
        <xpath>
            //ID
        </xpath>
    </property>
</bean>

Property name set to pickExpression, value as attribute:

<bean id="FlexibleAggregationStrategy"
    class="org.apache.camel.util.toolbox.FlexibleAggregationStrategy">
    <property name="pickExpression" value="&lt;xpath&gt;//ID&lt;/xpath&gt;"/>
</bean>

Property name set to pick, value as attribute:

<bean id="FlexibleAggregationStrategy"
    class="org.apache.camel.util.toolbox.FlexibleAggregationStrategy">
    <property name="pick" value="&lt;xpath&gt;//ID&lt;/xpath&gt;"/>
</bean>

Each time, I get an error complaining that it's unable to find the property descriptor with the name I give it. The reason I try both pick and pickExpression is that, in what appears to be the source code for FlexibleAggregationStrategy, the variable holding the pick expression in the class is named pickExpression, but the method to set it is simply called pick().

I don't have a perfect understanding of Spring XML, but based on what I know, using the <property> tag to set a variable value requires the bean to have getters and setters for that variable. Since FlexibleAggregationStrategy does not have getters and setters for pickExpression, I'm following the wrong approach anyway. However, if I'm reading the XML Schema Definition for the <bean> tag correctly, the only way to send information to a bean is with the <property> tag or with constructor parameters. Since FlexibleAggregationStrategy has no constructors that set pickExpression, I haven't found a way to configure a FlexibleAggregationStrategy without writing Java code.

I've found references to something called "method injection" that might allow me to configure a FlexibleAggregationStrategy. However, the only instructions I've found involve writing a bean in Java. As such, this technique also involves writing Java code; in addition, it seems like it would be faster and more direct to just write my own AggregationStrategy.

As of now, neither the old nor new Apache Camel Wiki pages documenting the <aggregator> pattern does not mention FlexibleAggregationStrategy at all.

I have attempted a Google search for the term FlexibleAggregationStrategy to see if anybody has written any tutorials or documentation for using a FlexibleAggregationStrategy. As of now, the first two Google results I get are automatically-generated Javadoc for the FlexibleAggregationStrategy class. The third result is the github-hosted sourcecode I linked above. The fourth result is another question on this topic that I posted; this question was closed because I didn't understand how to write proper StackOverflow questions. The fifth result is the source code hosted on grepcode.com. The sixth result is the Javadoc for an interface I don't understand. The seventh result is a question somebody else asked on grokbase.com; the question has no answers. The eigth result is a question somebody else asked on qnalist.com that also has no answers. The ninth result seems to be from a mailing list involving committing the source code for the FlexibleAggregationStrategy class. The tenth result is the question from grokbase posted to osdir.com. Similar searches return mostly the same results; the other new results I find are equally unhelpful. I think that, if somebody had written a good guide for using FlexibleAggregationStrategy, it would come up in those searches.

Is there anybody who has used a FlexibleAggregationStrategy who can tell me how to set the pickExpression and conditionPredicate so I can use a FlexibleAggregationStrategy? If you know of anything else I would need to configure it, or any other common pitfalls surrounding it, that information would also be appreciated.

Thank you for your time.


回答1:


Looking at the javadoc I'd say this class is not Camel XML-DSL-friendly and intended to be used with the Camel fluent Java-DSL. You're out of luck if you want to use it with Spring-DSL.

Your use case can probably be easier implemented by transforming the result body in the enrichment route using your xpath expression and then aggregate it with UseLatestAggregationStrategy which essentially makes the enrichment exchange the result of the aggregation:

<bean id="useLatest" class="org.apache.camel.processor.aggregate.UseLatestAggregationStrategy"/>

<camel:route id="main">
    ...
    <camel:enrich uri="direct:enrich" strategyRef="useLatest"/>
    ...
</camel:route>

<camel:route id="enrichment">
    <camel:from uri="direct:enrich"/>

    ...enrichment processing here...

    <camel:setBody>
        <camel:xpath>//ID</camel:xpath>
    </camel:setBody>
</camel:route>

Hope that helps.




回答2:


Spring's XML format isn't really geared towards fluent builders but you can do it. For example, to replicate this:

delegateStrategy = new FlexibleAggregationStrategy<Object>()
        .storeInBody()
        .accumulateInCollection(ArrayList.class)
        .pick(new SimpleExpression("${header[CamelFileName]}"));

would require this XML:

<bean id="_flexible0" class="org.apache.camel.util.toolbox.FlexibleAggregationStrategy"/>
<bean id="_flexible1" factory-bean="_flexible0" factory-method="storeInBody" />
<bean id="_flexible2" factory-bean="_flexible1" factory-method="accumulateInCollection">
  <constructor-arg value="java.util.ArrayList" />
</bean>
<bean id="fileNameListStrategy" factory-bean="_flexible2" factory-method="pick">
  <constructor-arg>
    <bean class="org.apache.camel.model.language.SimpleExpression">
      <constructor-arg type="java.lang.String" value="${header[CamelFileName]}" />
    </bean>
  </constructor-arg>
</bean>

As you see, it's not very concise, and requires creating a number of intermediate beans, but it is possible.

However, if you are not limited to zero custom Java, you could create your own AggregationStrategy that delegates to a FlexibleAggregationStrategy and use that in your XML.

Java portion:

public class FileNameListAggregationStrategy implements AggregationStrategy {

    private CompletionAwareAggregationStrategy delegateStrategy;

    public FileNameListAggregationStrategy() {
        delegateStrategy = new FlexibleAggregationStrategy<Object>()
                .storeInBody()
                .accumulateInCollection(ArrayList.class)
                .pick(new SimpleExpression("${header[CamelFileName]}"));
    }

    @Override
    public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
        return delegateStrategy.aggregate(oldExchange, newExchange);
    }

}

XML portion:

<bean id="fileNameListStrategy" class="org.example.camel.FileNameListStrategy"/>


来源:https://stackoverflow.com/questions/27404726/how-does-one-set-the-pick-expression-for-apache-camels-flexibleaggregationstr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!