いくつかのコンテキストでは、jsr 準拠の実装を使用して、Spring バッチで JMS リーダーとライターを実行しています。Spring バッチが提供する JMSReader クラスと JMS ライター クラスを使用していますが、それらを独自のリーダーとライターでラップしています。JSR アプローチを使用しているため、一般的なアプリケーション コンテキストは利用できません。クラスは、ジョブ仕様または jsr 仕様に従って batch.xml を介して初期化されます。
私が遭遇した問題は、アクティブな mq の接続ファクトリを作成し、それを spring の JMSTemplate クラスのターゲット ファクトリとして設定する JMS リーダーおよび/または jms ライターを定義すると、スタンドアロンのバッチ アプリケーションがあることです。処理が正しくシャットダウンされません。IBM MQ の接続ファクトリーを使用する代替手段は正常に機能します。
私が行ったいくつかのコードを提供させてください。
これは、接続ファクトリーを作成する場所です。アプリが終了したときに、生きたままになっているスレッドを終了させるために行った変更のコメント行がいくつかあります。
private ConnectionFactory openAMQ() throws IllegalArgumentException{
ActiveMQConnectionFactory targetConnectionFactory = new ActiveMQConnectionFactory();
if(protocol == null){
throw new IllegalArgumentException("Active MQ protocol can not be empty");
}
AMQProtocols proto = AMQProtocols.valueOf(protocol.toUpperCase());
StringBuilder sb = new StringBuilder();
sb.append(proto.getProtocol()).append("://").append(this.host).append(":").append(this.port);
if(amqParams != null && amqParams.trim().length() > 0){
sb.append("?").append(amqParams);
}
targetConnectionFactory.setBrokerURL(sb.toString());
//targetConnectionFactory.setAlwaysSessionAsync(false);
//targetConnectionFactory.setUseAsyncSend(false);
return targetConnectionFactory;
}
ここで JMSTemplate オブジェクトを作成します
protected JmsTemplate getJMSTemplate(ConnectionFactory targetConnectionFactory){
CachingConnectionFactory ccf = new CachingConnectionFactory();
ccf.setTargetConnectionFactory(targetConnectionFactory);
JmsTemplate template = new JmsTemplate(ccf);
template.setDefaultDestinationName(jmsDefaultDestinationName);
template.setReceiveTimeout(Long.parseLong(jmsReceiveTimeoutValue));
template.setSessionTransacted(Boolean.parseBoolean(jmsSessionTransacted));
//template.setMessageConverter(messageConverter);
return template;
}
最後に、JMSReader の open メソッドを示します。ライターはほぼ同じです。
public void open(Serializable checkpoint) throws Exception {
//First we need to get our broker specific connection factory
ConnectionFactory targetConnectionFactory = getTargetConnectionFactory();
this.template = getJMSTemplate(targetConnectionFactory);
reader = new JmsItemReader();
reader.setItemType(Class.forName(jmsItemTypeFullyQualifiedName));
reader.setJmsTemplate(template);
}
私が見ているスレッドは、接続といくつかの非アクティブ監視スレッドに関連しているようです。これらがそのまま存続することで、スタンドアロン アプリケーションがシャットダウンするのを防ぎます。
接続ファクトリまたはjmsテンプレートを構成してこれが発生しないようにする方法、またはリーダーが完了したらそれを管理して適切にシャットダウンする方法を知っている人はいますか?