Entering content frame

Procedure documentationSimple Transaction Message Processing Locate the document in its SAP Library structure

Use

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.

Note

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 graphic is explained in the accompanying text

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).

This graphic is explained in the accompanying text

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.

This graphic is explained in the accompanying text

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.

This graphic is explained in the accompanying text

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.

This graphic is explained in the accompanying text

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.

This graphic is explained in the accompanying text

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).

This graphic is explained in the accompanying text

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.

This graphic is explained in the accompanying text

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));

         }

      }

   }

}

Procedure

...

...

       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.

Result

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:

 

Source Code of JMS Scenarios

 

 

Leaving content frame