I have been trying to learn ActiveMQ and JMS. When I compile the following code I get the above exception. Although, I have attached the right jar files for JMS and ActiveMQ. Eclipse asks me to add a cast to the ConnectionFactory object when I try to create a connection (i.e. connectionFactory.createConnection()) using the ConnectionFactory object. The codes that I see everywhere on the internet are the same as I have written.
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
public class JMSProducer {
public static void main(String[] args) {
try {
// Create a ConnectionFactory
ConnectionFactory connectionFactory=new ActiveMQConnectionFactory("admin", "admin",
ActiveMQConnection.DEFAULT_BROKER_URL);
// Create a Connection
Connection connection = connectionFactory.createConnection();
//Error seen in above line
connection.start();
// Create a Session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Create the destination
Destination destination = session.createQueue("testQ");
// Create a MessageProducer from the Session to the Queue
MessageProducer producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// Create a messages
TextMessage message = session.createTextMessage("Helloworld");
producer.send(message);
session.close();
connection.close();
System.out.println("Message sent");
}
catch (Exception e) {
System.out.println(e);
e.printStackTrace();
}
}
}
Sholud have done ActiveMQConnection connection = connectionFactory.createConnection(); instead of Connection connection = connectionFactory.createConnection();. Now the code is running fine.
Related
I have a ActiveMQ consumer script running in Java where I am calling consumer.receive() in a while(true) loop.
I need to implement timeout for each message processed (eg: if a message process goes beyond 15 seconds I have to receive the next one).
I have given the client acknowledge mode for ACK.
Please look at the consumeMessage method where I have implemented the consume.
Desired outcome:
After 15 seconds the first message needs to be discarded (i.e. it should not invoke acknowledge()). The next message needs to be processed instead.
//package consumer;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
public class ActivmqConsumer implements ExceptionListener {
ActiveMQConnectionFactory connectionFactory = null;
Connection connection = null;
Session session = null;
public ActivmqConsumer() throws Exception{
String USERNAME = "admin";
String PASSWORD = "admin";
this.connectionFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, "tcp://192.168.56.101:61616?jms.prefetchPolicy.all=1");
// Create a Connection
this.connection = connectionFactory.createConnection();
connection.start();
connection.setExceptionListener(this);
// Create a Session
this.session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
}
public void consumeMessage(String destinationName, EventProcesser eventprocess){
Destination destination = null;
MessageConsumer consumer = null;
try{
// Create the destination (Topic or Queue)
destination = session.createQueue(destinationName);
// Create a MessageConsumer from the Session to the Topic or Queue
consumer = session.createConsumer(destination);
// Wait for a message
while(true){
Message message = consumer.receive(2);
if(message==null){
continue;
}
else if(message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
String text = textMessage.getText();
System.out.println("Received: " + text);
eventprocess.processEvent(text);
message.acknowledge();
} else{
System.out.println("Received: " + message);
}
}
}catch(Exception ex){
ex.printStackTrace();
}finally{
try{
consumer.close();
}catch(Exception ex){
ex.printStackTrace();
}
}
}
}
There is no "max message processing time" or equivalent feature in ActiveMQ. You'll need to monitor the processing yourself. Maybe take a look at this question/answer for ideas on how to do that. An alternative would be to use a JTA transaction manager and consume the message in a transaction with a timeout of 15 seconds. Using an MDB in a Java EE container would be a simple way to get the transaction timeout functionality.
Im trying to develop a "Message Driven Bean" to handle all the local ActiveMQ messages, but it's the first time that i try to do something like this.
The most part of the material that i found explain how to write a MDB using JBOSS server, in this case there's a xml file with some queue information, but in all wildfly tutorials there's no mention to any kind of configuration like that.
I have the following scenario:
A simple java project like message producer
An ActiveMQ instance running local
An EJB project deployed into Wildfly 10
My producer project is able to send messages to ActiveMQ queue, this part its working,but my EJB project just have a single class called TestMDBHandle with #MessageDriven annotation. Is this enough to receive my queue messages? Because the MDB isnt working, i imagine must be a kind of configuration or property in EJB to specify the host of the message-broker.
My message producer:
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class MessageSender {
public static void main(String args[]) throws NamingException, JMSException {
MessageSender sender = new MessageSender();
sender.sender();
}
public void sender() throws NamingException, JMSException {
InitialContext jndi = null;
Session session = null;
Connection connection = null;
try {
jndi = new InitialContext();
ConnectionFactory factory = (ConnectionFactory)jndi.lookup("connectionFactory");
connection = factory.createConnection();
connection.start();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = (Destination)jndi.lookup("MyQueue");
MessageProducer producer = session.createProducer(destination);
TextMessage mensagem = session.createTextMessage("Eu enviei uma mensagem!");
producer.send(mensagem);
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
connection.close();
jndi.close();
}
}
}
My jms properties located inside my producer project
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url=tcp://localhost:61616
connectionFactoryNames = connectionFactory, queueConnectionFactory, topicConnectionFactory
queue.MyQueue=jms/myqueue
Finally, my ejb project have this single class, without any kind of property file or xml.
package br.com.jms.mdb;
import javax.annotation.Resource;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.EJB;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
#MessageDriven(name = "meuHandler", activationConfig = {
#ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
#ActivationConfigProperty(propertyName = "destination", propertyValue = "jms/myqueue") })
public class Teste implements MessageListener {
#Resource
private MessageDrivenContext mdctx;
public Teste() {
}
#Override
public void onMessage(Message message) {
TextMessage objectMessage = null;
try {
objectMessage = (TextMessage)message;
System.out.println("Achei a mensagem : " + objectMessage.getText().toString());
}catch(JMSException e) {
e.printStackTrace();
}
}
}
Maybe you can provide a little more information such as the xml file with the queue information and the annotation properties of the MDB? Because it sounds you are heading in the right direction. The two main things:
You have to specify the exact queue that the MDB is listening to, for example through the properties of the #MessageDriven annotation (such as "name", "mappedName", "activationConfig"). And of course override the onMessage() method to process the messages.
You also have to make sure that this specific queue is available as a resource for your application. You have to provide jms configuration for this, which also defines the resource type (Queue or Topic). From your question I can't tell which of these steps you have (partly) completed.
New to JMS
Requirement - connect to Message queue . try to send some file/message to test the connection.
Getting Error- ERROR yarn.ApplicationMaster: User class threw exception: java.io.IOException: Failed to bind to server socket: tcp://dbusmq-sd00007.svc.db.com:1427 due to: java.net.BindException: Cannot assign requested address (Bind failed)
java.io.IOException: Failed to bind to server socket: tcp://dbusmq-sd00007.svc.db.com:1427 due to: java.net.BindException: Cannot assign requested address (Bind failed)
its firewall/SSL issue or something wrong with code ?
package practice;
import java.net.URI;
import java.net.URISyntaxException;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.broker.BrokerFactory;
import org.apache.activemq.broker.BrokerService;
public class jmsQueue {
public static void main(String[] args) throws URISyntaxException, Exception {
BrokerService broker = BrokerFactory.createBroker(new URI(
"broker:(tcp://dbusmq-sd00007.svc.db.com:1427)"));
broker.start();
Connection connection = null;
try {
// Producer
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
"tcp://dbusmq-sd00007.svc.db.com:1427");
connection = connectionFactory.createConnection();
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue("QM.SU00007");
String payload = "Testing helloworld";
Message msg = session.createTextMessage(payload);
MessageProducer producer = session.createProducer(queue);
System.out.println("Sending text '" + payload + "'");
producer.send(msg);
// Consumer
/* MessageConsumer consumer = session.createConsumer(queue);
connection.start();
TextMessage textMsg = (TextMessage) consumer.receive();
System.out.println(textMsg);
System.out.println("Received: " + textMsg.getText());*/
session.close();
} finally {
if (connection != null) {
connection.close();
}
broker.stop();
}
}
}
I'm currently working on a JMS project and I have created 2 keys and 2 certificates as well as a TrustStorage, mytruststore which I created through Qpid's UI.
In my jndi.properties file I have the following code:
//Set the InitialContextFactory class to use
java.naming.factory.initial = org.apache.qpid.jms.jndi.JmsInitialContextFactory
//Define the required ConnectionFactory instances
//connectionfactory.<JNDI-lookup-name> = <URI>
connectionfactory.myFactoryLookup = amqp://localhost:5672
connectionfactory.producerConnectionFactory = amqp://admin:admin#?brokerlist='tcp://localhost:5672?encryption_remote_trust_store='$certificates%255c/mytruststore''
connectionfactory.consumer1ConnectionFactory = amqp://admin:admin#?brokerlist='tcp://localhost:5672?encryption_key_store='C:\OpenSSL-Win64\bin\mytruststorage.jks'&encryption_key_store_password='thanos''
connectionfactory.consumer2ConnectionFactory = amqp://admin:admin#?brokerlist='tcp://localhost:5672?encryption_key_store='C:\OpenSSL-Win64\bin\mytruststorage.jks'&encryption_key_store_password='thanos''
//Configure the necessary Queue and Topic objects
//queue.<JNDI-lookup-name> = <queue-name>
//topic.<JNDI-lookup-name> = <topic-name>
queue.myQueueLookup = queue
topic.myTopicLookup = topic
queue.myTestQueue = queue
In my EncryptionExample.java class I have the following code:
package org.apache.qpid.jms.example;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class EncryptionExample {
public EncryptionExample() {
}
public static void main(String[] args) throws Exception {
EncryptionExample encryptionExampleApp = new EncryptionExample();
encryptionExampleApp.runProducerExample();
encryptionExampleApp.runReceiverExample();
}
private void runProducerExample() throws Exception
{
Connection connection = createConnection("producerConnectionFactory");
try {
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
Destination destination = createDesination("myTestQueue");
MessageProducer messageProducer = session.createProducer(destination);
TextMessage message = session.createTextMessage("Hello world!");
// ============== Enable encryption for this message ==============
message.setBooleanProperty("x-qpid-encrypt", true);
// ============== Configure recipients for encryption ==============
message.setStringProperty("x-qpid-encrypt-recipients", "CN=client1, OU=Qpid, O=Apache, C=US");
messageProducer.send(message);
session.commit();
}
finally {
connection.close();
}
}
private void runReceiverExample() throws Exception
{
Connection connection = createConnection("consumer1ConnectionFactory");
try {
connection.start();
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
Destination destination = createDesination("myTestQueue");
MessageConsumer messageConsumer = session.createConsumer(destination);
Message message = messageConsumer.receive();
if (message instanceof TextMessage) {
// application logic
System.out.println(((TextMessage) message).getText());
} else if (message instanceof BytesMessage) {
// handle potential decryption failure
System.out.println("Potential decryption problem. Application not in list of intended recipients?");
}
session.commit();
}
finally {
connection.close();
}
}
///////////////////////////////////////
// The following is boilerplate code //
///////////////////////////////////////
private Connection createConnection(final String connectionFactoryName) throws JMSException, IOException, NamingException
{
try (InputStream resourceAsStream = getResourceAsStream("jndi.properties")) {
Properties properties = new Properties();
properties.load(resourceAsStream);
Context context = new InitialContext(properties);
ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup(connectionFactoryName);
final Connection connection = connectionFactory.createConnection();
context.close();
return connection;
}
}
private InputStream getResourceAsStream(String string) {
// TODO Auto-generated method stub
return null;
}
private Destination createDesination(String desinationJndiName) throws IOException, NamingException
{
try (InputStream resourceAsStream = this.getClass().getResourceAsStream("example.properties")) {
Properties properties = new Properties();
properties.load(resourceAsStream);
Context context = new InitialContext(properties);
Destination destination = (Destination) context.lookup(desinationJndiName);
context.close();
return destination;
}
}
}
When I'm trying to build it I get the following exceptions.
Exception in thread "main" java.lang.NullPointerException
at java.util.Properties$LineReader.readLine(Unknown Source)
at java.util.Properties.load0(Unknown Source)
at java.util.Properties.load(Unknown Source)
at
org.apache.qpid.jms.example.EncryptionExample.createConnection(EncryptionExample.java:106)
at
org.apache.qpid.jms.example.EncryptionExample.runProducerExample(EncryptionExample.java:54)
at org.apache.qpid.jms.example.EncryptionExample.main(EncryptionExample.java:48)
I assume that something's wrong with the following code in jndi.properties file:
connectionfactory.myFactoryLookup = amqp://localhost:5672
connectionfactory.producerConnectionFactory = amqp://admin:admin#?brokerlist='tcp://localhost:5672?encryption_remote_trust_store='$certificates%255c/mytruststore''
connectionfactory.consumer1ConnectionFactory = amqp://admin:admin#?brokerlist='tcp://localhost:5672?encryption_key_store='C:\OpenSSL-Win64\bin\mytruststorage.jks'&encryption_key_store_password='thanos''
connectionfactory.consumer2ConnectionFactory = amqp://admin:admin#?brokerlist='tcp://localhost:5672?encryption_key_store='C:\OpenSSL-Win64\bin\mytruststorage.jks'&encryption_key_store_password='thanos''
This is my solution Explorer:
This first and biggest problem you have is that you are trying to use connection URIs and client features from a client other than the one you have configured you project to use. You seem to be using Qpid JMS which is the new AMQP 1.0 client developed at the Qpid project. This client uses a different URI syntax that the previous AMQP 0.x clients and you will get exception from the connection factory when passing in these invalid URIs.
The other problem you will have (which was called out in the comments on your post) is that there is not message encryption feature in the AMQP 1.0 JMS client so that would be your next problem once you got the URIs correctly defined.
The documentation for the newer AMQP 1.0 JMS client is here.
You cannot use // for comments in Properties files. Use # or ! instead.
See: https://docs.oracle.com/javase/8/docs/api/java/util/Properties.html#load-java.io.Reader-
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Producer {
private static String url = ActiveMQConnection.DEFAULT_BROKER_URL;
private static String QUEUE_NAME = "kesaven";
private static final Logger logger = LogManager.getLogger(Producer.class.getName());
public static void main(String[] args) throws JMSException
{
//System.out.println(url);
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue(QUEUE_NAME);
MessageProducer producer = session.createProducer(destination);
//TextMessage message = session.createTextMessage("My first log message to queue");
logger.info("My first log message to queue");
//producer.send(message);
//System.out.println("Sentage '" + message.getText() + "'");
connection.close();
}
}
i am trying to log the message to a queue using log4j2 and activemq. i am using log4j2.3 and for queue i am using activemq 5.9.0 . i am able to see exception message in queue not the message i sent. Following is the error message in queue
javax.jms.JMSException: Failed to build body from content.
Serializable class not available to broker. Reason:
java.lang.ClassNotFoundException:
org.apache.logging.log4j.core.impl.Log4jLogEvent$LogEventProxy
What appender are you using to write the data to ActiveMQ? I would suggest that instead of using Java serialization to write the log event that you serialize it to JSON, use the RFC5424 layout or some other format that doesn't require the Log4j2 jars when reading the events.
Since the Log4event is put on the queue , can you check if you have the log4j2 jars available on the broker end.
I added the following jars from log4j2 to the activeMQ server /lib directory to make this work
log4j-api-2.6.1,
log4j-core-2.6.1
I logged Strings only, if I tried to log ObjectMessages, the queue entry would not open in the Queue manager view, the JSP failed.