2013-04-14 202 views
1

我是MDB和EE的新成員。請告訴我,我錯了。 我的應用程序必須與Websphere MQ進行交互(等待隊列中的消息,執行某些操作並進行回覆)。 我正在使用NetBeans 7.3,GlassFish 3.1,Websphere MQ 6.2,保留適配器wmq.jmsra.rar。交互必須不是jms格式,只有Web MQ性質。 我正在部署適配器並創建Connecton池和管理對象。 domain.xml中Mdb Glasswish Websphere MQ

<connector-connection-pool description="" name="cpMqAdapter" resource-adapter-name="wmq.jmsra" connection-definition-name="javax.jms.QueueConnectionFactory" transaction-support="LocalTransaction"> 
    <property name="port" value="1414"></property> 
    <property name="CCSID" value="866"></property> 
    <property name="hostName" value="192.168.0.11"></property> 
    <property name="queueManager" value="QM"></property> 
    <property name="channel" value="SrvConn"></property> 
    <property description="CLIENT - mq on other computer" name="transportType" value="CLIENT"></property> 
</connector-connection-pool> 


<admin-object-resource enabled="false" res-adapter="wmq.jmsra" res-type="javax.jms.Queue" description="" jndi-name="wmqJmsAOR" class-name="com.ibm.mq.connector.outbound.MQQueueProxy"> 
    <property name="priority" value="APP"></property> 
    <property name="failIfQuiesce" value="true"></property> 
    <property name="baseQueueManagerName" value="QM"></property> 
    <property name="CCSID" value="1208"></property> 
    <property name="persistence" value="APP"></property> 
    <property name="encoding" value="NATIVE"></property> 
    <property name="baseQueueName" value="TEST"></property> 
    <property name="targetClient" value="MQ"></property> 
    <property name="expiry" value="APP"></property> 
</admin-object-resource> 

' 在NetBeans我是創造EE項目和消息驅動bean。我是GETT這個代碼「

@MessageDriven(mappedName = "wmqJmsAOR", activationConfig = { 
    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto- 
    acknowledge"), 
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") 

}) 
public class NewMessage implements MessageListener { 
public NewMessage() { 
    super(); 
    System.out.println("I created"); 
} 

@Override 
public void onMessage(Message message) { 

    System.out.println("I'm getting message"); 

} 
` 

請告訴我爲什麼這個MDB不listenig隊列(我把測試消息在WebSphere MQ控制檯)。可能是我必須在配置中寫入一些東西(現在項目爲默認的NetBeans創建)。

Alexei

+0

你有沒有想過這個?我遇到了同樣的問題。我沒有得到任何錯誤,但它只是沒有收到任何消息。我甚至把所有的連接信息都放到了管理對象的屬性中。 – Armand

+0

@Armand你好。不,這個任務被取消了。有可能我會回來後到這個工作 – asu

回答

1

我有一個解決方案的工作。這不是最好的解決方案,但它確實工作得非常好。

我們所做的是創建一個非常簡單的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的連接細節,而不是開發人員。

+0

你好!謝謝你阿爾芒。一年後,我又回到了這項工作。你的回答非常有幫助。我創建glassfish-ejb-jar.xml並將屬性設置爲MQQueueManger連接,將 wmq.jmsra設置爲它正在工作。但是這個解決方案並不愛因爲描述符中包含的所有參數。你能告訴我們更多關於Wrapper的版本和你的案例中描述符的內容。 – asu

+0

值得注意的是,IBM不支持JMS ResourceAdaptor中的事務。實現對XA事務的支持非常簡單。只需添加*** com.ibm.mqetclient。jar ***文件添加到RAR文件,並且很容易XA Transactions現在被MDB支持。另外,我使用MQ7完成了所有這些工作,但它也適用於MQ6。 – Armand

+0

非常感謝您提供如此詳細的回覆 – asu