我有一個解決方案的工作。這不是最好的解決方案,但它確實工作得非常好。
我們所做的是創建一個非常簡單的ActivationSpecWrapper類擴展IBM com.ibm.mq.connector.inbound.ActivationSpecImpl類。這個包裝類有一個公共set/get屬性(asJNDI)。目的是如果類要通過JNDI上下文讀取App服務器中定義的Properties類,該類包含激活MDB時要分配的所有屬性。
首先,創建新的ActivationSpecWrapper class。你可以把它放在你選擇的任何包中。
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);
}
}
}
要實現你只需要修改META-INF/ra.xml中文件內wmq.jmsra.rar文件中的類。將ActivationSpecImpl類的一次更改更改爲您的類。這將是您的新傳入連接工廠的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只允許在那裏有兩個屬性。
此外,如果你使用的是GlassFish,甲骨文確實拙劣的東西對於那些需要資源適配器MDB類,因爲在GlassFish @MessageDriven註釋承擔JMS的應用容器默認的資源適配器(OpenMQ)。這意味着供應商特定ActivationSpecImpl不起作用,因此直到通過glassfish-ejb-jar.xml切換資源適配器之後,才通過註釋支持IMB的主機/端口和其他激活配置屬性的自定義參數。
的JBoss允許@ResourceAdapter標註更改的資源適配器,但Glassfish的只允許這個通過與GlassFish ejb-jar.xml中文件。當使用這個時,你只需要用三個激活配置屬性(destinationType)註釋你的MDB。您將放置在您的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中,以定義e 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的連接細節,而不是開發人員。
你有沒有想過這個?我遇到了同樣的問題。我沒有得到任何錯誤,但它只是沒有收到任何消息。我甚至把所有的連接信息都放到了管理對象的屬性中。 – Armand
@Armand你好。不,這個任務被取消了。有可能我會回來後到這個工作 – asu