Search code examples
javajakarta-eewebsphereibm-mqmessage-driven-bean

Changing Activation Config of Topic reading MDB at deploy time


I feel this should be easy. Just RTM and go. But I can't find the info I need.

Q: Can I change the value of an @ActivationConfigProperty at deploy time without having to write any XML?


More detail

I have an MDB which is using the @MessageDriven annotation. Within this are a number of @ActivationConfigProperty annotations configuring it.

@MessageDriven(mappedName = "jms/TestJeremyTopic ", activationConfig = {
        @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
        @ActivationConfigProperty(propertyName = "subscriptionDurability", propertyValue = "Durable"),
        @ActivationConfigProperty(propertyName = "clientId", propertyValue = "TopicReaderBeanClientId"),
        @ActivationConfigProperty(propertyName = "subscriptionName", propertyValue = "TopicReaderBeanSubscriptionName")
})
public class TopicReaderBean implements MessageListener { // ...

I need to deploy this MDB multiple times, referring to a different topic each time.

At deploy time (WebSphere 7 ND) I am able to configure a distinct TopicListenerPort (WebSphere's way of mapping to different topics) for each EAR. However when I try to start a second instance it fails with the error:

WMSG0019E: Unable to start MDB Listener TopicReaderBean, JMSDestination jms/MMiSInLonTopic : com.ibm.msg.client.jms.DetailedIllegalStateException: JMSWMQ0026: Failed to subscribe to topic 'MMIS_LON_IN' using MQSUB. There may have been a problem creating the subscription due to it being used by another message consumer. Make sure any message consumers using this subscription are closed before trying to create a new subscription under the same name. Please see the linked exception for more information. Caused by: com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2429' ('MQRC_SUBSCRIPTION_IN_USE').

When I look to MQ Explorer I can see the subscription name is JMS:GGWKNNG5:gmm_poc_06:TopicReaderBeanSubscriptionName This is a composition of "JMS", QueueManager name, Topic Connection Factory ID, and ActivationConfigProperty "subscriptionName". The second connection fails because of a clash on this subscription name. I need to distinguish the subscription names used by distinct MDB instances.

Whilst I could create a new Topic Connection Factory for each bean, it would be a lot of work and doesn't make much sense.

What does make sense is to have a different subscription name per bean. However this property is baked into the annotation and I can't see anywhere in WebSphere that would allow me to override it.

So, can I override this property without having to write an XML deployment descriptor? And if I do need to write some XML, how do I override the property therein?


Solution

  • In lieu of any deploy-time solution I've written an ejb-jar.xml config that I can modify at build time. It reads thus:

    <?xml version="1.0"?>
     <ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
          version="3.1">
        <enterprise-beans>
    
            <message-driven id="MySpecialMDB">
                <display-name>MySpecialMDB</display-name>
                <ejb-name>TopicReaderBean</ejb-name>
                <ejb-class>my.TopicReaderBean</ejb-class>
                <transaction-type>Container</transaction-type>
                <message-destination-type>javax.jms.Topic</message-destination-type>
                <activation-config>
                    <activation-config-property>
                        <activation-config-property-name>destinationType</activation-config-property-name>
                        <activation-config-property-value>javax.jms.Topic</activation-config-property-value>
                    </activation-config-property>
                    <activation-config-property>
                        <activation-config-property-name>subscriptionDurability</activation-config-property-name>
                        <activation-config-property-value>Durable</activation-config-property-value>
                    </activation-config-property>
                    <activation-config-property>
                        <activation-config-property-name>subscriptionName</activation-config-property-name>
                        <activation-config-property-value>${subscriptionName}</activation-config-property-value>
                    </activation-config-property>
                </activation-config>
            </message-driven>
    
        </enterprise-beans>
    </ejb-jar>