http://wiki4.caucho.com/index.php?title=Resin_4_Java_EE_Java_Application_Server_JMS_Support_Tutorial&feed=atom&action=historyResin 4 Java EE Java Application Server JMS Support Tutorial - Revision history2024-03-28T11:10:18ZRevision history for this page on the wikiMediaWiki 1.18.0http://wiki4.caucho.com/index.php?title=Resin_4_Java_EE_Java_Application_Server_JMS_Support_Tutorial&diff=666&oldid=prevRick at 00:00, 16 June 20122012-06-16T00:00:00Z<p></p>
<table class='diff diff-contentalign-left'>
<col class='diff-marker' />
<col class='diff-content' />
<col class='diff-marker' />
<col class='diff-content' />
<tr valign='top'>
<td colspan='2' style="background-color: white; color:black;">← Older revision</td>
<td colspan='2' style="background-color: white; color:black;">Revision as of 00:00, 16 June 2012</td>
</tr><tr><td colspan="2" class="diff-lineno">Line 1:</td>
<td colspan="2" class="diff-lineno">Line 1:</td></tr>
<tr><td colspan="2"> </td><td class='diff-marker'>+</td><td style="background: #cfc; color:black; font-size: smaller;"><div><ins style="color: red; font-weight: bold; text-decoration: none;">{{Cookbook}}  {{Development}}</ins></div></td></tr>
<tr><td colspan="2"> </td><td class='diff-marker'>+</td><td style="background: #cfc; color:black; font-size: smaller;"><div><ins style="color: red; font-weight: bold; text-decoration: none;"></ins></div></td></tr>
<tr><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"><div>=JMS Tutorials=</div></td><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"><div>=JMS Tutorials=</div></td></tr>
<tr><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"><div>=JMS Listener with EJB message bean=</div></td><td class='diff-marker'> </td><td style="background: #eee; color:black; font-size: smaller;"><div>=JMS Listener with EJB message bean=</div></td></tr>
</table>Rickhttp://wiki4.caucho.com/index.php?title=Resin_4_Java_EE_Java_Application_Server_JMS_Support_Tutorial&diff=654&oldid=prevRick: Created page with "=JMS Tutorials= =JMS Listener with EJB message bean= <p>Introduces receiving a message using an EJB message bean.</p> ==Files in this tutorial== <table> <tr> <th..."2012-06-16T00:00:00Z<p>Created page with "=JMS Tutorials= =JMS Listener with EJB message bean= <p>Introduces receiving a message using an EJB message bean.</p> ==Files in this tutorial== <table> <tr> <th..."</p>
<p><b>New page</b></p><div>=JMS Tutorials=<br />
=JMS Listener with EJB message bean=<br />
<p>Introduces receiving a message using an EJB message bean.</p><br />
<br />
==Files in this tutorial==<br />
<table><br />
<tr><br />
<th>File</th><br />
<th>Description</th><br />
</tr><br />
<tr><br />
<td><code>WEB-INF/web.xml</code></td><br />
<td>Configures the Queue, MessageSender, MessageListener.</td><br />
</tr><br />
<tr><br />
<td><code>WEB-INF/classes/example/MyListener.java</code></td><br />
<td>The message listener.</td><br />
</tr><br />
<tr><br />
<td><code>WEB-INF/classes/example/MessageServlet.java</code></td><br />
<td>The message servlet</td><br />
</tr><br />
</table><br />
<br />
==Overview==<br />
<br />
<p>Messaging decouples a sending task from a receiving/processing task,<br />
allowing for batch processing or load balancing of tasks to another machine.<br />
The original task can respond immediately to the user without waiting for<br />
the task complete. The servlet creates a message<br />
and sends it to a queue. The servlet immediately completes and when the<br />
batch process is ready, it processes the message.</p><br />
<br />
<p>Messaging is therefore comprised of three main components:<br />
</p><br />
<br />
<ul><br />
<li>A '''''Producer''''' creates messages and sends them to<br />
a '''''Queue'''''. The Producer could be something like a Servlet.<br />
</li><br />
<li>A '''''Queue''''' stores the messages from the Produces and provides<br />
them to a Consumer when ready. The Queue is implemented by the<br />
messaging provider.<br />
</li><br />
<li>A '''''Consumer''''' processes messages as they become<br />
available in the Queue. The '''''Consumer''''' is typically a bean<br />
implementing the <code>MessageListener</code> interface.<br />
</li><br />
</ul><br />
<br />
<br />
==Producer (MessageServlet)==<br />
<br />
<p>In this example, the Producer is a Servlet which sends a simple message.<br />
To simplify the example, we'll use the <code>BlockingQueue</code> API instead<br />
of the JMS producers. The functionality is the same without the extra<br />
housekeeping of the JMS API.</p><br />
<br />
<p>The servlet uses [../../doc/resin-ioc.xtp CDI]<br />
dependency injection to get the <code>BlockingQueue</code>. The<br />
dependency injection cleans the code by decoupling it from the implementation.<br />
For example, the actual <code>BlockingQueue</code> could be facade around<br />
another JMS implementation's queue.</p><br />
<br />
====Example: MessageServlet====<br />
<pre><br />
import javax.inject.Inject;<br />
import java.util.concurrent.BlockingQueue;<br />
<br />
public class MessageServlet extends GenericServlet {<br />
@Inject BlockingQueue _sender;<br />
<br />
...<br />
String message = "sample message";<br />
_sender.put(message);<br />
}<br />
</pre><br />
<br />
<p>In this configuration, the <code>BlockingQueue</code> is a<br />
<code>java.util.concurrent.BlockingQueue</code>. It's also possible<br />
to use the full JMS <code>MessageProducer</code> which is more verbose.<br />
</p><br />
<br />
<p>The <code>put</code> method completes as soon as<br />
the message is stored in the queue. Later, when a thread is available, the<br />
Queue will send the message to the Consumer.</p><br />
<br />
<br />
==Consumer (MyListener)==<br />
<br />
<p>The Queue delivers messages to the Consumer at the consumer's rate.<br />
When the Consumer finishes processing a message the Queue will deliver the next<br />
available message.</p><br />
<br />
<p>The Consumer implements <code>javax.jms.MessageListener</code>, and<br />
will therefore be identical code in any application server. The<br />
Consumer might even be on a different server or use a different<br />
application server.</p><br />
<br />
<p>In this example, the Consumer just logs the message, but more<br />
realistic applications might use Java Persistence to store results<br />
in a database. The listener instance has full access to Resin-IoC<br />
capabilities, including dependency injection, standard aspects like<br />
@TransactionAttribute, interceptors, and WebBeans event processing.</p><br />
<br />
====Example: MyListener.java implementation====<br />
<pre><br />
package example;<br />
<br />
import java.util.logging.Logger;<br />
import java.util.logging.Level;<br />
<br />
import javax.jms.Message;<br />
import javax.jms.TextMessage;<br />
import javax.jms.MessageListener;<br />
<br />
public class MyListener implements MessageListener {<br />
private static final Logger log<br />
= Logger.getLogger(MyListener.class.getName());<br />
<br />
public void onMessage(Message message)<br />
{<br />
try {<br />
ObjectMessage objMessage = (ObjectMessage) message;<br />
<br />
log.info("received: " + objMessage.getValue());<br />
<br />
_lastMessage = textMessage.getValue();<br />
} catch (Exception e) {<br />
log.log(Level.WARNING, e.toString(), e);<br />
}<br />
}<br />
}<br />
</pre><br />
<br />
<br />
==Configuration==<br />
<br />
<p>Since Resin is an inversion of control container (IoC), it can<br />
configure the JMS resources in the standard Resin configuration file.<br />
The [../../doc/resin-ioc.xtp Resin IoC] documentation gives<br />
more information.</p><br />
<br />
<p>The configuration is responsible for three things:</p><br />
<ul><br />
<li>Configuring the Queue</li><br />
<li>Configuring the MessageListener</li><br />
</ul><br />
<br />
<p>The <code>Queue</code> is configured directly in a &lt;resin:FileQueue&gt;<br />
tag, together with any configuration setters. This example uses a<br />
local file store.</p><br />
<br />
<p>Because the listener and sender need a reference to the queue,<br />
the jms-queue stores it in the "my_queue" variable.</p><br />
<br />
====Example: Queue configuration in WEB-INF/resin-web.xml====<br />
<pre><br />
<web-app xmlns="http://caucho.com/ns/resin"<br />
xmlns:ee="urn:java:ee"<br />
xmlns:resin="urn:java:com.caucho.resin"><br />
<br />
<resin:FileQueue ee:Named="my_queue"><br />
<path>WEB-INF/db</path><br />
</resin:FileQueue><br />
<br />
</web-app><br />
</pre><br />
<br />
<p>JMS also needs a configured ConnectionFactory, so the sender<br />
and listener can create JMS connections.</p><br />
<br />
====Example: ConnectionFactory in resin-web.xml====<br />
<pre><br />
<web-app xmlns="http://caucho.com/ns/resin"<br />
xmlns:resin="urn:java:com.caucho.resin"><br />
<br />
<resin:JmsConnectionFactory/><br />
<br />
</web-app><br />
</pre><br />
<br />
<p>The MessageListener is configured as an EJB message bean.<br />
Resin's EJB support instantiates the listeners<br />
and receives messages from the queue.</p><br />
<br />
====Example: message bean configuration resin-web.xml====<br />
<pre><br />
<web-app xmlns="http://caucho.com/ns/resin"><br />
<br />
<resin:FileQueue ee:Named="my_queue"><br />
<path>WEB-INF/db</path><br />
</resin:FileQueue><br />
<br />
<ejb-message-bean class="example.MyListener"><br />
<destination>${my_queue}</destination><br />
</ejb-message-bean><br />
<br />
</web-app><br />
</pre><br />
<br />
<br />
=JMS Messaging in Quercus - Sending messages=<br />
==Files in this tutorial==<br />
<table><br />
<tr><br />
<th>File</th><br />
<th>Description</th><br />
</tr><br />
<tr><br />
<td><code>WEB-INF/resin-web.xml</code></td><br />
<td>resin-web.xml configuration</td><br />
</tr><br />
<tr><br />
<td><code>WEB-INF/classes/META-INF/beans.xml</code></td><br />
<td>Java Injection marker file to start bean scanning</td><br />
</tr><br />
<tr><br />
<td><code>send-message.php</code></td><br />
<td>PHP script sending the message.</td><br />
</tr><br />
<tr><br />
<td><code>WEB-INF/classes/example/MyListener.java</code></td><br />
<td>Java message bean listener receiving the message.</td><br />
</tr><br />
<tr><br />
<td><code>WEB-INF/classes/example/MessageStore.java</code></td><br />
<td>Singleton service bean storing the received messages.</td><br />
</tr><br />
</table><br />
<br />
<br />
==Using JMS in Quercus==<br />
<br />
<p><br />
Quercus offers a simplified messaging interface built upon JMS. This <br />
functionality makes it possible to send and receive messages using either<br />
the Resin JMS implementation or any other messaging service with a JMS<br />
implementation. Many features of JMS are designed for message-driven<br />
services which make sense in the Java world, but are not appropriate for<br />
PHP. This tutorial focuses on sending messages.<br />
</p><br />
<br />
<br />
==Sending JMS messages from a PHP script==<br />
<br />
<p><br />
In this example, the script checks a POST variable "message" and if<br />
it is set, sends the value of that variable to a JMS queue. A Message<br />
Driven Bean (MDB) receives these messages and records them. The record<br />
is displayed by a servlet.<br />
</p><br />
<br />
====Example: PHP sending script====<br />
<pre><br />
<?php<br />
<br />
if (isset($_POST["message"])) {<br />
$queue = java_bean("Queue");<br />
<br />
if (! $queue) {<br />
echo "Unable to get message queue!\n";<br />
} else {<br />
if ($queue->offer($_POST["message"]) == TRUE) {<br />
echo "Successfully sent message '" . $_POST["message"] . "'";<br />
} else {<br />
echo "Unable to send message '" . $_POST["message"] . "'";<br />
}<br />
}<br />
}<br />
<br />
?><br />
</pre><br />
<br />
<p><br />
The programming model of the Quercus JMS interface is first to<br />
get access to the queue using the <code>java_bean()</code> call.<br />
<code>java_bean</code> will look for the named bean in the<br />
resin-web.xml, in this case our queue. Since the Queue implements<br />
the <code>java.util.concurrent.BlockingQueue</code> API, the PHP script<br />
can send data to the queue directly using <code>offer()</code> and<br />
receive messages with <code>poll()</code>.<br />
</p><br />
<br />
<br />
==Configuring JMS for PHP and Java==<br />
<br />
<p><br />
JMS requires two resources: A <code>Queue</code> and a<br />
<code>ConnectionFactory</code>. Both are<br />
configured in <code>WEB-INF/resin-web.xml</code>.<br />
The <code>ConnectionFactory</code> is used to connect to all the<br />
<code>Queue</code>s and only one of them needs to be set up.</p><br />
<br />
===MemoryQueue configuration===<br />
<br />
<br />
<p><br />
The example uses the queue named <code>Queue</code>.<br />
</p><br />
<br />
====Example: Queue configuration in resin-web.xml====<br />
<pre><br />
<web-app xmlns="http://caucho.com/ns/resin"<br />
xmlns:resin="urn:java:com.caucho.resin"><br />
<br />
<jms:MemoryQueue><br />
<Named>Queue</Named><br />
</jms:MemoryQueue><br />
<br />
</web-app><br />
</pre><br />
<br />
<br />
===ConnectionFactory configuration===<br />
<br />
<br />
====Example: ConnectionFactory configuration in resin-web.xml====<br />
<pre><br />
<web-app xmlns="http://caucho.com/ns/resin"<br />
xmlns:resin="urn:java:com.caucho.resin"><br />
<br />
<resin:JmsConnectionFactory/><br />
<br />
</web-app><br />
</pre><br />
<br />
<p><br />
The complete configuration is in <br />
<code>WEB-INF/resin-web.xml</code>.<br />
</p><br />
<br />
<br />
===Message Bean configuration===<br />
<br />
<br />
====Example: MyListener configuration in resin-web.xml====<br />
<pre><br />
<web-app xmlns="http://caucho.com/ns/resin"<br />
xmlns:resin="urn:java:com.caucho.resin"><br />
<br />
<ejb-message-bean class="example.MyListener"><br />
<destination>#{Queue}</destination><br />
</ejb-message-bean><br />
<br />
</web-app><br />
</pre><br />
<br />
<br />
<br />
=JMS Messaging in Quercus - Receiving messages=<br />
==Files in this tutorial==<br />
<table><br />
<tr><br />
<th>File</th><br />
<th>Description</th><br />
</tr><br />
<tr><td><code>WEB-INF/resin-web.xml</code></td><br />
<td>resin-web.xml configuration</td><br />
</tr><br />
<tr><td><code>display-ad.php</code></td><br />
<td>PHP script displaying the advertisement.</td><br />
</tr><br />
<tr><td><code>WEB-INF/classes/example/AdProducer.java</code></td><br />
<td>Java listener that fills the advertisement queue.</td><br />
</tr><br />
</table><br />
<br />
==Using JMS in Quercus==<br />
<br />
<p><br />
Quercus offers a simplified messaging interface built upon JMS. This <br />
functionality makes it possible to send and receive messages using either<br />
the Resin JMS implementation or any other messaging service with a JMS<br />
implementation. Many features of JMS are designed for message-driven<br />
services which make sense in the Java world, but are not appropriate for<br />
PHP. This tutorial focuses receiving messages in a non-blocking way.<br />
</p><br />
<br />
<br />
==Receiving JMS messages from a PHP script==<br />
<p><br />
This example uses two queues: an "ad queue" and a "control queue".<br />
The PHP script removes advertisements from the ad queue using the<br />
<code>poll()</code> method. This method is <em>non-blocking</em> -<br />
if there are no advertisements, the method will return <code>FALSE</code><br />
instead of waiting for a new advertisement. Whenever the PHP script<br />
removes an advertisement from the ad queue, it signals a Java message<br />
driven bean (MDB) to add another ad by sending an empty message to the<br />
control queue.<br />
</p><br />
<br />
========<br />
<pre><br />
$ad_queue = java_bean("AdQueue");<br />
$control_queue = java_bean("ControlQueue");<br />
<br />
if (! $ad_queue) {<br />
echo "Unable to get ad queue!\n";<br />
} elseif (! $control_queue) {<br />
echo "Unable to get control queue!\n";<br />
} else {<br />
$ad = $ad_queue->poll();<br />
<br />
if ($ad == null) {<br />
echo "No ads available on the queue\n";<br />
} else {<br />
echo "$ad";<br />
}<br />
<br />
if (! $control_queue->offer(0)) {<br />
echo "Unable to send control message\n";<br />
}<br />
}<br />
</pre><br />
<br />
<p><br />
The programming model of the Quercus JMS interface is first to<br />
get access to the queue using <code>java_bean</code> to get the<br />
named queue. To create a <code>JMSQueue</code> object, pass in<br />
the name of the JMS queue to be used. Since the JMS Queue implements<br />
the <code>BlockingQueue</code> API, the PHP script can use<br />
<code>offer()</code> and <code>poll()</code>. The example above shows<br />
how to use both methods.<br />
</p><br />
<br />
<p><br />
</p><br />
<br />
==Configuring JMS for PHP and Java==<br />
<br />
<p><br />
JMS requires that two resources be set up: A<br />
<code>ConnectionFactory</code> and a <code>Queue</code>. Both are<br />
configured in <code>WEB-INF/resin-web.xml</code>.<br />
The <code>ConnectionFactory</code> is used to connect to all the<br />
<code>Queue</code>s and only one of them needs to be set up.</p><br />
<br />
====Example: connection factory configuration in resin-web.xml====<br />
<pre><br />
<web-app xmlns="http://caucho.com/ns/resin"><br />
<br />
<jms-connection-factory uri="resin:"/><br />
<br />
</web-app><br />
</pre><br />
<br />
<p><br />
This example uses two queues, <code>AdQueue</code> and <br />
<code>ControlQueue</code>.<br />
</p><br />
<br />
====Example: Queue configuration in resin-web.xml====<br />
<pre><br />
<web-app xmlns="http://caucho.com/ns/resin"><br />
<br />
<jms-queue name="AdQueue" uri="memory:"/><br />
<br />
<jms-queue name="ControlQueue" uri="memory:"/><br />
<br />
</web-app><br />
</pre><br />
<br />
<p><br />
The complete configuration is in <code>WEB-INF/resin-web.xml</code>.<br />
</p></div>Rick