On 12/14/06, RNobrega <[EMAIL PROTECTED]> wrote:
gnodet wrote:
>
>
2) files from an external ftp site are fetched at regular intervals,
some processing applied, and then uploaded to the mainframe. The
interval, user id, password, directory on the server(s), etc,
should be re-configurable by the end-user with minimal or no
intervention of developers or administrators. Here we had to come
up with our own way of doing it, as it was not obvious whether
servicemix offered support for it, out of the box. See my other
mail about our issues with the ftp component; this mail is about
the configuration bit
So, this is what we came up with (not saying we're too proud about it,
but it's done to the best of my ability). Let's say the cron
expression has to be changed. Originally, it sits in the xbean.xml
file:
<beans xmlns:quartz="http://servicemix.apache.org/quartz/1.0"
xmlns:foo="http://foo.org/foo">
<quartz:endpoint service="foo:scheduler" endpoint="endpoint"
targetService="foo:quartzFilter">
<quartz:trigger>
<quartz:cron cronExpression="0 0 * * * ?" />
</quartz:trigger>
</quartz:endpoint>
</beans>
Now imagine six months after this is in production, it's realised that
one hour is too long, and thirty minutes is the way to go. User wants
to change it, but nobody wants to redeploy the whole thing just to add
three bytes to a file. So, we came up with a configuration service,
that sits on the bus and accepts the following message:
<cfg>
<service>
<namespaceURI>http://foo.org/foo</namespaceURI>
<localPart>scheduler</localPart>
</service>
<endpoint>endpoint</endpoint>
<pre>getTrigger</pre>
<field>cronExpression</field>
<value>0 0/30 * * * ?</value>
</cfg>
The configuration endpoint receives this message, (desperately) asks
the container to give it a reference to the object (we're using
reflection because the object is in another classloader), invokes
whatever methods are in the <pre> element, and then calls the setter
specified in <field>, with argument <value>. It also saves this
request on a table, and replays all requests if the container
restarts. Couldn't be more messy, couldn't be more ugly, but
works. Please tell me this is wrong and there's a much cleaner way to
do it.
What about retrieving the value directly from the database when the endpoint
is started and default to a predefined value if nothing is found in
the database ?
I think it should easily doable using spring.
Something like:
<beans xmlns:quartz="http://servicemix.apache.org/quartz/1.0"
xmlns:foo="http://foo.org/foo">
<quartz:endpoint service="foo:scheduler" endpoint="endpoint"
targetService="foo:quartzFilter">
<quartz:trigger>
<quartz:cron cronExpression="#cronExpression" />
</quartz:trigger>
</quartz:endpoint>
<bean id="cronExpression" class="com.foo.DataRetriever">
<property name="service" value="foo:scheduler" />
<property name="endpoint" value="endpoint" />
<property name="key" value="cronExpression" />
<property name="defaultValue" value="0 0/30 * * * ?" />
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource" ... />
</beans>
Where com.foo.DataRetriever is a spring FactoryBean which would
load the value from the database and default to the given defaultValue
if not found.
Of course the drawback is that you have to know which value in the xbean.xml
can change and design the configuration around them.
A better way would be to use a BeanFactoryPostProcessor like the
PropertyPlaceholderConfigurer, but one which would look the actual value
from the database.
<beans xmlns:quartz="http://servicemix.apache.org/quartz/1.0"
xmlns:foo="http://foo.org/foo">
<quartz:endpoint service="foo:scheduler" endpoint="endpoint"
targetService="foo:quartzFilter">
<quartz:trigger>
<quartz:cron cronExpression="0 0/30 * * * ?" />
</quartz:trigger>
</quartz:endpoint>
<bean class="com.foo.DataBasePostProcessor">
<property name="service" value="foo:scheduler" />
<property name="endpoint" value="endpoint" />
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource" ... />
</beans>
This surely could be refined, but what about the idea ?
Btw, given what you do, I think the EndpointListener would be better
for you, if you keep your current solution.
BTW, before you ask, "quartzFilter" is an eip-filter configured like
this:
<eip:message-filter service="foo:quartzFilter"
endpoint="endpoint">
<eip:target>
<eip:exchange-target service="foo:process"/>
</eip:target>
<eip:filter>
<shared:xpath-persistent-predicate
xpath="concat(string(/timer/fullname), '::',
string(/timer/fireTime))"
dataSource="#dataSource"/>
</eip:filter>
</eip:message-filter>
and xpath-persistent-predicate is the one I was referring to, and is at
the root of the SM-774 issue
...
/**
* @org.apache.xbean.XBean element="xpath-persistent-predicate"
*/
public class XPathPersistentPredicate extends JAXPStringXPathExpression
implements Predicate {
private static final Log log =
LogFactory.getLog(XPathPersistentPredicate.class);
public XPathPersistentPredicate() {
}
public XPathPersistentPredicate(String xpath) throws Exception {
super(xpath);
}
public boolean matches(MessageExchange exchange) {
try {
NormalizedMessage in = MessageUtil.copyIn(exchange);
String match = (String) evaluate(exchange, in);
if (doneTable.containsKey(match))
return false;
doneTable.save(match);
return true;
} catch (Exception e) {
log.warn("Could not evaluate xpath expression", e);
return false;
}
}
DataSource dataSource = null;
DBTable doneTable;
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
doneTable = new DBTable();
...
}
}
As I said in another thread, I think a dup remover could be a good
fit for a new EIP pattern. You would still need an expression to
find a unique key for an exchange, but it would be more clean imho.
We did it this way to achieve a clustered quartz (couldn't figure out
a better way to do it)
What kind of problems did you had ? I haven't tried to cluster quartz,
but I don't see why it would not be possible.
I also have some comments on the ftp process, but will do this on a
separate thread
Thanks for yor valuable feedback
--
View this message in context:
http://www.nabble.com/listeners-in-container-and-MessageExchange-tf2815007s12049.html#a7869290
Sent from the ServiceMix - User mailing list archive at Nabble.com.
--
Cheers,
Guillaume Nodet