私はうまくいく解決策を持っています。これは最善の解決策ではありませんが、非常にうまく機能します。
ここで行ったことは、非常に単純なActivationSpecWrapperクラスを作成して、IBM com.ibm.mq.connector.inbound.ActivationSpecImplクラスを拡張することです。このラッパー クラスには、1 つのパブリック set/get プロパティ ( asJNDI ) があります。クラスが JNDI コンテキストを介して、MDB のアクティブ化で割り当てられるすべてのプロパティを含むアプリ サーバーで定義された Properties クラスを読み取ることである場合の目的。
最初に、新しいActivationSpecWrapperクラスを作成します。これを任意のパッケージに入れることができます。
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.InitialContext;
import com.ibm.mq.connector.inbound.ActivationSpecImpl;
public class ActivationSpecWrapper extends ActivationSpecImpl
{
private static final long serialVersionUID = -529716553593856979L;
private static final String sourceClass = ActivationSpecWrapper.class.getName();
private static final Logger log = Logger.getLogger(sourceClass);
private String asJNDI = null;
public void setAsJNDI(String asJNDI)
{
log.config("asJNDI = " + asJNDI);
this.asJNDI = asJNDI;
try
{
final InitialContext ctx = new InitialContext();
final Properties properties = (Properties) ctx.lookup(asJNDI);
for (final Object key : properties.keySet())
{
try
{
final String value = properties.getProperty((String) key);
final Object field = getSetter((String) key);
if (field != null)
{
if (field instanceof Field)
{
log.fine("Setting " + key + " via Field " + (String) key + " = " + value);
((Field) field).set(this, value);
}
else
{
log.fine("Setting " + key + " via Method " + (String) key + " = " + value);
((Method) field).invoke(this, value);
}
log.config(key + " = " + value);
}
else
{
log.warning("Invalid ActivationSpec Field: " + key);
}
}
catch (final NoSuchFieldException e)
{
log.throwing(sourceClass, "setAsJNDI", e);
}
}
}
catch (final Exception e)
{
log.log(Level.SEVERE, "Error looking up " + asJNDI, e);
return;
}
}
public String getAsJNDI()
{
return asJNDI;
}
private static Object getField(String fieldName) throws NoSuchFieldException
{
return ActivationSpecWrapper.class.getField(fieldName);
}
private static Object getSetter(String fieldName) throws NoSuchFieldException
{
try
{
final StringBuilder sb = new StringBuilder(fieldName.length() + 3).append("set").append(fieldName);
sb.setCharAt(3, Character.toUpperCase(sb.charAt(3)));
return ActivationSpecWrapper.class.getMethod(sb.toString(), String.class);
}
catch (final NoSuchMethodException e)
{
return getField(fieldName);
}
}
}
クラスを実装するには、 wmq.jmsra.rarファイル内のMETA-INF/ra.xmlファイルを変更するだけです。ActivationSpecImpl クラスの 1 つのオカレンスを自分のクラスに変更します。これは、それが使用する新しい受信接続ファクトリのActivationSpecWrapperクラスになります。これで、ラッパー クラスはアプリ サーバーを参照して、使用するプロパティを取得できます。
私は次のようにこれを行います:
: jar -xvf wmq.jmsra.rar META-INF/ra.xml
: perl -pi -e 's/com\.ibm\.mq\.connector\.inbound\.ActivationSpecImpl/your.new.package.ActivatonSpecWrapper/g' META-INF/ra.xml
: jar -uvf wmq.jmsra.rar META-INF/ra.xml
META-INF/ra.xml を変更する前は、次のようになります。
<activationspec>
<activationspec-class>
com.ibm.mq.connector.inbound.ActivationSpecImpl
</activationspec-class>
<required-config-property>
<config-property-name>destination</config-property-name>
</required-config-property>
<required-config-property>
<config-property-name>destinationType</config-property-name>
</required-config-property>
</activationspec>
変更後、META-INF/ra.xmlは次のようになります。
<activationspec>
<activationspec-class>
your.new.package.ActivatonSpecWrapper
</activationspec-class>
<required-config-property>
<config-property-name>destination</config-property-name>
</required-config-property>
<required-config-property>
<config-property-name>destinationType</config-property-name>
</required-config-property>
</activationspec>
ここで、新しいパッケージを RAR ファイルに追加する必要があります。標準のディレクトリ構造にする必要があります。このような:
: jar -uvf wmq.jmsra.rar your/new/package/ActivationSpecWrapper.class
この問題は、IBM がホスト/ポート/キュー マネージャー/チャネル (など) を管理オブジェクトではなくアクティベーション スペックに配置したことに起因します。これは MDB キューの接続ファクトリであるため、管理オブジェクトに属します。IBM はそこで 2 つのプロパティーのみを許可します。
また、グラスフィッシュを使用している場合、グラスフィッシュの@MessageDrivenアノテーションは JMS 用のアプリ コンテナーのデフォルトのリソース アダプター ( OpenMQ ) を想定しているため、オラクルはリソース アダプターを必要とする MDB クラスに対して実際に失敗しました。これは、ベンダー固有のActivationSpecImplが機能しないことを意味します。したがって、リソース アダプターがglassfish-ejb-jar.xmlを介して切り替えられるまで、ホスト/ポートおよびその他のアクティベーション構成プロパティの IMB のカスタム パラメーターは、アノテーションを介してサポートされません。
JBoss では@ResourceAdapterアノテーションを使用してリソース アダプタを変更できますが、Glassfish では Glassfish -ejb-jar.xmlファイルを介してのみこれを許可します。これを使用する場合、MDB に 3 つのアクティベーション構成プロパティ ( destinationType )で注釈を付けるだけで済みます。JNDI 公開プロパティに配置するその他すべて。
glassfish-ejb-jar.xmlは次のようになります。
<?xml version="1.0" encoding="UTF-8"?>
<glassfish-ejb-jar>
<enterprise-beans >
<unique-id>1</unique-id>
<ejb>
<ejb-name>MyMDB</ejb-name>
<mdb-resource-adapter>
<resource-adapter-mid>wmq.jmsra</resource-adapter-mid>
<activation-config>
<activation-config-property>
<activation-config-property-name>asJNDI</activation-config-property-name>
<activation-config-property-value>mq/InboundMessages</activation-config-property-value>
</activation-config-property>
</activation-config>
</mdb-resource-adapter>
</ejb>
</enterprise-beans>
</glassfish-ejb-jar>
MDB @MessageDrivenアノテーションは次のようになります。
@MessageDriven(activationConfig =
{
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "jms/InboundMessage_queue"),
@ActivationConfigProperty(propertyName = "useJNDI", propertyValue = "true") })
public class MyMDB implement MessageListener
{
public void onMessage(Message message)
{
// message handler code goes here...
}
}
これを機能させるための最後のステップは、mq/InboundMessagesプロパティを JDNI に追加して、MQ リスナー リソースのファクトリ プロパティを定義することです。domain.xmlファイルでの定義方法は次のとおりです。
<custom-resource res-type="java.util.Properties" jndi-name="mq/InboundMessages" factory-class="org.glassfish.resources.custom.factory.PropertiesFactory">
<property name="hostName" value="mqserver"></property>
<property name="port" value="1422"></property>
<property name="queueManager" value="MQMNGR"></property>
<property name="channel" value="MQMNGR.SM.S1"></property>
<property name="transportType" value="CLIENT"></property>
</custom-resource>
これが役立つことを願っています。これは最も簡単な解決策ではありませんが、十分に単純であり、いったん確立されると移植性が非常に高くなり、開発者の代わりにアプリケーション サーバー管理者が MQ への接続の詳細を管理できるようになります。