소프트웨어 엔지니어 고문, IBM
2005년 2 월 17 일
Jython으로 프로그래밍을 하면 Python의 장점을 활용하면서 자바 패키지 및 기능들로 접근을 관리할 수 있다. Apache Derby 관계형 데이터베이스에 접근하고 이를 조작하는데 Jython이 어떻게 사용되는지 살펴본다.
There are some similarities between the two; they both support JMS 1.1 and run inside JBoss 4.x.
However ActiveMQ does offer some specific differences and advantages (at least from our perspective)
I am commenting here the WS-BPEL working
draft 4/23/04 which is publicly available on
the OASIS web site.
It looks like the BPEL working group is
moving ahead with its plan to focus BPEL on B2B relationships. It
can be applied in one of two ways, a BPEL process can define:
One of the BPEL goals is to "lower the cost
in establishing cross-enterprise automated business processes".
I guess I am very confused by these
statements. After working for four years on ebXML, and being the
editor of the ebXML Business Process Specification Schema module, I
cannot but wonder how BPEL can be used in B2B scenarios. So
problably the best way to continue my commentary is to take an
example, say a simple RFQ/Order/Payment collaboration between a
buyer and a supplier. I have taken an example that is simple but non
trivial like the so many examples used to illustrate BPEL.
This example is using
BPMN and details 3 main components of the overall process. The
private process of the buyer, the private process of the supplier
and collaboration between the buyer, the supplier, the bank and the
credit check organization. The private process starts and as part of
its "GetQuote" activity it sends an RFQ document to the supplier
(this is when the collaboration starts). When the supplier receives
this document it dispatches it to its ProcessRFQ activity. This
activity is invoking the PrepareQuote activity which is actually an
activity performed by a user. As part of the activity, the user
invokes the ManageAccount activity which is in charge of creating a
customer record if the customer is unknown and in all cases to
perform a credit check with a partner agency. If all goes well, a
quote is returned to the processRFQ activity which forward it to the
customer. If the customer likes the quote, its process stipulates
that it will start the SendOrder activity which creates and send an
order relative to the quote. When the order is received by the
supplier, it dispatches to the processRFQ activity, which ends at
this point, and initiate the processOrder activity which notifies
the IssueInvoice activity which sends an invoice as a response to
the order. And so on...
If you want to see the details of one
activity, please see figure 2.
Now, as you can see here, there are several
concepts that ARE NOT supported by BPEL:
Now, on the "EAI" front (BPEL does
not claim clearly that space but some vendors like Collaxa view as a
domain of application of BPEL), BPEL is not much more efficient than
on the business process or B2B collaboration space. If I completely agree with Collaxa
on the fact that EAI is a good domain of application for BPEL, BPEL is
still missing the capability of transformation so useful in that
space. In the example above, for instance I cannot say that the
order document consumed by my ProcessQuote activity is actually a
transformed version of the order document sent by the buyer. These
kinds of transformation are done "by hand" with the assign/copy
activity. BPEL is so entrenched in B2B now that when you try to apply BPEL to EAI
you realize that every message based activity (send receive and
invoke) have a "partnerLink", ... but in EAI there is no partner,
just components. So if you now have a private process linking your
B2B interface to your back end systems you are left with this
dilemma that some activities must have a partnerLink while other don't.
Nothing has fundamentally changed compared
to my previous analysis of BPEL.
So where does this leaves us? I have been
arguing for sometime that BPEL is a programming language that let us
write business logic that can be part of a business process. In the
example above, the processRFQ or manageAccount, or sendOrder/processOrder
activities are all (web) services that manage a given business
entity (RFQ, Account, Order). The lifecycle of these services is
long running itself as the business processes they participate in.
Typically this business logic is very hard to write, debug,
maintain. Most technologies like Java/J2EE or .NET/COM+ have never
been designed for that purpose. All message handling is done as hoc.
It looks like that some people understand this since IBM and BEA
(and Collaxa way before them) has come up with the concept of
BPEL-J.
So a service would look like this:
src="bpel_2_0_files/image002.gif" v:shapes="_x0000_s1025">
This service is "orchestrated" and can
easily be described in BPEL (without partnerLinks). The business
process itself is not an orchestration but a choreography. This
concept is now supported by WS-CDL and
its authors, and I think to a certain extend by
BPMN.
Unfortunately, by pushing BPEL in the wrong
direction, the working groups and editors will achieve nothing: the
B2B model supported by BPEL will not be able to compete with the one
proposed by WS-CDL and ebXML BPSS, while the at the same time, we
would still be waiting for an "orchestration" language that no one
else is working on. I have my little idea of the politics behind all
this but it is kind of sad that after working for 5 years on the
problem (XLang was announced in the spring of 1999) we never left
the starting blocks, as I said before, BPEL represents how we
thought (I thought) about Business Processes 5 years ago. In five
years, we've got five years behind.
Jean-Jacques Dubray 6/13/04
I also would like to add some precisions on the differences between ESB (Enterprise Service Bus)
and SOA. There
is a fundamental difference between EAI (and the web service enabled EAI, a.k.a.
ESB) and SOA. EAI relies on a "common information model", with a
central EAI manager, onto which enterprise systems are bolted via
connectors (be it web services, JCA or anything else). The bus represents both
the common information model and the EAI manager. In an ESB, connected systems are not in control, the EAI manager is.
ESB is not SOA. SOA requires a registry onto
which peers registers and find other peers. In a SOA, every peer is at the same
level, there is no center of control, nothing in the middle, therefore no need
for a common
information model. Peers are not defined by their "contract" but
rather by how they interact with each other (i.e. collaborate via a message
choreography). To answer Collaxa's question, IMHO, Indigo is not an ESB, it
is a true SOA framework, just like TME's GAIA or SUN's
JXTA project. (Please
take a look at figure 7 of the BCM introduction). ESB can be viewed as a very
particular case of SOA, a special kind of fabric if you will, but it is
certainly not the only fabric possible.
Another aspect that few people seem to be grasping at the moment is that for building SOAs
we need the
notion of "service domains" (no, this is not the same thing as
Scopes, since scopes have always a context associated to them). This notion is natural as soon as we
think of a company boundary (which will be its own service domain), but the
concept is also useful at a lower level of granularity. It greatly simplifies
problems like management, security, ... but also offer an extra level of
decoupling. WS-CAF is going a bit in this direction with the concept of
coordination, but it stops short of providing "domain level" logic, it
rather relies on well defined composition of web services packaged in a
"composite application".
This page descibes the specifics for setting up various Jms Servers in Mule. For more information about all Mule Jms configuration go here.
The following Jms server configurations are described -
If you have configuration for a Jms server not listed here or there is a mistake on this page please raise a jira to get the document updated. Thanks.
JMS Endpoint URIs and JNDI destinations Some JNDI implementations treat dot (.) and forward slash symbols differently in destination names, so jms://order/incoming may not be the same as jms://order.incoming, but the former will not give you the order/incoming destination, but incoming. If you are dealing with such a server (JBoss is known to behave this way), here is a trick to help you: jms:////order/incoming See Mule Endpoint URIs for reference. and JmsEndpointTestCase for some more examples. |
The following are just examples and configuration values will change depending on your application environment. |
To configure a default embedded broker.
<connector name="jmsConnector" className="org.mule.providers.jms.JmsConnector">
<properties>
<property name="specification" value="1.1"/>
<property name="connectionFactoryJndiName" value="ConnectionFactory"/>
<property name="jndiInitialFactory"
value="org.activemq.jndi.ActiveMQInitialContextFactory"/>
<map name="connectionFactoryProperties">
<property name="brokerURL" value="vm://localhost"/>
<property name="brokerXmlConfig"
value="classpath:/org/mule/test/activemq-config.xml"/>
</map>
</properties>
</connector>
The specification property tells Mule to use the Jms 1.1 specification, which is the specification ActiveMQ supports. To disable queue persistence, you'll need to specify it in ActiveMQ configuration file (see below).
You can pass in any provider specific configuration using the connectionFactoryProperties property on the JmsConnector. These will get set on the ConnectionFactory implementation. |
To configure ActiveMQ on a specific brokerUrl or from an ActiveMQ configuration file use the following (Spring version)
<!-- Give this container a name in case you have more than one container,
e.g. Spring, Plexus, JNDI, EJB, etc. You can safely omit it if you
don't have these requirements.
-->
<container-context className="org.mule.extras.spring.SpringContainerContext"
name="spring">
<properties>
<property name="configFile" value="classpath:/org/mule/test/activemq-spring.xml"/>
</properties>
</container-context>
<connector name="jmsConnector" className="org.mule.providers.jms.JmsConnector">
<properties>
<property name="specification" value="1.1"/>
<!-- The container name must be the same as above in
container-context element or empty (then the first available
one will be used.
-->
<container-property name="connectionFactory"
reference="activeMqConnectionFactory"
container="spring"
</properties>
</connector>
Configure ActiveMQ from Spring:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="activeMqConnectionFactory" class="org.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost"/>
<property name="brokerXmlConfig"
value="classpath:/org/mule/test/activemq-config.xml"/>
<!-- More properties you want set on ActiveMQConnectionFactory -->
</bean>
</beans>
Your ActiveMQ config is a standard one. E.g. to use in-JVM messaging without persistent queues (very useful for testing) the file will be as follows:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//ACTIVEMQ//DTD//EN" "http://activemq.org/dtd/activemq.dtd">
<beans>
<broker>
<connector>
<serverTransport uri="vm://localhost"/>
</connector>
<persistence>
<vmPersistence/>
</persistence>
</broker>
</beans>
To configure a JBoss Jms connector for Mule use the following -
<connector name="jmsConnector" className="org.mule.providers.jms.JmsConnector">
<properties>
<property name="jndiInitialFactory"
value="org.jnp.interfaces.NamingContextFactory"/>
<property name="jndiProviderUrl" value="jnp://localhost/"/>
<property name="connectionFactoryJndiName" value="java:/ConnectionFactory"/>
</properties>
</connector>
Any provider-specific properties can be passed to the InitialContext for this connector using the jndiProviderProperties attribute. Use connectionFactoryProperties to set JBoss-specific properties on the ConnectionFactory.
The following example configuration describes how to configure a MUle JmsConnector for OpenJms. You will probably need to change the connectionFactoryJndiName to one that is configured from your OpenJms configuration.
<connector name="jmsConnector" className="org.mule.providers.jms.JmsConnector">
<properties>
<property name="connectionFactoryJndiName" value="QueueConnectionFactory"/>
<property name="jndiInitialFactory"
value="org.exolab.jms.jndi.InitialContextFactory"/>
<property name="jndiProviderUrl" value="tcp://localhost:3035"/>
</properties>
</connector>
Todo. If you are using Mule with Uber MQ please contact us with your configuration and any tips to getting Uber MQ and Mule working together. Thanks!
The configuration shown is for Weblogic 8.1 but should work with previous versions.
<connector name="jmsConnector" className="org.mule.providers.jms.JmsConnector">
<properties>
<property name="specification" value="1.0.2b"/>
<property name="connectionFactoryJndiName"
value="yourConnectionFactory" />
<property name="jndiInitialFactory"
value="weblogic.jndi.WLInitialContextFactory"/>
<property name="jndiProviderUrl" value="t3://localhost:7001"/>
</properties>
</connector>
There are some tricks to getting Oracle AQ working with Mule because the AQ implementation veers from the Jms specification when creating Connection Factories. The big difference is that Oracle uses a db-centric queue model meaning that really when you create a Connection you are creating a Oracle Jdbc connection. This connector will let Mule talk via the Jms API to a queue in an oracle database without using Jndi. (oracle standard edition disables exporting a queue to a repository).
This connector can be used to send a jms message when table data changes.
The Oracle JMS Provider extends the standard Mule Jms Provider with functionality specific to Oracle's JMS implementation based on Advanced Queueing (Oracle AQ).
The javadoc for this transport provider can be found here. And the Source Xref can be found here.
The Oracle JMS Provider adds support for queues with ADT (Advanced Data Type) payloads, including Oracle's native XML data type
Unlike the standard JMS Provider, the Oracle JMS Provider does
not require a JNDI provider to use.
As of Oracle 9i, only the JMS 1.0.2b specification is supported. |
In addition to the properties available for the standard Jms Provider, the Oracle JMS Provider adds the following properties:
Property | Description | Default | Required | ||
---|---|---|---|---|---|
url | The JDBC URL for the Oracle database, for example jdbc:oracle:oci:@myhost.
| yes | |||
multipleSessionsPerConnection | Some versions of Oracle do not support more than one JMS session per connection. In this case we need to open a new connection for each session to avoid the following error: JMS-106: Cannot have more than one open Session on a JMSConnection | false | no | ||
payloadFactory | If the queue's payload is an ADT (Oracle Advanced Data Type), the appropriate payload factory must be specified in the endpoint's properties. | no |
In addition to the transformers available for the standard Jms Provider, the Oracle JMS Provider adds the following transformers, found in org.mule.vendor.oracle.jms.transformers.
Transformer | Description |
---|---|
StringToXMLMessage | Expects a string containing properly-formed XML. Creates a JMS message whose payload is Oracle's native XML data type. |
XMLMessageToDOM | Expects a JMS message whose payload is Oracle's native XML data type. Returns the XML as a W3C Document (DOM). |
XMLMessageToStream | Expects a JMS message whose payload is Oracle's native XML data type. Returns the XML as an InputStream. |
XMLMessageToString | Expects a JMS message whose payload is Oracle's native XML data type. Returns the XML as a String. |
The default transformers are the same as the standard JMS Provider (JMSMessageToObject and ObjectToJMSMessage).
The following is an example configuration using the Oracle JMS Provider:
<mule-configuration id="TestConfiguration" version="1.0">
<connector name="oracleJmsConnector" className="org.mule.vendor.oracle.jms.OracleJmsConnector">
<properties>
<property name="url" value="jdbc:oracle:oci:@myhost" />
<property name="username" value="scott" />
<property name="password" value="tiger" />
</properties>
</connector>
<transformers>
<transformer name="StringToXMLMessage"
className="org.mule.vendor.oracle.jms.transformers.StringToXMLMessage"
returnClass="oracle.jms.AdtMessage" />
<transformer name="XMLMessageToString"
className="org.mule.vendor.oracle.jms.transformers.XMLMessageToString"
returnClass="java.lang.String" />
</transformers>
<global-endpoints>
<endpoint name="XmlQueue" address="jms://XML_QUEUE" transformers="StringToXMLMessage" />
</global-endpoints>
<model name="Test Model">
<mule-descriptor name="XML-Driven UMO" implementation="com.foo.MyUMO">
<inbound-router>
<endpoint address="jms://XML_QUEUE" transformers="XMLMessageToString">
<properties>
<property name="payloadFactory" value="oracle.xdb.XMLTypeFactory" />
</properties>
</endpoint>
</inbound-router>
</mule-descriptor>
</model>
</mule-configuration>
Refer to the unit tests for more examples on how to use the provider.
The Oracle JMS Provider requires the following Oracle libraries, which should be included in your Oracle installation:
The unit tests consist of two test suites: UnitTestSuite.java and IntegrationTestSuite.java. Only the integration test suite requires a live Oracle database.
In order to run the integration tests, you must edit the settings in file src/test/java/org/mule/vendor/oracle/jms/TestConfig.java according to your Oracle database.
The tests assume that your Oracle user has sufficient privileges to create and drop queues in the database. |
The configuration provided is for the SeeBeyond ICAN IQManager JMS Server. Note the values in [ ] (square brackets), these should be replaced by values relevant to your installation.
<connector name="jmsConnector" className="org.mule.providers.jms.JmsConnector">
<properties>
<property name="jndiInitialFactory"
value="com.stc.is.naming.NamingContextFactory"/>
<!-- port 18006 is the default, change it in the SeeBeyond designer -->
<property name="jndiProviderUrl" value="[ServerName]:18006"/>
<property name="connectionFactoryJndiName"
value="/jms/connectionfactory/queue/[LogicalHostName]_[JMS iqManager Name]" />
</properties>
</connector>
For a topic, the connectionFactoryJndiName would be /jms/connectionfactory/
topic/[LogicalHostName]_[JMS iqManager Name].
You will need the following jars and files from the Java ApiKit on your classpath:
Thanks to Brian Kalbfus for contributing this configuration.
To configure a WebSphere MQ Jms connector for Mule use the following -
<connector name="jmsConnector" className="org.mule.providers.jms.JmsConnector">
<properties>
<property name="specification" value="1.0.2b"/>
<property name="jndiInitialFactory" value="com.sun.jndi.fscontext.RefFSContextFactory"/>
<property name="jndiProviderUrl" value="file:///E:/wsmq_v53/bindings"/>
<property name="connectionFactoryJndiName" value="ConnectionFactory"/>
</properties>
</connector>
The specification property tells Mule to use the Jms 1.0.2b specification, which is the specification WebSphere MQ v5.3 supports.
You will also need the following jars on your classpath:
The following demonstrates how to configure Mule to use the SpiritWave Jms server.
<connector name="jmsConnector" className="org.mule.providers.jms.JmsConnector">
<properties>
<property name="connectionFactoryJndiName" value="ConnectionFactory"/>
<property name="jndiInitialFactory"
value="com.spirit.core.util.builder.JNDIResolver"/>
<map name="jndiProviderProperties">
<property name="messageChannels" value="tcp://localhost:50607"/>
<property name="driverName" value="SpiritWave"/>
</map>
</properties>
</connector>
Using Joram with Mule is a little less straight forward that the other Jms servers if you do not have a Jndi context set up for your connections and destinations. If you have Jndi set up you can use the following-
<connector name="JMSConnector" className="org.mule.providers.jms.JmsConnector">
<properties>
<property name="connectionFactoryJndiName" value="QueueConnectionFactory"/>
<property name="specification" value="1.1"/>
<property name="jndiDestinations" value="true"/>
<property name="connectionFactoryJndiName" value="ConnectionFactory"/>
<property name="jndiInitialFactory"
value="fr.dyade.aaa.jndi2.client.NamingContextFactory"/>
<map name="jndiProviderProperties">
<property name="java.naming.factory.host" value="localhost"/>
<property name="java.naming.factory.port" value="16400"/>
</map>
</properties>
</connector>
Durable Subscribers When using durable subscribers Mule automatically sets the Jms clientId on the connection, if not explicitly set. Joram complains if the clientId is set, so you need to tell Mule not to set it by setting the clientId on the JmsConnector to "". |
If you do not have Jndi set up you need to manually create a Jndi Initial Context. You can do this by adding a Mule property factory (like the one listed below). Your configuration will look something like -
<connector name="JMSConnector" className="org.mule.providers.jms.JmsConnector">
<properties>
<property name="connectionFactoryJndiName" value="QueueConnectionFactory"/>
<property name="specification" value="1.1"/>
<property name="jndiDestinations" value="true"/>
<list name="jndiQueues">
<entry value="exception.queue"/>
</list>
<property-factory name="jndiContext" value="com.foo.joram.JoramInitialContextFactory"/>
</properties>
</connector>
The Jndi property factory class will look like the following, though you may want to add support for other Joram properties.
public class JoramTest implements PropertyFactory
{
public Object create(Map properties) throws Exception
{
String connectionFactoryJndiName = (String) properties.get("connectionFactoryJndiName");
if (connectionFactoryJndiName == null)
{
throw new InitialisationException(
"connectionFactoryJndiName must be set");
}
// Connecting to JORAM server:
AdminModule.connect("root", "root", 60);
//Create anonymous user if security is not required
User user = User.create("anonymous", "anonymous");
// Creating the JMS administered objects:
javax.jms.ConnectionFactory connFactory = TcpConnectionFactory.create();
// Binding objects in JNDI:
//Create Jndi Queues
javax.naming.Context jndiCtx = new javax.naming.InitialContext();
jndiCtx.bind(connectionFactoryJndiName, connFactory);
List queues = (List)properties.get("jndiQueues");
if(queues!=null) {
Queue queue;
String name;
for (Iterator iterator = queues.iterator(); iterator.hasNext();)
{
name = (String) iterator.next();
queue = (Queue) Queue.create(0);
// Setting free access to the queue:
queue.setFreeReading();
queue.setFreeWriting();
jndiCtx.bind(name, queue);
}
}
//Create Jndi Topics
List topics = (List)properties.get("jndiTopics");
if(topics!=null) {
Topic topic;
String name;
for (Iterator iterator = topics.iterator(); iterator.hasNext();)
{
name = (String) iterator.next();
topic = (Topic) Topic.create(0);
// Setting free access to the queue:
topic.setFreeReading();
topic.setFreeWriting();
jndiCtx.bind(name, topic);
}
}
AdminModule.disconnect();
return jndiCtx;
}
}
February 11, 2002
Updated March 04, 2002
Description
Maintenance
version of the JavaTM Message Service specification, version 1.1.
Specification Lead
Kate Stout,
Sun Microsystems, Inc.
Feedback
This maintenance
release addresses the unification of the programming interfaces for the Point-to-Point
and Pub/Sub messaging domains in the Java Message Service (JMS) API. In the
existing version of the specification, the client programming model make
a strong distinction between these two domains. One consequence of domain
separation is that actions from the Point-to-Point domain and the Pub/Sub
domain in can not be used in the same transaction.
In this proposed
domain unification of the interfaces, methods have been added to support
the ability to include PTP and Pub/Sub messaging in the same transaction.
In addition, the domain unification proposed simplifies the client programming
model, so that the client programmer can use a simplified set of APIs to create
an application.
This proposal
is
- Fully backwards compatible;
existing implementations will work as is.
- Semantically compatible;
semantic differences between the two messaging domains are retained
ConnectionConsumer
createConnectionConsumer(Destination destination, String messageSelector,
ServerSessionPool sessionPool, int maxMessages) throws JMSException;
ConnectionConsumer createDurableConnectionConsumer(Topic topic,String
subscriptionName, String messageSelector, ServerSessionPool sessionPool,
int maxMessages) throws JMSException;
Session createSession(boolean transacted, int acknowledgeMode) throws
JMSException;
Connection createConnection() throws JMSException;
Connection createConnection(String userName, String password) throws
JMSException;
Destination getDestination() throws JMSException;
void send(Message message) throws JMSException;
void send(Message message, int deliveryMode, int priority, long timeToLive)
throws JMSException;
void send(Destination destination, Message message) throws JMSException;
void send(Destination destination, Message message, int deliveryMode,
int priority, long timeToLive) throws JMSException;
MessageProducer createProducer(Destination destination) throws JMSException;
MessageConsumer createConsumer(Destination destination) throws JMSException;
MessageConsumer createConsumer(Destination destination, java.lang.String
messageSelector) throws JMSException;
MessageConsumer createConsumer(Destination destination, java.lang.String
messageSelector, boolean NoLocal) throws JMSException;
TopicSubscriber createDurableSubscriber(Topic topic, java.lang.String
name) throws JMSException;
TopicSubscriber createDurableSubscriber(Topic topic, java.lang.String
name, java.lang.String messageSelector, boolean noLocal) throws JMSException;
QueueBrowser createBrowser(Queue queue) throws JMSException;
QueueBrowser createBrowser(Queue queue, String messageSelector) throws
JMSException;
Queue createQueue(String name) throws JMSException;
Topic createTopic(String name) throws JMSException;
TemporaryTopic createTemporaryTopic() throws JMSException;
TemporaryQueue createTemporaryQueue() throws JMSException;
void unsubscribe(String string name)
XASession createXASession() throws JMSException;
XAConnection createXAConnection() throws JMSException;
XAConnection createXAConnection(String userName, String password)
throws JMSException;
int getBodyLength() throws JMSException
int getAcknowledgeMode() throws JMSException
Example 1: Setting up a connection and session
JMS 1.0.2b
JMS 1.1
Example
2: Creating a Message Producer to a topic
JMS 1.0.2b
JMS 1.1
Example
3 - Adding a Message Producer to a queue
JMS 1.0.2b
JMS 1.1
// Look up connection factory and topic.
topicConnectionFactory = (TopicConnectionFactory)
topicConnection = topicConnectionFactory.createConnection();
Use ConnectionFactory, Connection and Session to setup.
Context jndiContext = null;
// Look up connection factory and topic.
Example
2: Creating a message producer (to a topic)
Set a message producer that can send messages
Sets up a TopicPublisher and sends messages on a TopicSession
// Create a TopicPublisher and send a message
TopicPublisher topicPublisher = null;
// Create a Message Producer and send a message
MessageProducer messageProducer = null;
Example
3: Adding a Message Producer to a queue
The client programming simplification can be seen if we now try to add a
Message producer that will send messages to a Queue.
To do this, the application must:
By contrast, the unified model can re-use the Connection and Session that
has already been established. The additional steps are:
MessageProducer workFlowProducer = null;