In my JavaEE application, I read messages from and IBM MQ queue in the following way:
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public class MyMessageHandler implements MessageListener {
#Resource
private MessageDrivenContext context;
#Override
public void onMessage(Message message) {
try {
processMessage(message);
}
catch (Exception e) {
context.setRollbackOnly();
}
}
The application is deployed on Jboss EAP 6.4, and the wmq.jms.rar adapter ( Implementation-Version: 7.1.0.0-k000-L111005) is used.
Here is the activation config from ejb-jar.xml:
<message-driven>
<display-name>MyMessageHandler</display-name>
<ejb-name>MyMessageHandler</ejb-name>
<ejb-class>org.example.MyMessageHandler</ejb-class>
<transaction-type>Container</transaction-type>
<activation-config>
<activation-config-property>
<activation-config-property-name>hostName</activation-config-property-name>
<activation-config-property-value>${somejbossproperty}</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>port</activation-config-property-name>
<activation-config-property-value>${somejbossproperty}</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>channel</activation-config-property-name>
<activation-config-property-value>${somejbossproperty}</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>queueManager</activation-config-property-name>
<activation-config-property-value>${somejbossproperty}</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>transportType</activation-config-property-name>
<activation-config-property-value>${somejbossproperty}</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>username</activation-config-property-name>
<activation-config-property-value>${somejbossproperty}</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>password</activation-config-property-name>
<activation-config-property-value>${somejbossproperty}</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>destinationType</activation-config-property-name>
<activation-config-property-value>javax.jms.Queue</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>destination</activation-config-property-name>
<activation-config-property-value>${somejbossproperty}</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>acknowledgeMode</activation-config-property-name>
<activation-config-property-value>auto-acknowledge</activation-config-property-value>
</activation-config-property>
</activation-config>
</message-driven>
When an exception is thrown, the transaction is rolled back, and the message is put into the IBM MQ backout queue using the IBM MQ backout mechanism. However, I notice a growth in the number of connections, and they are not released.
This is how I monitor the number of connections on the IBM MQ server:
echo "display conn(*) all" | runmqsc <queue manager name> | grep <the IP of the Jboss server>| wc -l
Why can it happen?
It seems that the issue was due to the version of the wmq.jms.rar-adapter. When we upgraded to a newer version (7.5.0.9-p750-009-180830), the connection leak stopped.
Related
I'm trying to use activeMq as a broker for JMS with open liberty. I managed to get messages on the queue but my activation spec is never triggering. I'm reading the following in the logs.
[25/07/20 18:13:51:857 CEST] 00000330 com.ibm.ws.ejbcontainer.runtime.AbstractEJBRuntime I CNTR0180I: The FailedKalenderUpdateProcessor message-driven bean in the typedagkalender-backend.jar module of the typedagkalender-ear application is bound to the jms/typedagkalender/kalenderupdates/dlqueueAS activation specification.
[25/07/20 18:13:51:857 CEST] 00000330 com.ibm.ws.jca.cm.ConnectorService I J2CA8050I: An authentication alias should be used instead of defining a user name and password on jms/typedagkalender/kalenderupdates/dlqueueAS.
[25/07/20 18:13:51:858 CEST] 00000330 SystemOut O 2020-07-25 18:13:51,858 [utor-thread-692] INFO ActiveMQEndpointWorker - Starting
[25/07/20 18:13:51:858 CEST] 00000330 com.ibm.ws.jca.service.EndpointActivationService I J2CA8801I: The message endpoint for activation specification jms/typedagkalender/kalenderupdates/dlqueueAS and message driven bean application typedagkalender-ear#typedagkalender-backend.jar#FailedKalenderUpdateProcessor is activated.
[25/07/20 18:13:51:858 CEST] 00000330 com.ibm.ws.ejbcontainer.runtime.AbstractEJBRuntime I CNTR0180I: The KalenderUpdateProcessor message-driven bean in the typedagkalender-backend.jar module of the typedagkalender-ear application is bound to the jms/typedagkalender/kalenderupdates/queueAS activation specification.
[25/07/20 18:13:51:858 CEST] 000002cb SystemOut O 2020-07-25 18:13:51,858 [utor-thread-591] INFO ActiveMQEndpointWorker - Establishing connection to broker [tcp://localhost:61616]
[25/07/20 18:13:51:858 CEST] 00000330 com.ibm.ws.jca.cm.ConnectorService I J2CA8050I: An authentication alias should be used instead of defining a user name and password on jms/typedagkalender/kalenderupdates/queueAS.
[25/07/20 18:13:51:860 CEST] 00000330 SystemOut O 2020-07-25 18:13:51,859 [utor-thread-692] INFO ActiveMQEndpointWorker - Starting
[25/07/20 18:13:51:860 CEST] 00000330 com.ibm.ws.jca.service.EndpointActivationService I J2CA8801I: The message endpoint for activation specification jms/typedagkalender/kalenderupdates/queueAS and message driven bean application typedagkalender-ear#typedagkalender-backend.jar#KalenderUpdateProcessor is activated.
[25/07/20 18:13:51:860 CEST] 0000032b SystemOut O 2020-07-25 18:13:51,860 [utor-thread-687] INFO ActiveMQEndpointWorker - Establishing connection to broker [tcp://localhost:61616]
[25/07/20 18:13:51:870 CEST] 000002cb SystemOut O 2020-07-25 18:13:51,870 [utor-thread-591] INFO ActiveMQEndpointWorker - Successfully established connection to broker [tcp://localhost:61616]
[25/07/20 18:13:51:871 CEST] 0000032b SystemOut O 2020-07-25 18:13:51,870 [utor-thread-687] INFO ActiveMQEndpointWorker - Successfully established connection to broker [tcp://localhost:61616]
This is my server.xml configuration the jms part
<?xml version="1.0" encoding="UTF-8"?>
<server>
<!-- JMS CONFIGURATION -->
<resourceAdapter id="ActiveMQResourceAdapter" location="${server.config.dir}/resources/lib/resource-adapter/activemq-rar-5.16.0.rar">
<properties.activemq ServerUrl="tcp://localhost:61616" />
</resourceAdapter>
<messagingEngine>
<queue id="Typedagkalender_destination" />
<queue id="_SYSTEM.Exception.Destination" />
</messagingEngine>
<jmsQueueConnectionFactory jndiName="jms/typedagkalender/kalenderupdates/queueCF" connectionManagerRef="ConMgr">
<properties.ActiveMQResourceAdapter />
</jmsQueueConnectionFactory> -->
<connectionManager id="ConMgr" maxPoolSize="${jms.ConMgr.maxPoolSize}" />
<jmsQueue id="jms/typedagkalender/kalenderupdates/queue" jndiName="jms/typedagkalender/kalenderupdates/queue">
<properties.ActiveMQResourceAdapter PhysicalName="Typedagkalender_destination" />
</jmsQueue>
<jmsQueue id="jms/typedagkalender/kalenderupdates/dlqueue" jndiName="jms/typedagkalender/kalenderupdates/dlqueue">
<properties.ActiveMQResourceAdapter PhysicalName="_SYSTEM.Exception.Destination" />
</jmsQueue>
<jmsActivationSpec id="jms/typedagkalender/kalenderupdates/queueAS">
<properties.ActiveMQResourceAdapter destinationType="javax.jms.Queue" destination="jms/typedagkalender/kalenderupdates/queue" />
</jmsActivationSpec>
<jmsActivationSpec id="jms/typedagkalender/kalenderupdates/dlqueueAS">
<properties.ActiveMQResourceAdapter destinationType="javax.jms.Queue" destination="jms/typedagkalender/kalenderupdates/dlqueue" />
</jmsActivationSpec>
</server>
This is my bean that should activate
#TransactionAttribute(NOT_SUPPORTED)
#MessageDriven(mappedName = "jms/typedagkalender/kalenderupdates/queue", activationConfig = {
#ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
#ActivationConfigProperty(propertyName = "destination", propertyValue = "jms/typedagkalender/kalenderupdates/queue")
})
public class KalenderUpdateProcessor implements MessageListener {
private static final Logger LOGGER = LoggerFactory.getLogger(KalenderUpdateProcessor.class);
#Inject
private KalenderAbonnementService kalenderAbonnementService;
#Override
public void onMessage(Message message) {
if (!(message instanceof TextMessage)) {
LOGGER.error("Er is alleen ondersteuning voor TextMessages");
return;
}
Auditor.setTimestamp(now());
TextMessage textMessage = (TextMessage) message;
try {
LOGGER.debug("Textmessage gekregen voor KalenderJaargangVersieUpdate {}", textMessage.getText());
handle(textMessage.getText());
} catch (JMSException e) {
LOGGER.error("Fout tijdens behandelen van message {}: {}", textMessage, e);
throw new KalenderUpdateNotificationException("Fout tijdens behandelen van message " + textMessage, e);
} finally {
Auditor.destroy();
}
}
}
This setup works if I use the internal JMS implementation that open liberty provides. But since that would only work for a single node and I need a persistent central broker, I need to get it to work with activeMQ. What am I missing in this configuration ?
I found the solution, seems I can't use a different physicalname for the queue or it won't work. Well solution is a big word here maybe, maybe I have to say I didn't find a way to make it work with a different physicalname but did by using the same queue name.
<?xml version="1.0" encoding="UTF-8"?>
<server>
<!-- JMS CONFIGURATION -->
<resourceAdapter id="ActiveMQResourceAdapter" location="${server.config.dir}/resources/lib/resource-adapter/activemq-rar-5.16.0.rar">
<properties.activemq ServerUrl="tcp://localhost:61616" />
</resourceAdapter>
<messagingEngine>
<queue id="jms/typedagkalender/kalenderupdates/queue" />
<queue id="jms/typedagkalender/kalenderupdates/dlqueue" />
</messagingEngine>
<jmsQueueConnectionFactory jndiName="jms/typedagkalender/kalenderupdates/queueCF" connectionManagerRef="ConMgr">
<properties.ActiveMQResourceAdapter />
</jmsQueueConnectionFactory> -->
<connectionManager id="ConMgr" maxPoolSize="${jms.ConMgr.maxPoolSize}" />
<jmsQueue id="jms/typedagkalender/kalenderupdates/queue" jndiName="jms/typedagkalender/kalenderupdates/queue">
<properties.ActiveMQResourceAdapter PhysicalName="jms/typedagkalender/kalenderupdates/queue" />
</jmsQueue>
<jmsQueue id="jms/typedagkalender/kalenderupdates/dlqueue" jndiName="jms/typedagkalender/kalenderupdates/dlqueue">
<properties.ActiveMQResourceAdapter PhysicalName="jms/typedagkalender/kalenderupdates/dlqueue" />
</jmsQueue>
<jmsActivationSpec id="jms/typedagkalender/kalenderupdates/queueAS">
<properties.ActiveMQResourceAdapter destinationType="javax.jms.Queue" destination="jms/typedagkalender/kalenderupdates/queue" />
</jmsActivationSpec>
<jmsActivationSpec id="jms/typedagkalender/kalenderupdates/dlqueueAS">
<properties.ActiveMQResourceAdapter destinationType="javax.jms.Queue" destination="jms/typedagkalender/kalenderupdates/dlqueue" />
</jmsActivationSpec>
</server>
I am publishing JMS text message to topic and consumer is able to consumer ( MDB ) the text message. But not able to get Message Object and String property. it is null in MDB consumer side. I have defined MDB in ejb-jar.xml under META-INF folder. I am using
TomEE plus 7.0.2
JMS 2.0
IBM MQ 8
JDK 1.8
Topic
I refereed below mentioned Tomee official example. In example they used tomee.xml instead i used resource.xml and don't use web.xml
Consumer is MessageDrivenBean
Consumer is able to get Text or Object Message. But Message property is null.
http://tomee.apache.org/tomee-and-webspheremq.html
#Resource(name = "qcf")
private ConnectionFactory connectionFactory;
#Resource(name = "wmq-javax.jms.Topic")
private Topic topic;
Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(topic);
TextMessage message = session.createTextMessage();
message.setText("Test Message");
message.setObjectProperty("a","b");
message.setStringProperty("c","D");
connection.start();
producer.send(message);
session.close();
connection.close();
Consumer
<ejb-jar id="ejb-jar_ID" version="3.1"
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">
<display-name>SampleTransactionMDB</display-name>
<enterprise-beans>
<message-driven>
<display-name>SampleTransactionMDB</display-name>
<ejb-name>SampleTransactionMDB</ejb-name>
<ejb-class>com.example.SampleTransactionMDB</ejb-class>
<transaction-type>Container</transaction-type>
<activation-config>
<activation-config-property>
<activation-config-property-name>destinationType</activation-config-property-name>
<activation-config-property-value>javax.jms.Queue</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>destination</activation-config-property-name>
<activation-config-property-value>openejb:Resource/projectname/topicname</activation-config-property-value>
</activation-config-property>
</activation-config>
<activation-config-property>
<activation-config-property-name>useJNDI</activation-config-property-name>
<activation-config-property-value>true</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>HostName</activation-config-property-name>
<activation-config-property-value>x.x.x.x</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>Port</activation-config-property-name>
<activation-config-property-value>123</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>QueueManager</activation-config-property-name>
<activation-config-property-value>xxxxx</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>Channel</activation-config-property-name>
<activation-config-property-value>xxxx</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>TransportType</activation-config-property-name>
<activation-config-property-value>CLIENT</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>subscriptionName</activation-config-property-name>
<activation-config-property-value>xxxxxx</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>sharedSubscription</activation-config-property-name>
<activation-config-property-value>true</activation-config-property-value>
</activation-config-property>
</message-driven>
</enterprise-beans>
<assembly-descriptor>
</assembly-descriptor>
</ejb-jar>
Guide me why message property is null in MDB consumer.
I found the root cause of the problem. it is my mistake. TopicProxy's targetClient should be JMS. I wrongly configured as MQ. so I was able to get message but not property.
After changing targetClient value to JMS. I am able to get message and property
http://tomee.apache.org/tomee-and-webspheremq.html
MessageProducer producer = session.createProducer(queue);
If you are publishing a message to topic then why are you using a variable named 'queue'? A topic string generally looks like 'test/ABC/one' (no quotes).
Secondly, why didn't you post the code for the consumer? Update your original posting to include the consumer code.
In Jboss 5.x, JMS model- queue (Point to point) used to be implemented as follows (MDB class and ejb-jar.xml)
MDB
package receiver;
import javax.jms.JMSException;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import javax.jms.Message;
public class WildFlyJmsQueueReceiveLocal implements MessageListener {
public void onMessage(Message msg) {
try {
System.out.println("[WildFlyJmsQueueReceiveLocal][onMessage]There are three kinds of basic JMS connection-factory that depends on the type of connectors that is used.");
String msgText;
if (msg instanceof TextMessage) {
msgText = ((TextMessage)msg).getText();
} else {
msgText = msg.toString();
}
if (msgText.equalsIgnoreCase("quit")) {
synchronized(this) {
this.notifyAll(); // Notify main thread to quit
}
}
} catch (JMSException | InterruptedException jmse) {
jmse.printStackTrace();
}
}
}
ejb-jar.xml
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="3.0" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">
<display-name>MDB</display-name>
<enterprise-beans>
<message-driven>
<display-name>MDB1</display-name>
<ejb-name>MDB1</ejb-name>
<ejb-class>receiver.WildFlyJmsQueueReceiveLocal</ejb-class>
<transaction-type>Container</transaction-type>
<activation-config>
<activation-config-property>
<activation-config-property-name>destinationType</activation-config-property-name>
<activation-config-property-value>javax.jms.Queue</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>destination</activation-config-property-name>
<activation-config-property-value>jms/queue/TestQ</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>maxSession</activation-config-property-name>
<activation-config-property-value>2</activation-config-property-value>
</activation-config-property>
</activation-config>
</message-driven>
</enterprise-beans>
</ejb-jar>
Now i am migrating from jboss 5.x to wildfly10. In wildfly 10, JMS feature has been implemented using 'Apache ActiveMQ Artemis'.
So In wildfly 10, first i configured queue 'jms/queue/TestQ' and tried to deploy same code (which was used in jboss 5.x), It was running successfully. I thought i have to create 'ActiveMQConnectionFactory' object and do the further stuff, but it was not like that. The JMS API which i had used in Jboss 5.x,was working fine in wildfly10.
JMS sender and receiver is deployed on same wildfly instance. Am i implementing correctly the JMS queue feature? Is it the right way to do in wildfly10. If not please direct me to the link/documentation.
My Que is
Java code which i had used in Jboss 5.x (for JMS-Queue implementation) will work in Wildfly-10 without any change?
For Jboss 5.x go to JMS links :
https://docs.jboss.org/jbossas/guides/j2eeguide/r2/en/html/ch6.chapt.html
I'm using Spring Boot and ActiveMQ. I want to send and receive messages from a topic. This is working well. My code looks like this:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {
JmsSpike.TestListener1.class,
JmsSpike.TestListener2.class,
JmsSpike.Config.class
})
#TestPropertySource(properties = {
"spring.activemq.broker-url: tcp://localhost:61616",
"spring.activemq.password: admin",
"spring.activemq.user: admin",
"spring.jms.pub-sub-domain: true", // queue vs. topic
})
#EnableJms
#EnableAutoConfiguration
public class JmsSpike {
#Autowired
private JmsTemplate jmsTemplate;
#Test
public void sendMessage() throws Exception {
sendMessageInThread();
Thread.sleep(10000);
}
private void sendMessageInThread() {
new Thread() {
public void run() {
jmsTemplate.convertAndSend("asx2ras", "I'm a test");
}
}.start();
}
#TestComponent
protected static class TestListener1 {
#JmsListener(destination = "asx2ras")
public void receiveMessage(String message) {
System.out.println("****************** 1 *******************");
System.out.println("Hey 1! I got a message: " + message);
System.out.println("****************** 1 *******************");
}
}
#TestComponent
protected static class TestListener2 {
#JmsListener(destination = "asx2ras")
public void receiveMessage(String message) {
throw new RuntimeException("Nope");
}
}
#Configuration
protected static class Config {
#Bean
public RedeliveryPolicy redeliveryPolicy() {
RedeliveryPolicy topicPolicy = new RedeliveryPolicy();
topicPolicy.setMaximumRedeliveries(1);
return topicPolicy;
}
#Bean
public ConnectionFactory connectionFactory(#Value("${spring.activemq.user}") final String username,
#Value("${spring.activemq.password}") final String password,
#Value("${spring.activemq.broker-url}") final String brokerUrl) {
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory(username, password, brokerUrl);
cf.setRedeliveryPolicy(redeliveryPolicy());
return cf;
}
}
}
I can send a message
I receive the message with both listeners
One listener will always work and just print some console message
The other listener will always throw an exception
I set the retry to "1", so the failing listener will be called one more time after the exception was thrown. However, after the retry, the message is not delivered to an error queue (or error topic). How can I send the message to an error queue so that I can call the failing listener again later?
Note that I only want to call the failing listener again, not all listeners on the topic. Is that possible?
EDIT
Here's my activemq.xml (just the broker tag):
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}">
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry topic=">" >
<pendingMessageLimitStrategy>
<constantPendingMessageLimitStrategy limit="1000"/>
</pendingMessageLimitStrategy>
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>
<managementContext>
<managementContext createConnector="false"/>
</managementContext>
<persistenceAdapter>
<kahaDB directory="${activemq.data}/kahadb"/>
</persistenceAdapter>
<systemUsage>
<systemUsage>
<memoryUsage>
<memoryUsage percentOfJvmHeap="70" />
</memoryUsage>
<storeUsage>
<storeUsage limit="100 gb"/>
</storeUsage>
<tempUsage>
<tempUsage limit="50 gb"/>
</tempUsage>
</systemUsage>
</systemUsage>
<transportConnectors>
<!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
<shutdownHooks>
<bean xmlns="http://www.springframework.org/schema/beans" class="org.apache.activemq.hooks.SpringContextHook" />
</shutdownHooks>
</broker>
According to the official documentation, you can override the broker configurations on the client side:
The broker transmits the default delivery policy that he prefers to a
client connection in his BrokerInfo command packet. But the client can
override the policy settings by using the
ActiveMQConnection.getRedeliveryPolicy() method:
RedeliveryPolicy policy = connection.getRedeliveryPolicy();
policy.setInitialRedeliveryDelay(500); policy.setBackOffMultiplier(2);
policy.setUseExponentialBackOff(true);
policy.setMaximumRedeliveries(2);
So, the way you have configured the redelivery policy seems OK.
The only issue that I see is when you create a new instance of RedeliveryPolicy and set only a single field topicPolicy.setMaximumRedeliveries(1); all other fields that are primitives will be assigned default values. You should probably set the maximum redeliveries on the existing instance of redelivery policy:
RedeliveryPolicy policy = cf.getRedeliveryPolicy();
policy.setMaximumRedeliveries(1);
Edit
Also, make sure that by using #JmsListener is not using CLIENT_ACKNOWLEDGE. According to this thread the messages will not get redelivered when CLIENT_ACKNOWLEDGE is used.
I'm using sun-jms-adapter.rar. All my configuration works fine before starting to use authentication. I also tried accessing to queue from a standalone application and stateless bean (this is used to send messages to queue), and all works fine.
My actual configuration is:
weblogic-ds.xml
<connection-factories>
<!-- SUN JMS JCA Resource adapter, use this to get transacted JMS in beans -->
<no-tx-connection-factory>
<jndi-name>CFX/ExternalConnectionFactory</jndi-name>
<xa-transaction />
<rar-name>sun-jms-adapter.rar</rar-name>
<connection-definition>javax.jms.QueueConnectionFactory</connection-definition>
<config-property name="SessionDefaultType" type="java.lang.String">javax.jms.Queue</config-property>
<config-property name="JmsProviderAdapterJNDI" type="java.lang.String">java:/DefaultJMSProvider</config-property>
<config-property name="Destination" type="java.lang.String">javax.jms.Destination</config-property>
<max-pool-size>20</max-pool-size>
<depends>jboss.messaging:service=ServerPeer</depends>
</no-tx-connection-factory>
</connection-factories>
ejb-jar.xml configuration:
<enterprise-beans>
<message-driven>
<ejb-name>QueueReceiverMDB</ejb-name>
<ejb-class>com.tests.mdb.QueueReceiverMDB</ejb-class>
<transaction-type>Bean</transaction-type>
<activation-config>
<activation-config-property>
<activation-config-property-name>destination</activation-config-property-name>
<activation-config-property-value>${weblogic.jms.queue.in}</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>destinationType</activation-config-property-name>
<activation-config-property-value>javax.jms.Queue</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>ConnectionURL</activation-config-property-name>
<activation-config-property-value>${weblogic.jms.url}</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>UserName</activation-config-property-name>
<activation-config-property-value>${weblogic.jms.username}</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>Password</activation-config-property-name>
<activation-config-property-value>${weblogic.jms.password}</activation-config-property-value>
</activation-config-property>
</activation-config>
</message-driven>
</enterprise-beans>
and finally my jboss.xml:
<message-driven>
<ejb-name>QueueReceiverMDB</ejb-name>
<destination-jndi-name>java:/CFX/ExternalConnectionFactory</destination-jndi-name>
<local-jndi-name>local/QueueReceiverMDB</local-jndi-name>
<resource-adapter-name>sun-jms-adapter.rar</resource-adapter-name>
<configuration-name>JMSJCA Message Driven Bean</configuration-name>
</message-driven>
I'm allways getting this error:
16:25:07,126 WARNING [Activation] JMSJCA-E016: [sync-QueueReceiver(jms/TestJMSQueueIn) # [t3://localhost:7001]]: message delivery initiation failed (attempt #1); will retry in 1 seconds. The error was: Access denied to resource: type=, application=TestJMSModule, destinationType=queue, resource=TestJMSQueueIn, action=receive
weblogic.jms.common.JMSSecurityException: Access denied to resource: type=, application=TestJMSModule, destinationType=queue, resource=TestJMSQueueIn, action=receive
at weblogic.jms.dispatcher.DispatcherAdapter.convertToJMSExceptionAndThrow(DispatcherAdapter.java:110)
at weblogic.jms.dispatcher.DispatcherAdapter.dispatchSync(DispatcherAdapter.java:45)
at weblogic.jms.client.JMSSession.consumerCreate(JMSSession.java:2982)
at weblogic.jms.client.JMSSession.setupConsumer(JMSSession.java:2749)
at weblogic.jms.client.JMSSession.createConsumer(JMSSession.java:2691)
at weblogic.jms.client.JMSSession.createReceiver(JMSSession.java:2596)
at weblogic.jms.client.WLSessionImpl.createReceiver(WLSessionImpl.java:991)
at com.stc.jmsjca.core.RAJMSObjectFactory.createMessageConsumer(RAJMSObjectFactory.java:620)
at com.stc.jmsjca.core.SyncDelivery$SyncWorker.init(SyncDelivery.java:502)
at com.stc.jmsjca.core.SyncDelivery.start(SyncDelivery.java:202)
at com.stc.jmsjca.core.Activation.asyncStart(Activation.java:557)
at com.stc.jmsjca.core.Activation.access$000(Activation.java:82)
at com.stc.jmsjca.core.Activation$1.run(Activation.java:351)
at java.lang.Thread.run(Thread.java:745)
Caused by: weblogic.jms.common.JMSSecurityException: Access denied to resource: type=, application=TestJMSModule, destinationType=queue, resource=TestJMSQueueIn, action=receive
at weblogic.jms.dispatcher.DispatcherAdapter.convertToJMSExceptionAndThrow(DispatcherAdapter.java:110)
at weblogic.jms.dispatcher.DispatcherAdapter.dispatchSync(DispatcherAdapter.java:45)
at weblogic.jms.frontend.FEConsumer.(FEConsumer.java:296)
at weblogic.jms.frontend.FESession$2.run(FESession.java:1076)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:363)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:146)
at weblogic.jms.frontend.FESession.consumerCreate(FESession.java:1072)
at weblogic.jms.frontend.FESession.invoke(FESession.java:3027)
at weblogic.messaging.dispatcher.Request.wrappedFiniteStateMachine(Request.java:961)
at weblogic.messaging.dispatcher.DispatcherServerRef.invoke(DispatcherServerRef.java:276)
at weblogic.messaging.dispatcher.DispatcherServerRef.handleRequest(DispatcherServerRef.java:141)
at weblogic.messaging.dispatcher.DispatcherServerRef.access$000(DispatcherServerRef.java:34)
at weblogic.messaging.dispatcher.DispatcherServerRef$2.run(DispatcherServerRef.java:111)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:256)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:221)
Caused by: weblogic.jms.common.JMSSecurityException: Access denied to resource: type=, application=TestJMSModule, destinationType=queue, resource=TestJMSQueueIn, action=receive
at weblogic.jms.dispatcher.Request.handleThrowable(Request.java:87)
at weblogic.jms.dispatcher.Request.getResult(Request.java:52)
at weblogic.messaging.dispatcher.Request.wrappedFiniteStateMachine(Request.java:1124)
at weblogic.messaging.dispatcher.DispatcherImpl.syncRequest(DispatcherImpl.java:185)
at weblogic.messaging.dispatcher.DispatcherImpl.dispatchSync(DispatcherImpl.java:220)
at weblogic.jms.dispatcher.DispatcherAdapter.dispatchSync(DispatcherAdapter.java:43)
... 13 more
Caused by: weblogic.jms.common.JMSSecurityException: Access denied to resource: type=, application=TestJMSModule, destinationType=queue, resource=TestJMSQueueIn, action=receive
at weblogic.jms.common.JMSSecurityHelper.checkPermission(JMSSecurityHelper.java:162)
at weblogic.jms.backend.BEDestinationSecurityImpl.checkReceivePermission(BEDestinationSecurityImpl.java:87)
at weblogic.jms.backend.BEConsumerImpl.init(BEConsumerImpl.java:312)
at weblogic.jms.backend.BEConsumerImpl.(BEConsumerImpl.java:268)
at weblogic.jms.backend.BEQueueImpl.createConsumer(BEQueueImpl.java:188)
at weblogic.jms.backend.BESessionImpl.createBEConsumer(BESessionImpl.java:469)
at weblogic.jms.backend.BESessionImpl.createConsumer(BESessionImpl.java:479)
at weblogic.jms.backend.BESessionImpl.invoke(BESessionImpl.java:297)
at weblogic.messaging.dispatcher.Request.wrappedFiniteStateMachine(Request.java:961)
... 16 more
Any suggestion is welcome...
I found a solution to my problem, could not be the best one, but it works.
After spent lots of time trying put this working, I checkout the source code of resource adaptor (sun-jms-adapter.rar) from here, and found a possible error. They don't put credentials in initialContext and close context after creating session. So I modify this stepts, by adding "Context.SECURITY_PRINCIPAL" and "Context.SECURITY_CREDENTIALS" to context, and leave it open. And this really works. All this in getJndiObject method in RAWLObjectFactory class.
If someone finds another way, and a best way, please share... because they are putting credentials when creating queue Connection, so may be a bug at weblogic source.
I leave the modified code:
private Object getJndiObject(UrlParser url, String name, String username, String password) throws JMSException {
if (sLog.isDebugEnabled()) {
sLog.debug("Looking up JNDI object " + name);
}
if (name == null || name.length() == 0) {
throw Exc.jmsExc(LOCALE.x("E401: The JNDI name is null"));
}
InitialContext ctx = null;
try {
if (mSpecialISORBMethod != null) {
// Works on IS only
if (mSpecialISORBMethodIsOn != null) {
Boolean isEnabled = (Boolean) mSpecialISORBMethodIsOn.invoke(null, new Object[0]);
if (!isEnabled.booleanValue()) {
throw Exc.rsrcExc(LOCALE.x("E823: CORBA-SE needs to be enabled on"
+ " this server. Please change the value of the <se-orb enabled=\"false\"/>"
+ " to <se-orb enabled=\"true\"/> in the configuration file of "
+ " the Integration Server (logicalhost/is/domains/<domain-name>"
+ "/config/domain.xml) and restart the server."));
}
}
final Properties prop = (Properties) mSpecialISORBMethod.invoke(null, new Object[0]);
prop.put(Context.URL_PKG_PREFIXES, JNDI_WEBLOGIC_PROTOCOL_PACKAGES);
ctx = new InitialContext(prop);
return ctx.lookup("corbaname:iiop:1.2#" + url.getHost() + ":" + url.getPort()
+ '#' + name);
} else {
// Will be executed on other application servers than the IS
//add username/password if not null to context
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
env.put(Context.PROVIDER_URL, "t3://" + url.getHost() + ":" + url.getPort());
if (username != null) {
env.put(Context.SECURITY_PRINCIPAL, username);
env.put(Context.SECURITY_CREDENTIALS, password);
}
ctx = new InitialContext(env);
return ctx.lookup(name);
}
} catch (Exception e) {
throw Exc.jmsExc(LOCALE.x("E821: Could not find JNDI object by name [{0}]: {1}", name, e), e);
}
//leave context open
/*finally {
safeClose(ctx);
}*/
}