Closed spring-operator closed 13 years ago
Dave Syer commented
It feels uncomfortable to tie the expression source to a properties file in the expression element itself. In the groovy case were you thinking it would be one expression per file (that's the only way it would work with Spring scripting support right now, I think)?
It would feel more natural to me to use a placeholder for the expression. Maybe a custom scope is better if a change to the expression source might invalidate many expressions all at once?
<transformer input-channel="in" output-channel="out">
<expression value="${transformation.userToCity}" scope="refresh"/>
</transformer>
(or just refresh="true"
).
This is actually a special case of a fairly general pattern that could be applied to many Spring apps.
Mark Fisher commented
What about that last example above? There is an expression source with a refresh-check-delay. It can hold multiple expression key value pairs. Then in the actual \
Dave Syer commented
I still don't like it. For me this is not a production time use case, so it's questionable whether we should support it at all. Supposing it really is a production use case then restricting the source of expressions to a file is too restrictive, even if it is hidden behind a Resource. Maybe you can persuade me that the expression source can be a Properties instance, making it explicitly a dereference (as opposed to implicitly in the case of a custom scope). Then to make the expression refreshable I only need to implement a Properties instance that updates itself (eg from a database).
Mark Fisher commented
Please have a look at the prototype in the sandbox. ExpressionSource is in no way restricted to a File. It simply has a getExpression() method. The implementation possibilities are endless.
Mark Fisher commented
Also, I'm wondering why you don't think this would ever be a production use-case. I'm assuming you would not say the same for the Groovy script refresh?
Personally, I would be very careful with either SpEL or Groovy being modified at runtime, but people clearly want these dynamic options.
Mark Fisher commented
I'm moving this to RC1 so we can continue to evolve the example in the sandbox as well as explore alternative implementation ideas (e.g. generic scope options).
Dave Syer commented
I'm OK with what we have in the prototype, as long as there is an abstraction. Still not sure I like the whole feature, but if we have to do it in 2.0, this is a reasonable approach.
Mark Fisher commented
I guess you are suggesting that post 2.0, we might be able to rely upon a refreshable Scope?
Mark Fisher commented
I have committed the core functionality. For the namespace support, I'm planning the following:
<transformer input-channel="in" output-channel="out">
<expression source="myExpressions" key="transformation.userToCity"/>
</transformer>
<expression-source id="myExpressions" location="file:///example/expressions.properties" cache-seconds="60"/>
The "source" attribute should probably be optional, since a single "expressionSource" bean would likely be a common configuration.
Mark Fisher commented
Everything is committed for this support on transformer, filter, router, splitter, and header-enricher. The 'expression' sub-element can be defined like so:
<transformer input-channel="in" output-channel="out">
<expression source="myExpressions" key="transformation.userToCity"/>
</transformer>
The "source" attribute is optional. It will default to resolving a bean named "expressionSource".
We don't have namespace support for the "expressionSource" at this point, but it's simple to create as a bean. In fact the one implementation that is available out-of-the-box is exactly like a "messageSource" definition in Spring MVC, e.g.:
<bean id="expressionSource" class="org.springframework.integration.expression.ReloadableResourceBundleExpressionSource">
<property name="basename" value="/some/path/expressions"/>
</bean>
Any implementation of the ExpressionSource interface can be referenced.
Mark Fisher opened INT-1382 and commented
Currently, we support "expression" attributes on all of the primary component types (e.g. transformer, filter, router, splitter, ...).
Those expression values are passed in the XML attribute at configuration time:
Today, we do support externalization of the expression value by using yet another expression, or more commonly a property-placeholder:
Even with the externalization however, the actual Expression instance is created at initial startup only.
Meanwhile, with Groovy support, we have the ability to change the backing script at runtime. We should provide the same option for SpEL expressions (with a configurable cache + refresh time setting). To do this, we should probably just add support for an inner "expression" sub-element that would look similar to using an inner bean in place of a "ref" attribute, but in this case, it would be an alternative to using an "expression" attribute. For example:
The problem with the above example is that location would likely end up being duplicated throughout the configuration. A referenced Resource instance would be better, and in that case the Resource instance itself should have the refresh-check-delay (since it would apply at the level of Resource-loading). Perhaps something like this would be better:
2 votes, 2 watchers