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 |