Extending the capability of a Java message processing or output node

Within a message processing or output node, you can add extended functions to your Java™ node.

Before you begin

Read Creating a message processing or output node in Java.

About this task

Accessing ESQL

About this task

Nodes can invoke ESQL expressions using Compute node ESQL syntax. You can create and modify the components of the message using ESQL expressions, and you can refer to elements of both the input message and data from an external database.

The following procedure demonstrates how to use ESQL to control transactions from the evaluate method in your user-defined node:
  1. Set the name of the ODBC data source to use. For example:
    String dataSourceName = "myDataSource";
    
  2. Set the ESQL statement to run:
    String statement = 
       "SET OutputRoot.XMLNS.data = 
              (SELECT Field2 FROM Database.Table1 WHERE Field1 = 1);";
    
    Or, if you want to run a statement that returns no result:
    String statement = "PASSTHRU(
                            'INSERT INTO Database.Table1 VALUES(
                                 InputRoot.XMLNS.DataField1,
                                 InputRoot.XMLNS.DataField2)');";
    
  3. Select the transaction you want from the following types:
    MbSQLStatement.SQL_TRANSACTION_COMMIT
    Immediately commit the transaction after the ESQL statement has completed.
    MbSQLStatement.SQL_TRANSACTION_AUTO
    Commit the transaction when the message flow has completed. (Rollbacks are performed if necessary.)
    For example:
    int transactionType = MbSQLStatement.SQL_TRANSACTION_AUTO;
  4. Get the ESQL statement. For example:
    MbSQLStatement sql = 
           createSQLStatement(dataSourceName, statement, transactionType);
    
    You can use the method createSQLStatement(data source, statement to default the transaction type to MbSQLStatement.SQL_TRANSACTION_AUTO).
  5. Create the new message assembly to be propagated:
    MbMessageAssembly newAssembly = 
           new MbMessageAssembly(assembly, assembly.getMessage());
    
  6. Run the ESQL statement:
    sql.select(assembly, newAssembly);
    Or, if you want to run an ESQL statement that returns no result:
    sql.execute(assembly);
    

Interacting with databases

About this task

You can interact with databases from the Java code in your message processing node. The support that is provided is identical to the support for Java code that you write for the JavaCompute node; for details of the available options, and the advantages and restrictions that apply, see Interacting with databases by using the JavaCompute node.

Handling exceptions

About this task

Use the MbException class to catch and access exceptions. The MbException class returns an array of exception objects that represent the children of an exception in the integration node exception list. Each element returned specifies its exception type. An empty array is returned if an exception has no children. The following code sample shows an example of how you might use the MbException class in the evaluate method of your user-defined node.

public void evaluate(MbMessageAssembly assembly, MbInputTerminal inTerm) throws MbException
  {
    try
      {

        // plug-in functionality

      }
    catch(MbException ex)
      {
        traverse(ex, 0);

        throw ex; // if re-throwing, it must be the original exception that was caught
      }
  }

  void traverse(MbException ex, int level)
  {
    if(ex != null)
      {
        // Do whatever action here
        System.out.println("Level: " + level);
        System.out.println(ex.toString());
        System.out.println("traceText:  " + ex.getTraceText());

        // traverse the hierarchy
        MbException e[] = ex.getNestedExceptions();
        int size = e.length;
        for(int i = 0; i < size; i++)
          {
            traverse(e[i], level + 1);
          }
      }
  }

You can develop a user-defined message-processing or output node in such a way that it can access all current exceptions. For example, to catch database exceptions you can use the MbSQLStatement class. This class sets the value of the 'throwExceptionOnDatabaseError' attribute, which determines integration node behavior when it encounters a database error. When it is set to true, if an exception is thrown it can be caught and handled by the evaluate method in your user-defined extension.

The following code sample shows an example of how to use the MbSQLStatement class.

public void evaluate(MbMessageAssembly assembly, MbInputTerminal inTerm) throws MbException
  {
    MbMessage newMsg = new MbMessage(assembly.getMessage());
    MbMessageAssembly newAssembly = new MbMessageAssembly(assembly, newMsg);

    String table = 
       assembly.getMessage().getRootElement().getLastChild().getFirstChild().getName();

    MbSQLStatement state = createSQLStatement( "dbName", 
       "SET OutputRoot.XMLNS.integer[] = PASSTHRU('SELECT * FROM " + table + "');" );

    state.setThrowExceptionOnDatabaseError(false);
    state.setTreatWarningsAsErrors(true);

    state.select( assembly, newAssembly );

    int sqlCode = state.getSQLCode();
    if(sqlCode != 0)
      {
        // Do error handling here

        System.out.println("sqlCode = " + sqlCode);
        System.out.println("sqlNativeError = " + state.getSQLNativeError());
        System.out.println("sqlState = " + state.getSQLState());
        System.out.println("sqlErrorText = " + state.getSQLErrorText());
      }

    getOutputTerminal("out").propagate(newAssembly);
  }

Writing to an output device

About this task

To write to an output device, the logical (hierarchical) message must be converted back into a bit stream in your evaluate method. Use the getBuffer method in MbMessage to perform this task:


public void evaluate( MbMessageAssembly assembly, MbInputTerminal in)
                                                     throws MbException
{
  MbMessage msg = assembly.getMessage();
  byte[] bitstream = msg.getBuffer();

  // write the bitstream out somewhere
  writeBitstream( bitstream );   // user method

 }

Typically, for an output node the message is not propagated to any output terminal, therefore you can just return at this point.

You must use the supplied MQOutput node when writing to WebSphere® MQ queues, because the integration node internally maintains a WebSphere MQ connection and the open queue handles on a thread-by-thread basis. These handles are cached to optimize performance. In addition, the integration node handles exception scenarios when certain WebSphere MQ events occur, and this recovery is adversely affected if WebSphere MQ MQI calls are used in a user-defined output node.