# EJB/JMS Transaction Example

The example application will invoke an EJB which within the JBoss AS (Application Server) which will:

1. send a JMS message
2. update a database from the same transaction

The example application will then receive the message sent by the EJB.
We will also check that the database has been updated as expected.

## Example configuration

To run the example, you need to download JBoss AS 5.x and create a configuration for HornetQ.

The example also requires a database. The instructions are for MySQL. If you use another database, please refer to the database documentation to configure it.

The example makes a copy of the default-with-hornetq profile so please configure this for the database

### JBoss AS configuration

Please refer to HornetQ Quickstart guide to install it in JBoss AS 5

### Database configuration

This example needs a database supporting XA transactions. The instructions are written for MySQL. Please refer to your database documentation to configure it appropriately.

To use MySQL with JBoss AS 5

- copy MySQL JDBC jar to `$JBOSS_HOME/server/default-with-hornetq/lib/`

During the deployment, the example will:

- remove HSQLDB configuration (`hsqldb-ds.xml`) from the profile
- copy `mysql-ds.xml` to to the profile

MySQL is configured to connect to a `jbossdb` database using the `jboss`/`jboss` credentials1.

MySQL configuration file defines two DataSources:

- `DefaultDS`, the default DataSource (used to create a table from the example)
- `XADS`, the XA DataSource. This datasource will be used to send a JMS message and update the table within the same transaction

## Example step-by-step

To deploy and run the server, simply type `./build.sh deploy` (or `build.bat deploy` on windows) from this directory.

Once the second server has started, simply type `./build.sh run` (or `build.bat run` on windows) to run the example .

Simply type `./build.sh undeploy` (or `build.bat undeploy` on windows) to remove the profile from JBoss AS 5.

The example code is composed of two main classes:

- `EJBExample`
- the example application
- `SendMessageBean`
- a Stateless EJB

### Example Application

Let's take a look at EJBClientExample first.

1. First we need to get an initial context so we can look-up the JMS connection factory and destination objects from JNDI. This initial context will get it's properties from the jndi.properties

                InitialContext initialContext = new InitialContext();

2. We look up the EJB

                SendMessageService service = (SendMessageService)initialContext.lookup("mdb-example/SendMessageBean/remote");

3. We create the DB table which will be updated if it does not already exist

                service.createTable();

4. We invoke the EJB's `sendAndUpdate` method. This method will send a JMS text message (with the text passed in parameter) and insert a row in the database table with the text and the message's JMS Message ID

                service.sendAndUpdate("This is a text message");

We will now consume the JMS message which was sent by the EJB at step 4.

5. We look up the JMS connection factory

                ConnectionFactory cf = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");

6. We lookup the JMS queue

                Queue queue = (Queue)initialContext.lookup("queue/testQueue");

7. We create a connection, a session and a message consumer for the queue

                connection = cf.createConnection();
                Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                MessageConsumer consumer = session.createConsumer(queue);

8. We start the JMS connection

                connection.start();

9. We receive a message from the queue. It corresponds to the message sent by the EJB

                TextMessage messageReceived = (TextMessage)consumer.receive(5000);
                System.out.println("Received message: " + messageReceived.getText() +
                                             " (" +  messageReceived.getJMSMessageID() + ")");

10. And finally, always remember to close your JMS connections and resources after use, in a `finally` block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects

                finally
                {
                   if (initialContext != null)
                   {
                      initialContext.close();
                   }
                   if (connection != null)
                   {
                      connection.close();
                   }
                 }

### EJB Example

Let's now take a look at the EJB example

1. First, we create a new initial context

                ic = new InitialContext();

2. We look up the JMS XA Connection Factory (which is bound to `java:/JmsXA`)

                ConnectionFactory cf = (ConnectionFactory)ic.lookup("java:/JmsXA");

3. We look up the JMS Queue

                Queue queue = (Queue)ic.lookup("queue/testQueue");

4. We create a JMS connection, a session and a message producer for the queue

                jmsConnection = cf.createConnection();
                Session session = jmsConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                MessageProducer messageProducer = session.createProducer(queue);

5. We create a text message with the text passed in parameter of the EJB method

                TextMessage message = session.createTextMessage(text);

6. We send the message to the queue

                messageProducer.send(message);
                System.out.println("Sent message: " + message.getText() + "(" + message.getJMSMessageID() + ")");

7. We now lookup the JDBC XA DataSource

                DataSource ds = (DataSource)ic.lookup("java:/XADS");

8. We retrieve a JDBC connection

                jdbcConnection  = ds.getConnection();

9. We create a prepared statement to insert the text and message's ID in the DB table

                PreparedStatement pr = jdbcConnection.prepareStatement("INSERT INTO " + TABLE
                            + " (id, text) VALUES ('" + message.getJMSMessageID() + "', '" + text + "');");

10. We execute the prepared statement

                pr.execute();

11. We close the prepared statement

                pr.close();

12. And finally, always remember to close all your connections and resources (for both JMS and JDBC) after use, in a `finally` block.

                finally
                {
                    if (ic != null)
                    {
                       ic.close();
                    }
                    if (jmsConnection != null)
                    {
                       jmsConnection.close();
                    }
                    if (jdbcConnection != null)
                    {
                       jdbcConnection.close();
                    }
                }

## More information

- HornetQ deployment in JBoss AS 5
- Use Alternative Databases with JBoss AS

1. Steps to create the MySQL DB↩
   - connect as root to MySQL: `mysql`
   - create database jbossdb: `create database jbossdb;`
   - create user jboss/jboss: `GRANT ALL PRIVILEGES ON *.* TO 'jboss'@'%' IDENTIFIED BY 'jboss' WITH GRANT OPTION;`
   - disconnect from MySQL
   - check it works: `mysql -u jboss -p jbossdb` (and type `jboss` when prompted for the password)