!--a11y-->
Simple Transaction Message
Processing 
In this scenario, the material staging process flow that is described in the two point-to-point scenarios is described in more detail. Due to the large number of production units and their distribution in the plant, the warehouse management has been decentralized so that multiple storage locations exist. For a material staging, both the retrieval of the material at the storage location (stock removal) and the transport from the storage location to the corresponding production unit have to be triggered. Accordingly, a material requirement message is considered as processed only if the relevant messages were sent successfully to both the transport logistics and the storage location. In addition, the material stock database has to be updated. If one of these steps fails, the material requirement message is processed again at a later stage.
The transaction concept provided by the JMS API lends itself to fulfilling these requirements. The usage of a JMS transaction ensures that all receiving or sending operations that belong to one logical function (here: material staging) are processed either completely or not at all. The confirmation of a JMS transaction can also be dependent on the result of non-JMS-specific operations (such as updating the material stock database). If a JMS transaction is terminated, however, only JMS-specific operations (sending and receiving messages) are recalled.

By using a client confirmation (see Point-to-Point Scenario with Client Confirmation), only the receipt of a message can be recalled, but not sending operations.
Remember that the transaction term in connection with JMS always refers to the communication between an JMS client and the JMS provider. No transactional linkage takes place between the sender and the receiver of a message (which is a characteristic of asynchronous, message-based communication).

This scenario requires a message sender for the production units, a combined message receiver and sender for the warehouse management, and message receivers for the storage locations and the transport logistics.
For the production units, the message sender from the simple point-to-point scenario can be used.
The warehouse management receives the messages synchronously in an endless loop and processes them further.
The receiver and sender objects are generated as part of the known procedure by using the classes NamingContext, QueueConnectionFactory, Queue, QueueConnection, and QueueSession. In this case, one queue is used for receiving messages, and two queues are used for forwarding messages. The session is generated as a transactional session with an automatic confirmation of the messages when they are received (AUTO_ACKNOWLEDGE).

queueSession = queueConnection.createQueueSession(true, Session.AUTO_ACKNOWLEDGE); queueReceiver = queueSession.createReceiver(productionQueue); |
Two additional senders are required for forwarding requirements to the storage location and transport logistics. These senders have to be generated in the same session to ensure that the sending operations are included in the transaction context of the receiver.

storageSender = queueSession.createSender(storageQueue); transportSender = queueSession.createSender(transportQueue); |
Then the queue is checked for messages synchronously in an endless loop. When a message is received, it is processed. If the message is processed successfully, it is output and transported. If an error occurs, the message is rolled back so that it can be processed again at a later stage. The receiving process can be terminated by entering q.

queueConnection.start(); while (!(key == 'q')) { Message m = queueReceiver.receive(1); if (m != null) { System.out.println("Message received"); if (m instanceof MapMessage) { message = (MapMessage) m; if (process(message)) { System.out.println("Processed message with content: "); for (Enumeration e = message.getMapNames() ; e.hasMoreElements() ;) { String key = (String)e.nextElement(); System.out.println(key+": "+ message.getString(key)); } queueSession.commit(); } else { System.out.println("Processing failed, rolling back session"); queueSession.rollback(); } } } } |
The processing method includes forwarding a message to a production location and to the transport logistics, and simulating an update of a database.

private boolean process(MapMessage m) { try { storageSender.send(m); transportSender.send(m); } catch (JMSException e) { System.out.println("Exception occurred: " + e.toString()); return false; } if (!updateDatabase()) { System.out.println("Database failure"); return false; } return true; } |
A random number mechanism simulates occasional errors that occur during a database update.

private boolean updateDatabase() { // database fails with 50% probability if (failure.nextInt(2) == NO_FAILURE) return true; else return false; } |
The storage locations and the transport logistics receive messages synchronously in an endless loop and return a relevant message for each message received. Since a point-to-point model is to be used here, two separate queues are required for the storage location and the transport logistics. To use the same receiver logic, the queue name is transferred to the program as a parameter.
The receiver object is generated as part of the known procedure by using the naming context, the queue connection factory, the queue, the queue connection, and the queue session. The session is generated without a transaction and with an automatic confirmation of the messages when they are received (AUTO_ACKNOWLEDGE).

queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); queueReceiver = queueSession.createReceiver(queue); |
Then the queue is checked for messages synchronously in an endless loop. When a message is received, its type is checked, and the fields of the message are output. The receiving process can be terminated by entering q.

queueConnection.start(); while (!(key == 'q')) { Message m = queueReceiver.receive(1); if (m != null) { if (m instanceof MapMessage) { message = (MapMessage) m; System.out.println("Reading message with content: "); for (Enumeration e = message.getMapNames() ; e.hasMoreElements() ;) { String key = (String)e.nextElement(); System.out.println(key+": "+message.getString(key)); } } } } |
...
...
1. Generation and registration of queues
Using the Visual Administrator tool of the SAP J2EE Engine, generate three queues named:
¡ ProductionUnitRequirements
¡ StorageRequirements
¡ TransportationRequirements
2. Start the receivers
Make sure that the J2EE Engine is running. In the directory of the compiled example packages, open two windows for the command line, and start one receiver for each storage location and the transport logistics by entering the following commands:
java -cp .;<Path to J2EE Client Library>;<Path to JMS API Library> scenario5.RequirementReceiver StorageRequirements
java -cp .;<Path to J2EE Client Library>;<Path to JMS API Library> scenario5.RequirementReceiver TransportationRequirements |
3. Start the Warehouse Management
In the directory of the compiled example packages, open a window for the command line, and start the program for warehouse management with the following command:
java -cp .;<Path to J2EE Client Library>;<Path to JMS API Library> scenario5.WarehouseReceiver |
4. Start the sender
In the directory of the compiled example packages, open a window for the command line, and start the sender for the production unit with the following command:
java -cp .;<Path to J2EE Client Library>;<Path to JMS API Library> scenario5.ProductionUnitSender REQ1 PU1 P-100 2 06.03.2003 |
The sender then sends a message to its queue with the parameters that were specified when the program was started.
The following is an example of the output for the warehouse management:
Message received Database failure Processing failed, rolling back session Message received Processed message with content: MaterialID: P-100 MaterialRequirementDate: 06.03.2003 ProductionUnitID: 1 RequirementID: 13 MaterialAmount: 2 |
When the message is processed, an error occurs, which leads to a rollback. The same message is then processed successfully and confirmed.
Using the transaction ensures that in the case of an error, the receipt of the message by the production unit, and the forwarding of the message to the storage location and the transport logistics can be recalled together. The message can then be received and processed again.
Accordingly, the receivers for the storage location and the transport logistics display the message once only, which means that the first sending operation from the warehouse management was recalled successfully in the rollback process:
Reading message with content: MaterialID: P-100 MaterialAmount: 2 MaterialRequirementDate: 06.03.2003 |
See also:
