Creating the XML_Reservation message flow

Use the following instructions to create the XML_Reservation message flow. For more detailed instructions, click the links provided at the end of each step.

To create and configure the XML_Reservation message flow:

  1. Create a new message flow called XML_Reservation.
    For instructions, see Creating a message flow in the WebSphere Message Broker documentation.
  2. In the Message Flow editor, add and rename the nodes listed in the following table.
    For instructions, see Adding a message flow node in the WebSphere Message Broker documentation.
    Palette drawers Node type Node name
    WebSphere MQ MQInput XML_RESERVATION_IN
    WebSphere MQ MQOutput XML_RESERVATION_OUT
    WebSphere MQ MQOutput XML_RESERVATION_FAIL
    Transformation Compute UpdatePassengerTable
    Transformation Compute BuildSingleMessage
    Transformation Compute PropagateMultipleMessages
    Database Database UpdateFlightTable
    Routing Filter MultipleOrSingleMessage
    Construction Throw InvalidRequest
    Construction Trace LogException
  3. Connect the nodes together as shown in the following table.
    For instructions, see Connecting message flow nodes in the WebSphere Message Broker documentation.
    To check that you have connected the nodes together correctly, see the diagram in About the XML_Reservation message flow.
    Node name Terminal Connect to this node
    XML_RESERVATION_IN Out UpdateFlightTable
    Catch XML_RESERVATION_FAIL
    UpdateFlightTable Out UpdatePassengerTable
    UpdatePassengerTable Out MultipleOrSingleMessage
    MultipleOrSingleMessage Unknown InvalidRequest
    False BuildSingleMessage
    True PropagateMultipleMessages
    BuildSingleMessage Out XML_RESERVATION_OUT
    PropagateMultipleMessages Out XML_RESERVATION_OUT
    XML_RESERVATION_FAIL Out LogException
  4. Configure the node properties as shown in the following table.
    Accept the default values for all of the properties unless an alternative value is shown in the table.
    For instructions, see Configuring a message flow node in the WebSphere Message Broker documentation.
    Node name Page Property Value
    XML_RESERVATION_IN Basic Queue name XML_RESERVATION_IN
    (This value is the local queue from which the message flow takes the message.)
    Input Message Parsing Message domain XMLNSC : For XML messages (namespace aware, validation, low memory use)
    (This value tells the broker to use the generic XML parser.)
    UpdateFlightTable Basic Data source RESERVDB
    (This value is the database that is used by this node.)
    Basic Statement

    UpdateFlightTable
    (Replace the default value)
    (This value is the name of the ESQL module that is used by this node during processing. The name must match the name in the CREATE DATABASE MODULE statement in the ESQL file.)

    UpdatePassengerTable Basic Data source

    RESERVDB
    (This value is the database that is used by this node.)

    Basic ESQL module UpdatePassengerTable
    (Replace the default value)
    (This value is the name of the ESQL module that is used by this node during processing. The name must match the name in the CREATE COMPUTE MODULE statement in the ESQL file.)
    XML_RESERVATION_OUT Basic Queue name
    (You are not required to specify the name of the queue manager because the queue is defined on the same queue manager as the broker.)
    XML_RESERVATION_OUT
    (This value is the local queue on which the message flow puts the message.)
    LogException Basic Destination Local Error Log
    (This value instructs the node to write the trace information to the local error log. On Windows, the local error log is Event Viewer; on Linux, the local error log is syslog.)
    Basic Pattern Date is:
    ${EXTRACT (MONTH FROM CURRENT_DATE)}/
    ${EXTRACT (DAY FROM CURRENT_DATE)}/
    ${EXTRACT (YEAR FROM CURRENT_DATE)}
    Time is: ${EXTRACT (HOUR FROM CURRENT_TIMESTAMP)}:
    ${EXTRACT(MINUTE FROM CURRENT_TIMESTAMP)}

    Environment is:
    ${Environment}

    Exception List is:
    ${ExceptionList}

    (This value extracts the date and time information, and information about the error from the Exception List.)
    Basic Message number 3052
    MultipleOrSingleMessage Basic Filter Expression MultipleOrSingleMessage
    BuildSingleMessage Basic ESQL Module

    BuildSingleMessage
    (Replace the default value)
    (This value is the name of the ESQL module that is used by this node during processing. The name must match the name in the CREATE DATABASE MODULE statement in the ESQL file.)

    PropagateMultipleMessages Basic ESQL Module

    PropagateMultipleMessages
    (Replace the default value)
    (This value is the name of the ESQL module that is used by this node during processing. The name must match the name in the CREATE DATABASE MODULE statement in the ESQL file.)

    XML_RESERVATION_FAIL Basic Queue name
    (You are not required to specify the name of the queue manager because the queue is defined on the same queue manager as the broker.)
    XML_RESERVATION_FAIL
    (This value indicates where the message flow puts the message if the processing fails.)
  5. In the XML Airline Message Flows project, double-click the ESQL file to open it in the ESQL editor. Copy and paste the following ESQL code modules to the ESQL file, then save the file. For more information, see Developing ESQL in the WebSphere Message Broker documentation.
    -- ************************************************
    -- * ESQL for the XML_Reservation message flow
    -- ************************************************
    
    CREATE DATABASE MODULE UpdateFlightTable
    	CREATE FUNCTION Main() RETURNS BOOLEAN
    	BEGIN
    		-- populate the environment with flight info from the database		
    		SET Environment.Variables =
    			THE (SELECT T.* FROM Database.XMLFLIGHTTB AS T
    				WHERE T.FLIGHTDATE = Root.XMLNSC.Reservation.FlightDetails.FlightDate
    				AND T.FLIGHTNO = Root.XMLNSC.Reservation.FlightDetails.FlightNumber);
    		DECLARE ref REFERENCE TO Root.XMLNSC.Reservation.ListOfPassengers.PassengerDetails[1];
    		-- track the remaining number of seats
    		SET Environment.Variables.EconomyClassRemain = CAST(Environment.Variables.TOTALECONOMIC AS INTEGER);
    		SET Environment.Variables.FirstClassRemain = CAST(Environment.Variables.TOTALFIRST AS INTEGER);
    
    		-- loop through the request, counting the passengers and checking capacity
    		SET Environment.Variables.NoPassengers = 0;
    		WHILE LASTMOVE(ref) DO -- check that the REFERENCE is still valid
    			IF ref.Class = 'F' THEN
    				IF Environment.Variables.FirstClassRemain >= 1 THEN
    					SET Environment.Variables.FirstClassRemain = Environment.Variables.FirstClassRemain - 1;
    					SET Environment.Variables.FIRSTCLASS = Environment.Variables.FIRSTCLASS + 1;
    					SET Environment.Variables.NoPassengers = Environment.Variables.NoPassengers + 1;
    				ELSE
    					THROW USER EXCEPTION MESSAGE 2949 VALUES('Number of passengers exceeds capacity');
    				END IF;
    			END IF;
    			IF ref.Class = 'Y' THEN
    				IF Environment.Variables.EconomyClassRemain >= 1 THEN
    					SET Environment.Variables.EconomyClassRemain = Environment.Variables.EconomyClassRemain - 1;
    					SET Environment.Variables.ECONOMICCLASS = Environment.Variables.ECONOMICCLASS + 1;
    					SET Environment.Variables.NoPassengers = Environment.Variables.NoPassengers + 1;
    				ELSE
    					THROW USER EXCEPTION MESSAGE 2949 VALUES('Number of passengers exceeds capacity');
    				END IF;
    			END IF;
    			MOVE ref NEXTSIBLING REPEAT NAME; -- increment the loop condition
    		END WHILE;
    		
    		-- update the database with the decreased seat availability for the flight
    		UPDATE Database.XMLFLIGHTTB AS T
    			SET ECONOMICCLASS = Environment.Variables.ECONOMICCLASS,
    				TOTALECONOMIC = Environment.Variables.EconomyClassRemain,
    				FIRSTCLASS = Environment.Variables.FIRSTCLASS,
    				TOTALFIRST = Environment.Variables.FirstClassRemain
    				WHERE T.FLIGHTDATE = Root.XMLNSC.Reservation.FlightDetails.FlightDate
    				AND T.FLIGHTNO = Root.XMLNSC.Reservation.FlightDetails.FlightNumber;
    		RETURN TRUE;
    	END;
    END MODULE;
    
    CREATE COMPUTE MODULE UpdatePassengerTable
    	CREATE FUNCTION Main() RETURNS BOOLEAN
    	BEGIN		
    		SET OutputRoot = InputRoot;		
    		DECLARE I INTEGER 1;
    		DECLARE J INTEGER Environment.Variables.NoPassengers;
    		DECLARE resno CHARACTER;
    		WHILE I <= J DO -- loop through the passengers
    			SET Environment.Variables.RESERVATIONSEQNO = Environment.Variables.RESERVATIONSEQNO + 1;
    			-- generate the reservation number (unique)
    			SET resno = (InputRoot.XMLNSC.Reservation.FlightDetails.FlightNumber ||
    						 InputRoot.XMLNSC.Reservation.FlightDetails.FlightDate ||
    						 CAST (Environment.Variables.RESERVATIONSEQNO AS CHAR));
    			-- insert a row into the database to track this reservation
    			INSERT INTO Database.XMLPASSENGERTB (LASTNAME, FIRSTNAME, FLIGHTNO, FLIGHTDATE, CLASSTYPE, RESERVATIONNO)
    				VALUES(InputRoot.XMLNSC.Reservation.ListOfPassengers.PassengerDetails[I].LastName,
    					   InputRoot.XMLNSC.Reservation.ListOfPassengers.PassengerDetails[I].FirstName,
    					   InputRoot.XMLNSC.Reservation.FlightDetails.FlightNumber,
    					   InputRoot.XMLNSC.Reservation.FlightDetails.FlightDate,
    					   InputRoot.XMLNSC.Reservation.ListOfPassengers.PassengerDetails[I].Class,
    					   resno);
    			-- report the reservation number in the output message
    			SET OutputRoot.XMLNSC.Reservation.ListOfPassengers.PassengerDetails[I].ReservationNumber = resno;
    			SET I = I + 1;
    		END WHILE;
    
    		-- update the sequence number in the database
    		UPDATE Database.XMLFLIGHTTB AS T
    			SET RESERVATIONSEQNO = Environment.Variables.RESERVATIONSEQNO; 
    		RETURN TRUE;
    	END;
    END MODULE;
    
    CREATE FILTER MODULE MultipleOrSingleMessage
    	CREATE FUNCTION Main() RETURNS BOOLEAN
    	BEGIN
    		IF Root.XMLNSC.Reservation.Request = 'M' THEN
    			RETURN TRUE;
    		END IF;
    		IF Root.XMLNSC.Reservation.Request = 'S' THEN
    			RETURN FALSE;
    		END IF;
    		RETURN UNKNOWN;
    	END;
    END MODULE;
    
    CREATE COMPUTE MODULE BuildSingleMessage
    	CREATE FUNCTION Main() RETURNS BOOLEAN
    	BEGIN
    		SET OutputRoot = InputRoot;
    		SET OutputRoot.XMLNSC.Reservation = NULL;
    		SET OutputRoot.XMLNSC.PassengerReservationResponse.ListOfConfirmations.ClassF.Confirmation[] =
    			(SELECT X.FirstName, X.LastName AS Surname, X.ReservationNumber
    				FROM InputRoot.XMLNSC.Reservation.ListOfPassengers.PassengerDetails[] AS X
    				WHERE UPPER(X.Class) = 'F');
    		SET OutputRoot.XMLNSC.PassengerReservationResponse.ListOfConfirmations.ClassY.Confirmation[] =
    			(SELECT X.FirstName, X.LastName AS Surname, X.ReservationNumber
    				FROM InputRoot.XMLNSC.Reservation.ListOfPassengers.PassengerDetails[] AS X
    				WHERE UPPER(X.Class) = 'Y');
    		RETURN TRUE;
    	END;
    END MODULE;
    
    CREATE COMPUTE MODULE PropagateMultipleMessages
    	CREATE FUNCTION Main() RETURNS BOOLEAN
    	BEGIN
    		DECLARE I INTEGER 1;
    		DECLARE J INTEGER Environment.Variables.NoPassengers;
    		WHILE I <= J DO
    			SET OutputRoot = InputRoot;
    			SET OutputRoot.XMLNSC.Reservation = NULL;
    			SET OutputRoot.XMLNSC.PassengerReservationResponse.ListOfConfirmations.Confirmation = 
    				InputRoot.XMLNSC.Reservation.ListOfPassengers.PassengerDetails[I];
    			PROPAGATE;
    			SET I = I + 1;
    		END WHILE;
    		RETURN FALSE; -- returning false stops automatic propagation
    	END;
    END MODULE;

     

  6. The ESQL uses the Environment tree to carry data. The second SET statement in the UpdateFlightTable ESQL module populates the Environment.Variables folder with the elements (data) extracted from the flight table (XMLFLIGHTTB). The names of the elements in the folder are inherited from the column names of the flight table (XMLFLIGHTTB). The statement generates the following Environment tree. For more information, see Accessing the environment tree in the WebSphere Message Broker documentation.
    (
       (0x1000000)Variables = (
          (0x3000000)FLIGHTDATE         = '20020220'
          (0x3000000)FLIGHTNO           = 'CA937'
          (0x3000000)ECONOMICCLASS      = 18
          (0x3000000)FIRSTCLASS         = 9
          (0x3000000)TOTALECONOMIC      = 200
          (0x3000000)TOTALFIRST         = 50
          (0x3000000)ECONOMICPRICE      = 200
          (0x3000000)FIRSTPRICE         = 300
          (0x3000000)STARTPOINT         = 'BEIJING       '
          (0x3000000)ENDPOINT           = 'LONDON        '
          (0x3000000)EconomyClassRemain = 182
          (0x3000000)FirstClassRemain   = 41
          (0x3000000)NoPassengers       = 3
       )
    )
    

    The UpdateFlightTable module uses the REFERENCE field dynamic reference and the MOVE statement (see the statements that begin DECLARE ref REFERENCE TO and While LASTMOVE(ref)) rather than the CARDINALITY statement to access repeating structures in the Message tree. Field reference variables are more efficient when accessing repeating structures.

    If CARDINALITY is used within a WHILE loop, it reduces the efficiency of the message flow. The overhead of using CARDINALITY in a loop increases because every time the CARDINALITY statement is run, it counts the number of instances in the array.

    This ESQL uses the Environment tree to carry data for the purposes of the Airline Reservations sample, which is not necessarily how you would achieve the result in a real business situation.

  7. Save the message flow.

You have created the XML_Reservation message flow, which reserves seats on a flight and builds reply messages to confirm that the reservations have been made.

Back to Building the Airline Reservations sample