/**
*
*/
package org.diirt.support.jms;
import static org.diirt.datasource.ExpressionLanguage.channel;
import static org.diirt.util.time.TimeDuration.ofHertz;
import static org.diirt.vtype.ValueFactory.alarmNone;
import static org.diirt.vtype.ValueFactory.newVString;
import static org.diirt.vtype.ValueFactory.timeNow;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.diirt.datasource.PV;
import org.diirt.datasource.PVManager;
import org.diirt.datasource.PVReader;
import org.diirt.datasource.PVReaderEvent;
import org.diirt.datasource.PVReaderListener;
import org.diirt.datasource.PVWriterEvent;
import org.diirt.datasource.PVWriterListener;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* @author Kunal Shroff
*
*/
public class JMSDatasourceIT {
private static final Logger log = Logger.getLogger(JMSDatasourceIT.class.getName());
private static final String BROKER_URL = "tcp://localhost:61616?jms.prefetchPolicy.all=1000";
private static final String topic = "test_topic";
private static Connection connection;
private static Session session;
@BeforeClass
public static void initialize() {
// Create a ConnectionFactory
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
// Create a Connection
try {
connection = connectionFactory.createConnection();
connection.start();
// Create a Session
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@AfterClass
public static void cleanup() {
try {
session.close();
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
/**
* A basic test to send a jms message and check if it was received by the
* diirt jms datasource
*/
@Test
public void topicSubscribe() {
final JMSDatasource jms = new JMSDatasourceProvider().createInstance();
PVManager.setDefaultDataSource(jms);
final PVReader<Object> pv = PVManager.read(channel(topic)).from(jms).readListener(new PVReaderListener<Object>() {
@Override
public void pvChanged(PVReaderEvent<Object> event) {
log.info("reading jms message: " + event.getPvReader().getValue());
}
}).maxRate(ofHertz(100));
try {
writeTextMessage(topic, "topicSubscribe", 10);
} catch (Exception e) {
}
// pv.close();
}
/**
* A basic test to write to a jms topic using the diirt jms datasource
*/
@Test
public void topicPublish(){
final JMSDatasource jms = new JMSDatasourceProvider().createInstance();
PVManager.setDefaultDataSource(jms);
final PV<Object, Object> pv = PVManager.readAndWrite(channel(topic))
.writeListener(new PVWriterListener<Object>() {
@Override
public void pvChanged(PVWriterEvent<Object> event) {
log.info("writing completed: " + event.isWriteSucceeded());
}
})
.readListener(new PVReaderListener<Object>() {
@Override
public void pvChanged(PVReaderEvent<Object> event) {
if(event.isValueChanged()){
log.info("reading written message: " + event.getPvReader().getValue());
}
}
}).asynchWriteAndMaxReadRate(ofHertz(100));
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
pv.write(newVString("Hello", alarmNone(), timeNow()));
}
pv.close();
}
/**
*
*/
@Test
public void topicMultipleSubscribers(){
final JMSDatasource jms = new JMSDatasourceProvider().createInstance();
PVManager.setDefaultDataSource(jms);
List<String> eventList1 = new ArrayList<String>();
List<String> eventList2 = new ArrayList<String>();
final PVReader<?> pv1 = PVManager.read(channel(topic)).readListener((event) -> {
eventList1.add(event.getPvReader().getValue().toString());
log.info("pv1 event" + event.getPvReader().getValue());
}).maxRate(ofHertz(100));
final PVReader<?> pv2 = PVManager.read(channel(topic)).readListener((event) -> {
eventList2.add(event.getPvReader().getValue().toString());
log.info("pv2 event" + event.getPvReader().getValue());
}).maxRate(ofHertz(100));
try {
writeTextMessage(topic, "topicMultipleSubscribers", 10);
} catch (Exception e) {
} finally {
pv1.close();
pv2.close();
}
Assert.assertSame("events reveived by both pvs were not the same", eventList1, eventList2);
}
/**
* Parse the name to support defining the read and write types / the
* sytax is as follows
*
* jms://topic_name<readType, writeType>{filter}
**/
@Test
public void topicSubscribersWithFilter(){
final JMSDatasource jms = new JMSDatasourceProvider().createInstance();
PVManager.setDefaultDataSource(jms);
List<String> eventList1 = new ArrayList<String>();
final PVReader<?> pv1 = PVManager.read(channel(topic + "{property = 'ID1'}")).readListener((event) -> {
if (event.isValueChanged()) {
eventList1.add(event.getPvReader().getValue().toString());
log.info("pv1 event" + event.getPvReader().getValue());
}
}).maxRate(ofHertz(100));
try {
writeTextMessageWithProperty(topic, "ID1", "ID1", 10);
writeTextMessageWithProperty(topic, "ID2", "ID2", 10);
} catch (Exception e) {
} finally {
pv1.close();
}
Assert.assertSame("events reveived by both pvs were not the same", eventList1.size(), 10);
}
/**
* A helper method used by tests to write plain text message/s to a topic
*
* @param topic The topic to write the message to
* @param count The number of times the message should be written
* @throws JMSException
* @throws InterruptedException
*/
private static void writeTextMessage(String topic, String textID, int count) throws JMSException, InterruptedException {
writeTextMessageWithProperty(topic, null, textID, count);
}
/**
* A helper method used by tests to write plain text message/s with a property to a topic
*
* @param topic The topic to write the message to
* @param count The number of times the message should be written
* @throws JMSException
* @throws InterruptedException
*/
private static void writeTextMessageWithProperty(String topic, String Property, String textID, int count) throws JMSException, InterruptedException {
// Create the destination (Topic or Queue)
Destination destination = session.createTopic(topic);
// Create a MessageProducer from the Session to the Topic or
// Queue
MessageProducer producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// Create a messages
//String text = "SimpleTopicProducer - From: " + Thread.currentThread().getName() + " : " + textID;
String text = textID;
TextMessage message = session.createTextMessage(text);
if (Property != null) {
message.setStringProperty("property", Property);
}
for (int i = 0; i < count; i++) {
Thread.sleep(100);
// Tell the producer to send the message
log.fine("Sent message: " + message.hashCode() + " : " + Thread.currentThread().getName());
producer.send(message);
}
}
}