JMS通信の手順を全部自分で書かなければいけない うげぇ。特に必要なければ JavaEE 使おう
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany</groupId>
<artifactId>JMSExam</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.glassfish.main.appclient</groupId>
<artifactId>gf-client</artifactId>
<version>4.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.mq</groupId>
<artifactId>imqjmsra</artifactId>
<version>5.1</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
package com.mycompany.jmsexam;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class Sender {
public static void main(String[] args) {
try {
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"com.sun.enterprise.naming.SerialInitContextFactory");
props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");//your server ip
props.setProperty("org.omg.CORBA.ORBInitialPort", "3700"); //default is 3700
Context jndiContext = new InitialContext(props);
// (1)
ConnectionFactory factory = (ConnectionFactory) jndiContext.lookup("jms/myQueueFactory");
// (2)
Queue queue = (Queue) jndiContext.lookup("jms/myQueue");
// (3)
try (Connection connection = factory.createConnection()) {
// (4)
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// (5)
TextMessage message = session.createTextMessage();
message.setText("Hello JMS World");
// (6)
MessageProducer producer = session.createProducer(queue);
// (7)
producer.send(message);
connection.close();
}
} catch (NamingException | JMSException ex) {
Logger.getLogger(Sender.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
package com.mycompany.jmsexam;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class Receiver {
public static void main(String[] args) {
try {
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"com.sun.enterprise.naming.SerialInitContextFactory");
props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");//your server ip
props.setProperty("org.omg.CORBA.ORBInitialPort", "3700"); //default is 3700
Context jndiContext = new InitialContext(props);
// (1)
ConnectionFactory factory = (ConnectionFactory) jndiContext.lookup("jms/myQueueFactory");
// (2)
Queue queue = (Queue) jndiContext.lookup("jms/myQueue");
// (3)
try (Connection connection = factory.createConnection()) {
// (4)
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// (5)
MessageConsumer consumer = session.createConsumer(queue);
// (6)
connection.start();
TextMessage message = (TextMessage) consumer.receive(5000L);\
connection.close();
System.out.println(message);
}
} catch (NamingException | JMSException ex) {
Logger.getLogger(Receiver.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
9 29, 2015 1:44:01 午前 org.hibernate.validator.internal.util.Version <clinit> INFO: HV000001: Hibernate Validator 5.0.0.Final 9 29, 2015 1:44:02 午前 com.sun.messaging.jms.ra.ResourceAdapter start 情報: MQJMSRA_RA1101: GlassFish MQ JMS Resource Adapter: Version: 5.1 (Build 9-b) Compile: July 29 2014 1229 9 29, 2015 1:44:02 午前 com.sun.messaging.jms.ra.ResourceAdapter start 情報: MQJMSRA_RA1101: GlassFish MQ JMS Resource Adapter starting: broker is REMOTE, connection mode is TCP 9 29, 2015 1:44:02 午前 com.sun.messaging.jms.ra.ResourceAdapter start 情報: MQJMSRA_RA1101: GlassFish MQ JMS Resource Adapter Started:REMOTE
9 29, 2015 1:45:00 午前 org.hibernate.validator.internal.util.Version <clinit> INFO: HV000001: Hibernate Validator 5.0.0.Final 9 29, 2015 1:45:00 午前 com.sun.messaging.jms.ra.ResourceAdapter start 情報: MQJMSRA_RA1101: GlassFish MQ JMS Resource Adapter: Version: 5.1 (Build 9-b) Compile: July 29 2014 1229 9 29, 2015 1:45:00 午前 com.sun.messaging.jms.ra.ResourceAdapter start 情報: MQJMSRA_RA1101: GlassFish MQ JMS Resource Adapter starting: broker is REMOTE, connection mode is TCP 9 29, 2015 1:45:00 午前 com.sun.messaging.jms.ra.ResourceAdapter start 情報: MQJMSRA_RA1101: GlassFish MQ JMS Resource Adapter Started:REMOTE Text: Hello JMS World Class: com.sun.messaging.jmq.jmsclient.TextMessageImpl getJMSMessageID(): ID:9-192.168.10.10(c6:c5:8b:11:f:95)-54343-1443458642434 getJMSTimestamp(): 1443458642434 getJMSCorrelationID(): null JMSReplyTo: null JMSDestination: myQueue getJMSDeliveryMode(): PERSISTENT getJMSRedelivered(): false getJMSType(): null getJMSExpiration(): 0 getJMSDeliveryTime(): 0 getJMSPriority(): 4 Properties: {JMSXDeliveryCount=1}
Sender (Session Bean) は Queue を Inject するだけ やったー
Receiver (Message Driven Bean) では、ユーザプログラムがメッセージを待つ必要がない。JavaEE コンテナが、メッセージが届いたら MDB#onMessage() を呼んでくれる。
package com.mycompany.websocketexam;
import javax.annotation.Resource;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.jms.JMSContext;
import javax.jms.Queue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@LocalBean
@Stateless
public class QueueSenderSessionBean {
private static final Logger logger
= LoggerFactory.getLogger(QueueSenderSessionBean.class);
@Resource(mappedName = "jms/myQueue")
private Queue myQueue;
@Inject
private JMSContext jmsContext;
public void sendMessage(String message) {
logger.info("Enqueu Message to JMS");
jmsContext.createProducer().send(myQueue, message);
}
}
package com.mycompany.websocketexam;
import javax.ejb.MessageDriven;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.enterprise.event.Event;
import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@MessageDriven(mappedName = "jms/myQueue")
public class WebSocketMDB implements MessageListener {
private static final Logger logger
= LoggerFactory.getLogger(WebSocketMDB.class);
@Inject
@WSJMSMessage
private Event<Message> jmsEvent;
@Override
public void onMessage(Message msg) {
logger.info("Fire CDI Event");
jmsEvent.fire(msg);
}
}
// (1) ConnectionFactory factory = (ConnectionFactory) jndiContext.lookup("jms/myQueueFactory"); // (2) Queue queue = (Queue) jndiContext.lookup("jms/myQueue");
// (1) ConnectionFactory factory = (ConnectionFactory) jndiContext.lookup("jms/myTopicFactory"); // (2) Topic topic = (Topic) jndiContext.lookup("jms/myTopic");
session.createDurableSubscriber(topic, "SubscriptionID001");JMS 側では、ID でメッセージを管理する。次に立ち上げるときにも同じ ID を指定すると、落ちていた間に溜まっていたメッセージが配信される
Text: Hello JMS World Class: com.sun.messaging.jmq.jmsclient.TextMessageImpl getJMSMessageID(): ID:9-192.168.10.10(c6:c5:8b:11:f:95)-54343-1443458642434 getJMSTimestamp(): 1443458642434 getJMSCorrelationID(): null JMSReplyTo: null JMSDestination: myQueue getJMSDeliveryMode(): PERSISTENT getJMSRedelivered(): false getJMSType(): null getJMSExpiration(): 0 getJMSDeliveryTime(): 0 getJMSPriority(): 4 Properties: {JMSXDeliveryCount=1}
JMSDestination | 宛先 |
JMSDeliveryMode? | PERSISTENT:MQにメッセージの送達を保証させる / NON_PRESENT:メッセージの送達保障は不要 |
JMSExpiration | 有効期限 ms |
JMSPriority | 0(最低)〜9(最高) |
Message#setIntPriority("GENRE", 8);任意の属性を指定できる
session.createConsumer(topic, "GENRE IN(1,2,6,8)")演算子は SQL92 のサブセット NOT,AND,OR,=,>,>=,<=,<,<>,+,-,*,/,NOT,BETWEEN,IN,LIKE,IS,NULL
@MessageDriven(mappedName = "jms/myTopic", activationconfig = { @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), @ActivationConfigProperty(propertyName = "...(略)... }) public class TopicMDB (
propertyName | propertyValue |
destinationType | TOPIC / QUEUE |
destination | 宛先名(任意) cf.JMSDestination |
messageSelector | フィルタリング式 |
acknowledgeMode | Auto-acknowledge(自動的に送達確認) / Client-acknowledge(クライアント側プログラムで明示的に送達確認) / Dups_ok_acknowledge(送達確認不要=重複許可) |
subscriptionDurability | DURABLE/NON_DURABLE cf 永続サブスクライバ |
subscriptionName | 永続サブスクライバのID |