Using Microsoft .NET in WebSphere Message Broker V8: Part 4: Using the .NETCompute node for exception handling

This series of four tutorials demonstrates the new support for Microsoft .NET in WebSphere Message Broker V8. Part 4 shows you how to use the .NETCompute node for exception handling, using a scenario that builds in complexity as additional exception conditions are deliberately produced and then handled. Readers should be familiar with either Microsoft .NET or WebSphere Message Broker, but need not be familiar with both.

Ben Thompson (bthomps@uk.ibm.com), Consulting IT Specialist, IBM

Author photoBen Thompson is a Consulting IT Specialist working on the WebSphere Message Broker development team at the IBM Hursley Software Lab in the UK. He is currently working on the design and implementation of .NET support in Message Broker. In the past, he has worked for IBM Software Services for WebSphere designing and implementing WebSphere solutions for IBM customers worldwide. You can contact Ben at bthomps@uk.ibm.com.


developerWorks Contributing author
        level

Matthew Golby-Kirk (mgk@uk.ibm.com), Software Developer, IBM

Matthew Golby-Kirk photoMatthew Golby-Kirk is a software developer working on the WebSphere Message Broker development team at the IBM Hursley Software Lab in the UK. He works on the design and implementation of the HTTP and Web services support, along with the ESQL language run time in WebSphere Message Broker. You can contact Matthew at mgk@uk.ibm.com.



22 February 2012

Before you start

IBM® WebSphere® Message Broker V8 (hereafter called Message Broker) provides the capability to integrate with existing Microsoft® .NET® Framework (hereafter called .NET) applications. You can do this integration by wiring the new Message Broker .NETCompute node into a message flow, or by calling a .NET application from an ESQL Compute node. This series of tutorials shows you how to use the .NETCompute node integration technique.

WebSphere Message Broker and Microsoft .NET

About this tutorial series

Youtube tutorial: Integrating Microsoft .NET code in a WebSphere Message Broker message flow

This five-minute youtube tutorial shows you how simple it is to use WebSphere Message Broker V8 to build a message flow that includes Microsoft .NET code. Microsoft Visual Studio is used to build .NET code in C#, which is then integrated into a message flow using Message Broker and an HTTP RESTful interface.

This series of four tutorials shows you how to write and build C# code in Microsoft Visual Studio 2010 (either Express Edition or Professional Edition) using an embedded template provided by WebSphere Message Broker Toolkit. The four tutorials explore the following topics:

  1. Using the .NETCompute node sample
  2. Using the .NETCompute node to integrate with Microsoft Word
  3. Using the .NETCompute node to integrate with Microsoft Excel
  4. Using the .NETCompute node for exception handling

About this tutorial

This tutorial describes a scenario that gradually builds in complexity as extra exception conditions are deliberately produced and then handled. You can use the .NETCompute node on Microsoft Windows brokers to construct output messages and to interact with .NET or Component Object Model (COM) applications.

WebSphere Message Broker enables you to host and run .NET code inside an execution group. The new .NETCompute node routes or transforms messages by using any Common Language Runtime (CLR) compliant .NET programming language, such as C#, Visual Basic (VB), F#, or C++/Common Language Infrastructure (CLI). This tutorial describes the new .NET API provided by WebSphere Message Broker, which enables .NET developers to interact with Message Broker's logical tree.

You can develop the .NET code in this tutorial in C# using Microsoft Visual Studio 2010 Professional Edition. The message flow development is done graphically using the WebSphere Message Broker Toolkit. To begin with, you start with a simple message flow to demonstrate how Broker exceptions are described and handled, and then gradually increase the complexity of the scenario to show some of the more advanced exception handling features of the .NETCompute node.

Prerequisites and system requirements

This tutorial is written for WebSphere Message Broker programmers who want to learn about the new .NETCompute node, and for .NET programmers who want to learn about using WebSphere Message Broker. If you have a general familiarity with C# or with Message Broker, then you should find the tutorial relatively easy to complete.

To build and execute the example in this tutorial, you will need:

  • A Windows installation that includes Microsoft .NET Framework V4
  • WebSphere Message Broker (Toolkit and Runtime) V8
  • Microsoft Visual Studio 2010 (Express Edition or Professional Edition) to write and build the required C# code

Generating a message flow exception

  1. Assuming that the WebSphere Message Broker Toolkit has not yet been started, from the Start menu, choose Start => Programs => IBM WebSphere Message Broker Toolkit => IBM WebSphere Message Broker Toolkit 8.0 => WebSphere Message Broker Toolkit 8.0. You will be asked for the location of a workspace -- the rest of this tutorial assumes that you are using C:\student\DOTNET\lab_exceptions\workspace.
  2. Close the Welcome screen and from your empty workspace, launch the Quick Start wizard: Click Start by creating an application as shown below in the red box. If you have chosen to use your existing workspace, you can also launch the Quick Start menu by clicking the New link at the top of the Broker Development view on the left:

    New application
  3. The Quick Start wizard requires an application name. Specify App_DotNet_Exceptions and click Finish:

    New Application wizard
  4. In the Application Development window, click New underneath the application you just created, and then on the pop-up New Artifact window, select Message Flow, as shown below:

    New Artifact popup
  5. In the New Message Flow wizard that opens, specify a Message Flow name of MyFlow, and then click Finish:

    NewFlow wizard
  6. The message flow will appear with an empty canvas. Create the contents of a simple message flow by dragging and dropping two nodes onto the flow canvas. Take an MQ Input node from the WebSphere MQ drawer, and a Throw node from the Construction drawer of the palette. Rename the MQ Input node DOTNET.EXCEPTIONS.IN and set the Basic property of Queue name to the same value. Wire the Out terminal of the MQ Input node to the In terminal of the Throw node. The resulting message flow should look like this:

    Flow design
    The Basic properties panel of the MQInput node, where the queue name is configured, should look like this:

    Basic Properties panel of MQInput node
  7. Configure the Throw node's basic property of Message text to a value such as This is a deliberate exception!:

    Throw node
  8. Save the message flow: Type Ctrl-S or select File => Save.
  9. To test the message flow, you need to define an input queue. Assuming that WebSphere Message Broker Explorer has not yet been started, from the Start menu, choose Start => Programs => IBM WebSphere Message Broker 8.0.0.0 => IBM WebSphere Message Broker Explorer. This tutorial assumes your user ID has permissions to administer WebSphere MQ. This tutorial also assumes that you have set up a runtime broker using the default configuration, which provides a message broker named MB8BROKER associated with a queue manager named MB8QMGR. For more information on the default configuration, see Creating the Default Configuration in the Message Broker information center. Right-click the Queues folder underneath the queue manager MB8QMGR and select New => Local Queue:

    Create queues
  10. In the New Local Queue wizard, specify the Name as DOTNET.EXCEPTIONS.IN and click Finish:

    New Local Queue Wizard
  11. For the purpose of the later examples, create another two queues using the same New Local Queue wizard. Name the queues DOTNET.EXCEPTIONS.CATCH and DOTNET.EXCEPTIONS.OUT. The Message Broker Explorer view of the queue manager should then look like this:

    Local queues
  12. Now return to the WebSphere Message Broker Toolkit and the message flow MyFlow that you constructed earlier. This simple example demonstrates what message flows do when they encounter an exception. The Throw node is a simple way for a flow developer to generate an exception. When an input message reaches the Throw node, an exception is created and the propagation flows backwards through the flow until the exception is caught. In this simple flow, the Catch terminal of the MQInput node has not been wired, so when the rollback occurs, the message is backed out to the input queue's backout queue if one exists, or placed on the queue manager's dead letter queue if one is defined. If neither of these options is possible, then the message is discarded if non-persistent, or left back on the input queue if persistent, and the exception is recorded in the Windows Application Log. To demonstrate this behaviour, right-click the MQInput node and select Test:

    Test message flow named MyFlow
  13. Click OK to confirm that you are happy to deploy the message flow within an application:

    Application deployment confirmation
  14. A test client file will be created named App_DotNet_Exceptions.mbtest. Type any input message (the text is not important) into the main box, then click Send Message in the bottom right corner:

    App_DotNet_Exceptions.mbtest
  15. The Select Deployment Location wizard opens. Keep the default settings and click Finish, as shown below:

    Select Deployment Location wizard
  16. After a few seconds, the message flow will deploy and the input message will be sent, exercising the flow:

    Result of Test 1
  17. Open the Windows Event Viewer and in the Application Log, you should see information messages showing the deployment that you just executed. Check the three most recent entries. The first error (BIP2628) shows the exception being caught at the MQInput after the flow rolled back. The information event (BIP3001) explains what caused the rollback (the deliberate exception thrown by the Throw node). The last error message (BIP2648) indicates that the backout threshold has been reached, and therefore the message will be discarded:

    Windows Event Log 1

This section of the tutorial showed a simple exception being deliberately thrown from a message flow. In the next section, you will catch this exception using the Catch terminal of the MQInput node, and then in later sections you will explore the .NETCompute node's ability to generate and catch exceptions.


Catching a message flow exception

  1. Return to MyFlow, which should still be open in the WebSphere Message Broker Toolkit. You will modify the message flow in order to catch the rollback, and then record the exception using a Trace node. Create a Trace node by dragging and dropping it onto the canvas from the Construction drawer of the palette and then wire it to the Catch terminal of the MQ Input node:

    MyFlow with Trace node Catch path

    The exception list tree is a logical message tree in which the message flow writes information about exceptions that occur when a message is processed. If an exception condition occurs, message processing is suspended and an exception is thrown. Control is passed back to a higher level -- that is, a Catch terminal or TryCatch node in the flow. Then an exception list is built to describe the failure condition, and the whole message, together with the local environment tree and the newly-populated exception list, is propagated through an exception-handling message flow path. In the case of this example message flow, the exception-handling message flow path is the one wired to the Catch terminal of the MQ Input node.
  2. Set the Trace node properties as shown below, so that the Root Message and ExceptionList structures are written to the file C:\student\DOTNET\lab_exceptions\trace.txt when the flow back is sent down the Catch branch of the message flow:

    Trace node properties
    Set the Destination property to File and the File path property to C:\student\DOTNET\lab_exceptions\trace.txt. The listing below provides the Pattern property to let you easily cut and paste the text:
    Listing 1. Text for the pattern property of the Trace node
    ===== ${CURRENT_TIMESTAMP} =====
    The Root of the message is:
    ${Root}
    The ExceptionList structure is:
    ${ExceptionList}

    Save the message flow: Type Ctrl-S or select File => Save.
  3. Retest the message flow: Return to the test client file that you created in the first section of the tutorial, named App_DotNet_Exceptions.mbtest. Right-click the Invoke Message Flow level of the hierarchy on the left and select Re-run:

    Test the Catch branch
  4. After the test has completed, the test client should look like the image below:

    Result of test 2
  5. Return to the Event Viewer, and you should see some Information messages about the successful redeploy that you just executed, except this time you should not see any error messages, because the flow has caught the exception and handled it by wiring it to the Trace node:

    Windows Event Log 2
  6. Use NotePad to open the trace file that the Trace node should have generated for you at C:\student\DOTNET\lab_exceptions\trace.txt. Check the ExceptionList structure, which contains the UserException generated by the Throw node generated. It should look like this:
    Listing 2. Trace of the ExceptionList recorded down the Catch branch:
    The ExceptionList structure is:
    ( ['MQROOT' : 0xd6bd4c0]
      (0x01000000:Name):UserException = (
        (0x03000000:NameValue):File     = 
           'F:\build\S000_P\src\DataFlowEngine\BasicNodes\ImbThrowNode.cpp' (CHARACTER)
        (0x03000000:NameValue):Line     = 265 (INTEGER)
        (0x03000000:NameValue):Function = 'ImbThrowNode::evaluate' (CHARACTER)
        (0x03000000:NameValue):Type     = 'ComIbmThrowNode' (CHARACTER)
        (0x03000000:NameValue):Name     = 'MyFlow#FCMComposite_1_2' (CHARACTER)
        (0x03000000:NameValue):Label    = 'MyFlow.Throw' (CHARACTER)
        (0x03000000:NameValue):Catalog  = 'BIPmsgs' (CHARACTER)
        (0x03000000:NameValue):Severity = 1 (INTEGER)
        (0x03000000:NameValue):Number   = 3001 (INTEGER)
        (0x03000000:NameValue):Text     = 'User exception thrown 
           by throw node' (CHARACTER)
        (0x01000000:Name     ):Insert   = (
          (0x03000000:NameValue):Type = 5 (INTEGER)
          (0x03000000:NameValue):Text = 'This is a deliberate exception!' (CHARACTER)
        )
      )
    )

This section of the tutorial introduced the Message Broker ExceptionList and shown that if a simple exception is caught and handled by a message flow, then no errors are written to the Windows Event Log. In the next section, you will use a .NETCompute node to catch and format an exception that has been routed to it from the Catch terminal of the MQInput node.


Using a .NETCompute node to handle a WebSphere Message Broker exception

  1. Amend the message flow MyFlow that you have been working with in the previous sections of the tutorial to include a .NETCompute node after the Trace node by dragging it from the Transformation drawer of the palette . The .NETCompute node API provides some methods that can interpret Message Broker exceptions, so that if you want to compose an exception for your own purposes, you can easily do so. Wire the Out terminal of the .NETCompute node to the In terminal of an MQ Output node by dragging it from the WebSphere MQ drawer of the palette. Rename the MQ Output node DOTNET.EXCEPTIONS.CATCH and set its Queue name property to the same value:

    MQ Output node Basic Properties
  2. Save the message flow, which should now look like this:

    MyFlow with .NETCompute node added

    Double-click the .NETCompute node, or right-click on it and select Open Microsoft Visual Studio.
  3. When Microsoft Visual Studio is launched, you will see the Start Page. Select New Project, as shown below:

    Microsoft Visual Studio Start Page
  4. Microsoft Visual Studio template extensions

    If the WebSphere Message Broker Toolkit is installed after Microsoft Visual Studio, then the broker's project templates will be automatically installed ready for you to use. However, if the Broker Toolkit is installed first, then you will need to manually install the templates by executing the file IBM.Broker.DotNet.vsix and stepping through the wizard. If you have used the default installation location, then you will find this file at C:\Program Files (x86)\IBM\WMBT800\wmbt.

    The New Project wizard provides three types of project templates in the Message Broker category. Select Project to create a Message Broker message. Specify the properties at the bottom of the New Project wizard, as listed beneath the image below, and Click OK:

    New Project wizard

    Name = ExceptionsDotNetProject
    Location = C:\student\DOTNET\lab_exceptions\visual studio 2010\Projects
    Solution Name = ExceptionsDotNetProject
  5. After the project is created, expand the Solution Explorer view. You should see that the CreateNode.cs file has been created to contain the C# class, and a reference to IBM.Broker.Plugin has been added. This assembly contains the helper methods from Message Broker to transform messages in a .NETCompute node:

    Solution Explorer references
  6. Locate the UserCode region of the CreateNode.cs file:

    UserCode region of CreateNode.cs
  7. Add the C# code in the listing below to the UserCode region:
    Listing 3. UserCode region demonstrating method CreateExceptionFromExceptionList:
    #region UserCode
    // Add user code in this region to create a new output message
    NBMessage inboundExceptionList = inputAssembly.ExceptionList;
    NBException exc = CreateExceptionFromExceptionList(inboundExceptionList);
    String pleasantExceptionMessage = exc.FormattedMessage(false); 
    NBElement outputXMLNSC = 
        outputRoot.CreateLastChildUsingNewParser(NBParsers.XMLNSC.ParserName);
    NBElement field = outputXMLNSC.CreateFirstChild("Message").CreateFirstChild("Field");
    field.CreateFirstChild(NBParsers.XMLNSC.AsIsElementContent, 
            "", pleasantExceptionMessage);
    #endregion UserCode

    XML development note

    The NBElement in the logical tree that holds the formatted message as a string value is assigned an XMLNSC type called AsIsElementContent. When the output node uses the XMLNSC writer to serialise the logical tree and convert it to an output message bitstream, it informs the writer not to carry out XML entity substitution. This technique makes the output readable and avoids XML entities in the output message. This should only be necessary in situations where you are trying to include XML reserved characters within the output of an XML message. The example includes this because it is the easiest way to render the error message with apostrophes in its text as readable XML output.

    The above code begins by navigating to the ExceptionList structure, which you have already examined using the Trace node, and which is passed into the .NETCompute node as part of the Input Message Assembly (logical tree hierarchy). The method CreateExceptionFromExceptionList converts the hierarchical ExceptionList tree structure into an NBException object, which provides a method named FormattedMessage, which re-inflates the object into a readable exception in which all message inserts have been reinserted. In the example, this nicely formatted message is then copied into the output message structure by the .NETCompute node.
  8. With the Visual Studio development work complete, the next step is to build an assembly file that you will reference from the .NETCompute node. From Solution Explorer, right click on the Solution and select Build Solution: Build ExceptionsDotNetProject

    How to open the Output window in Microsoft Visual Studio

    If the Output window is not visible in Microsoft Visual Studio Professional Edition, select Debug => Windows => Output. If the Output window is not visible in Microsoft Visual Studio Express Edition, select View => Output.

  9. The Output window will show you where the built assembly file has been saved on your file system. Depending on how you have Microsoft Visual Studio configured, the Build Output window may not be visible -- if it is not, follow the instructions in the sidebar. Build Output
    If you have used the default naming suggested throughout the tutorial, the assembly file should have been saved at:
    C:\student\DOTNET\lab_exceptions\visual studio 2010\Projects\ExceptionsDotNetProject\
    ExceptionsDotNetProject\bin\Debug\ExceptionsDotNetProject.dll

    Copy this location, as you will use it to configure the .NETCompute node in the next step.
  10. Return to WebSphere Message Broker Toolkit and configure the Assembly Name property of the .NETCompute node by pasting it from the previous instruction:

    Configure .NETCompute node
  11. Save the message flow: Type Ctrl-S or select File => Save.
  12. Return to the open test client file App_DotNet_Exceptions.mbtest, right click the Invoke Message Flow level in the hierarchy on the panel on the left, and select Re-run. The flow should be redeployed and the same message will be sent to the input queue again. This time, you should see an output message appear on the queue named DOTNET.EXCEPTIONS.CATCH:

    Result of Test 3
  13. Examine the output message and note in particular that the exception text should be nicely formatted in the Field element of the output XML message, which should look like this:
    Listing 4. Output message formatted using .NETCompute node method FormattedMessage
    <Message>
    <Field>( MB8BROKER.default ) Exception thrown by throw node 
    'DotNetExceptions.Throw'; text is 'This is a deliberate exception!'. 
    The throw node 'DotNetExceptions.Throw' has received a message and thus has thrown 
    an exception as this is its normal behavior.  The message text associated with this
    exception is 'This is a deliberate exception!'. Since this is application-generated
    (by message flow behavior), the user action is determined by the message flow 
    and the type of exception generated.</Field></Message>

Catching an exception when using the Propagate method in a .NETCompute node

  1. So far you have seen that the WebSphere Message Broker .NETCompute node API provides some methods to easily convert between the way that Message Broker reports exceptions (using the Exception List tree structure) and the more user-friendly formatted text messages for inclusion in output data. You can now extend the scenario by using a .NETCompute node to catch exceptions in the node during a rollback, which avoids having to catch exceptions using an explicit Catch branch in the flow. In WebSphere Message Broker Toolkit, return to the previously created message flow named MyFlow and insert another .NETCompute node between the MQInput node and the Throw node. Wire the Out terminal of the MQ Input node to the In terminal of the new .NETCompute node, and wire the Out terminal of the new .NETCompute node to the In terminal of the Throw node. Here is what the message flow should look like:

    Editted flow MyFlow
  2. Right-click .NETCompute1 (the new name for the .NETCompute node) and select Add Output Terminal:

    Add Output Terminal
  3. A pop-up window will ask you to name the new terminal. Specify Alternate:

    Name the new Output Terminal
  4. Add a second Trace node to the message flow from the Construction drawer of the palette and wire it between the Alternate terminal of the .NETCompute1 node (which you just created) and the In terminal of the existing MQ Output node:

    MyFlow with additional trace node added
  5. Set the Properties of the new Trace node as shown below:

    Node Trace1's properties
    Set the Destination property to File and the File path property to C:\student\DOTNET\lab_exceptions\trace1.txt. The listing below provides the Pattern property so that you can easily cut and paste the text:
    Listing 5. Text for the pattern property of the Trace node
    ===== ${CURRENT_TIMESTAMP} =====
    The Root of the message is:
    ${Root}
    The ExceptionList structure is:
    ${ExceptionList}
  6. Save the message flow: Type Ctrl-S or select File => Save. At this stage, the message flow should look like the image below. The red cross on the node .NETCompute1 indicates that a .NET assembly has not yet been assigned to the node.

    Saved message flow MyFlow
  7. Switch windows to Microsoft Visual Studio, which should still have the project named ExceptionsDotNetProject open. Expand the Solution Explorer view, right-click on the ExceptionsDotNetProject level in the hierarchy, and from the menu select Add => Class:

    Solution Explorer Add Class menu
  8. In the dialog, select the Message Broker template named Class to Create a Message Broker message, keep the suggested name of CreateNode1.cs, and click OK:

    Add Class dialog
  9. In the generated class CreateNode1.cs, at the beginning of the Evaluate method, and after the declaration of the NBOutputTerminal object that represents the node's Out terminal, add a new declaration for the Alternate output terminal that you added to the message flow node. The C# code is shown below with the new line in bold:
    Listing 6. Code extract for the declaration of the Alternate output terminal
    public override void Evaluate(NBMessageAssembly inputAssembly)
    {
        NBOutputTerminal outTerminal = OutputTerminal("Out");
        NBOutputTerminal altTerminal = OutputTerminal("Alternate");
        NBMessage inputMessage = inputAssembly.Message;
        .....

    This NBOutputTerminal object will be used below when you send a message out of the .NETCompute1 node in the circumstances where the node has caught a downstream exception.
  10. Edit the UserCode region of the class CreateNode1.cs using the code in the listing below. This snippet of C# simply copies the body of the input message to the output message assembly:
    Listing 7. Code extract for the UserCode region
    #region UserCode
    // Add user code in this region to create a new output message 
    // Copy the input message to the output
    outputRoot.AddLastChild(inputRoot.LastChild);
    #endregion UserCode
  11. Beneath the UserCode region, you will find a line of code responsible for sending the output message assembly out of the .NETCompute node to the Output terminal. By default, this code will look like this:
    Listing 8. Propagation code before editing
    // Change the following if not propagating message to the 'Out' terminal
    outTerminal.Propagate(outAssembly);

    Surround this code with a Catch block, so that if an exception occurs on the message flow thread that executes the Propagate (including subsequent message flow logic downstream of this point in the message flow), then it will be caught in .NETCompute1, rather than being rewound further back to the MQ Input node. Use the replacement code below (remove the two lines above and put the code below in its place), and you will see that if an exception is caught, the C# code will generate a description from the exception (the code uses the FormattedMessage method if the exception is a Broker exception type). An output message is built containing this description and then propagated to the Alternate terminal of the node:
    Listing 9. Propagation code after editing
    try
    {
        outTerminal.Propagate(outAssembly);
    }
    catch (NBBrokerException downstreamBrokerException)
    {
        outputRoot.LastChild.Delete();
        // The NBBrokerException which is caught here could contain CLR exceptions
        // e.g. If a .NETCompute node were responsible for the downstream throw.
        // So, to bullet proof this code, we use GetBaseException and then: 
        //   If we have an NBRecoverableException, use method FormattedMessage 
        //   If we have a non-Broker exception, use method ToString
        Exception exc = downstreamBrokerException.InnerException.GetBaseException();
        NBRecoverableException nbrecov = exc as NBRecoverableException;
        String pleasantExceptionMessage;
        if (nbrecov != null )
        { 
            pleasantExceptionMessage = nbrecov.FormattedMessage(false);
        }
        else
        {
            pleasantExceptionMessage = exc.ToString();
        }
        // Create an output message which contains the exception information
        NBElement outputXMLNSC =
            outputRoot.CreateLastChildUsingNewParser(NBParsers.XMLNSC.ParserName);
        NBElement field = 
            outputXMLNSC.CreateFirstChild("Message").CreateFirstChild("Field");
        field.CreateFirstChild(NBParsers.XMLNSC.AsIsElementContent, 
            "", pleasantExceptionMessage);
        // Propagate the message to the Alternate output terminal
        altTerminal.Propagate(outAssembly);
    }

    The block that catches downstream problems with the Propagate method deliberately catches NBBrokerException and not NBException, which is at a higher level in the Message Broker exception hierarchy and can include fatal exceptions that should not be caught within a flow developer's code. The Broker exception hierarchy is shown below. NBBrokerException is a special wrapper exception designed to catch exceptions from downstream nodes that will successfully catch all other types of downstream exceptions on which a flow developer might want to take action.

    Message Broker exception inheritance hierarchy
  12. With the Visual Studio development work complete, build an assembly file containing the two classes -- the one you created earlier in the tutorial and the one you just wrote -- which will be referenced from the .NETCompute nodes in the message flow. From Solution Explorer, right-click on the Solution and select Build Solution:

    Build solution containing two classes
    At this stage, if you happen to have the Windows Event Log open, you will notice a hot swap deploy error for the first .NETCompute node in the flow. This error occurs because the assembly now contains two classes, and the node has not yet been configured to nominate which of the two classes it should use. You will put this right in the next instruction, but don't be alarmed if you see the hot swap deploy error in the Event Log.
  13. Return to Message Broker Toolkit and the message flow MyFlow. Now that the assembly contains two classes (one for each .NETCompute node), you must tell each .NETCompute node in the flow which class to use:

    Edit the Basic properties of the node .NETCompute1:

    Assembly name = C:\student\DOTNET\lab_exceptions\visual studio 2010\Projects\ExceptionsDotNetProject\ ExceptionsDotNetProject\bin\Debug\ExceptionsDotNetProject.dll
    Class name = ExceptionsDotNetProject.CreateNode1

    Basic properties of node .NETCompute1

    Edit the Basic properties of the node .NETCompute:

    Assembly name = C:\student\DOTNET\lab_exceptions\visual studio 2010\Projects\ExceptionsDotNetProject\ ExceptionsDotNetProject\bin\Debug\ExceptionsDotNetProject.dll
    Class name = ExceptionsDotNetProject.CreateNode

    Basic properties of node .NETCompute
  14. Save the message flow, return to the open test client, right-click the Invoke Message Flow level in the hierarchy on the panel on th left, and select Re-run. The flow should be redeployed and the same Hello World! message will be sent to the input queue again:

    Invoking the Test client
  15. The output message from the test should appear on the output queue DOTNET.EXCEPTIONS.CATCH, and should have the same message content as the last test, except that this time the route followed through the flow will be slightly different. The image below shows that the rollback does not go all the way back to the MQ Input node. The input message follows the path of the blue arrow (A), and on reaching the Throw node, a rollback (red arrow B) occurs which is then caught by the node .NETCompute1. The output message is then propagated down the path of the green arrow (C):

    Flow paths
  16. To check that the message was directed along the paths shown above and through the new trace node Trace1, make sure that there is now a second trace file, Trace1.txt, in the directory C:\student\DOTNET\lab_exceptions:

    Trace output file
  17. Open the trace file Trace1.txt and you should find it contains a trace of the XML exception message generated by the .NETCompute1 node. Check the body of the message, and extract of which is shown below:
    Listing 10. Extract from trace file Trace1.txt
    (0x01000000:Folder):XMLNSC = ( ['xmlnsc' : 0xd4c37a0]
      (0x01000000:Folder):Message = (
        (0x01000000:Folder):Field = (
          (0x03000600:AsisElementContent): = '( MB8BROKER.default ) Exception 
          thrown by throw node 'MyFlow.Throw'; text is 'This is a deliberate 
          exception!'. The throw node 'MyFlow.Throw' has received a message 
          and thus has thrown an exception as this is its normal behavior. 
          The message text associated with this exception is 'This is a 
          deliberate exception!'. Since this is application generated (by 
          message flow behavior), the user action is determined by the 
          message flow and the type of exception generated. ' (CHARACTER)
        )
      )
    )

Catching a real-life WebSphere MQ exception

  1. You can easily extend the previous example to show a more complex and realistic exception tree being caught and navigated. Up to this point, you have only considered artificial exceptions produced by a Throw node. Substitute an MQ Output node in the place of the Throw node, but do not configure its Queue name property. Rename the MQ Output node NO QUEUE. Resave the message flow, and you should see a yellow warning triangle on the corner of the node indicating that the Queue name has not been configured:

    Amended MyFlow with the MQ Output node named NO QUEUE
  2. As you have done a few times now, return to the open test client, right-click the Invoke Message Flow level in the hierarchy on the panel on the left, and select Re-run. The flow should be redeployed and the message sent to the input queue again. This time a new exception should be recorded in the output message written to the queue named DOTNET.EXCEPTIONS.CATCH. The red box below shows the beginning of the new exception. The full message is displayed in the listing that follows the image:

    Result of Test 4
    Listing 11. Output message describing the WebSphere MQ exception, caught after rollback to .NETCompute1
    <Message>
    <Field>( MB8BROKER.default ) An error occurred in node 'DotNetExceptions.NO QUEUE'
    when opening queue '' on queue manager ''. State = '-1' 'MQW101' '2085' ''   An    
    error occurred when a message flow node attempted to open a queue. The reason code 
    from the MQOPEN is displayed as the 3rd (native error) state. Check the WebSphere MQ 
    completion and reason codes in the WebSphere MQ Application Programming Reference
    to establish the cause of the error, taking any appropriate action. You may have to 
    restart the message broker after you have performed this recovery action.</Field>
    </Message>
  3. The exception generated in this example has more levels of nesting, and more inserts than the earlier simple Throw example. The broker exception list from this example, which the .NETCompute node navigates and then inflates to produce the above output message, is shown below:

    Exception List showing MQ Exception
    This image shows that the .NETCompute node's use of the method GetBaseException to walk down to the lowest exception in the tree hierarchy has navigated to the exception that contains the root cause of the problem. Typically for Message Broker, this will always be at the most nested part of the exception list. In this example, this root cause is Message Broker exception BIP2666. This example also demonstrates the real power of the FormattedMessage method that the Broker provides, as it reconstructs a human-readable message containing all required inserts.

Catching a CLR exception in a .NETCompute node

  1. This section of the tutorial demonstrates that .NETCompute nodes can also throw standard CLR Exceptions. These exceptions can also be caught and navigated using .NETCompute nodes. Separate .NETCompute nodes can also exist in distinct application domains, and exceptions thrown by CLR code running in one application domain can then be caught by CLR code running in a different application domain (assuming that the class defining the exception is available to both application domains). You will modify the existing message flow to achieve these aims, but first write some more C# code in a new Microsoft Visual Studio project. If you have followed the previous examples, then Visual Studio should already be running. Save and close the existing open solution, and then create a new project by selecting File => New Project:

    New Project
  2. The New Project wizard offers you the three types of Message Broker Project templates. Select the one named Project to create a Message Broker message, specify the properties at the bottom of the window as follows, and then Click OK:

    Name = ExceptionsDotNetProject2
    Location = C:\student\DOTNET\lab_exceptions\visual studio 2010\Projects
    Solution Name = ExceptionsDotNetProject2

    New Project wizard
  3. After the project is created, the class CreateNode.cs will be open in Visual Studio. Locate the UserCode region and add the lines of C# shown in the listing beneath the image below:

    UserCode region of CreateNode.cs
    Listing 12. C# code to be used in the UserCode region of CreateNode.cs
    #region UserCode
    // Add user code in this region to create a new output message
    // Force a NullReferenceException 
    String test = null;
    int len = test.Length;
    #endregion UserCode

    The purpose of this code is to cause a common CLR exception to be thrown, which you will catch when it is rolled back to the previous .NETCompute node running in the message flow. The two .NETCompute nodes will run their code in different .NET application domains.
  4. Save CreateNode.cs by selecting File => Save All. Build the assembly: right-click the ExceptionsDotNetProject2 level in the hierarchy of Solution Explorer and click Build Solution:

    Build Solution
  5. Switch back to Message Broker Toolkit and edit the same message flow named MyFlow that you have been using throughout this tutorial. This time, delete the MQ Output node named NO QUEUE and in its place drag and drop a .NETCompute node from the Transformation drawer of the palette onto the message flow canvas. Wire the node into the flow as shown below:

    Redesigned message flow MyFlow
  6. Edit the Basic properties of the node .NETCompute2:

    Assembly name = C:\student\DOTNET\lab_exceptions\visual studio 2010\Projects\ExceptionsDotNetProject2\ ExceptionsDotNetProject2\bin\Debug\ExceptionsDotNetProject2.dll
    Class name = ExceptionsDotNetProject2.CreateNode

    Basic properties of node .NETCompute2
  7. Switch to the Advanced tab of .NETCompute2, and set the AppDomain name to NewAppDomain. When this property is left blank on a .NETCompute node, the Broker runs the code in an application domain with the same name as the execution group or the Message Broker application in which it is deployed (depending on whether it is deployed as a standalone flow, or within an application). However, when a value is specified for the AppDomain property, then this is the name of the application domain in which the node's CLR code will run:

    Advanced properties of node .NETCompute2
  8. Save the message flow, return to the open test client, right-click the Invoke Message Flow level in the hierarchy on the panel on the left, and click Re-run. The flow should be redeployed and the same Hello World! message will be sent to the input queue again.

    Result of Test 5
    This time the output message that is caught contains the CLR NullReferenceException, which was thrown from the node .NETCompute2. Here is the full output message:

    Output message generated displaying CLR exception
  9. The exception list used by the Message Broker to carry the information about the CLR exception when the flow rollback occurs contains all detailed information a flow developer might need to understand where the exception was thrown and what the problem was. For this tutorial, you don't need to record the contents of this exception list, but an extract is included below just to show that the information it contains also describes the CLR exception. The red box below shows that the application domain in which the code was executing is also included. In your example, the id will probably be a different number:
    Extract of the Broker exception list generated when a CLR exception causes a flow rollback
  10. You can also use the Message Broker command console to display information about the application domains that an execution group contains, by using the mqsireportproperties command:
    Listing 13. mqsireportproperties command to display application domain information
    mqsireportproperties MB8BROKER -e default -o ComIbmAppDomainDirector -r

    The output from the command lists the application domains supported by the Message Broker execution group. The image below has highlighted the output for the application domain named NewAppDomain using a red box. The second red box shows all the assemblies loaded in this application domain:

    Application domain information output from mqsireportproperties

This section of the tutorial showed you how to catch a CLR exception using a .NETCompute node, even if the .NETCompute node in which the exception is thrown is running in a different application domain from the .NETCompute node in which the exception is caught. The next section shows you how to use Message Broker to execute hot-swap deploys.


Hot swap deploy of a .NETCompute node assembly

In the tutorial so far, you have been developing and editing a message flow that has undergone several changes. Each time the flow was altered, you retested it using the Message Broker Toolkit's built-in test client, which deploys the new message flow and then sends a test message through the flow. Whilst doing this, you may have noticed a few seconds delay at the beginning of each test as the Broker packaged and then deployed the flow. To reduce the number of flow redeploys, Message Broker also includes a Hot Swap deploy feature for .NET code written for execution in a .NETCompute node. It speeds up development when writing .NET code for use in Message Broker. When you edit and rebuild a .NET assembly using Microsoft Visual Studio, the assembly file is resaved on the file system. The Broker's execution group has a file watcher that notices this change and then reloads all application domains that use the assembly, so that you don't have to rebuild your .NET code and then redeploy their message flow. Only the first step is required and Hot Swap ensures that the changes are picked up by the Broker. To demonstrate this handy feature, you will create a new message flow that contains a .NETCompute node. Before starting, save and close any open files in Message Broker Toolkit from previous sections of the tutorial.

  1. This scenario will reuse the same queues that you have already created, so begin by removing anything deployed to the default runtime Broker configuration. In the Message Broker Toolkit Brokers view, right-click the execution group default and choose Delete => All Flows and Resources:

    Delete All Flows and Resources
  2. From the Quick Start panel, select Start by creating an application, as shown below:

    Quick Starts Panel
  3. In the resulting wizard, specify an application name of App_DotNet_HotSwap and click Finish:

    Quick Starts Panel
  4. Click New underneath the application that has been created, and in the resulting pop-up window, click Message Flow:

    New Message Flow
  5. Specify a Message Flow name of MyFlow and click Finish:

    New Message Flow Wizard
  6. The Broker message flow you will use to demonstrate the Hot Swap feature is simple. On the flow canvas, drag and drop an MQ Input node and MQ Output node from the WebSphere MQ drawer of the flow palette, and a .NETCompute node from the Transformation drawer of the flow palette. Rename the MQ Input node DOTNET.EXCEPTIONS.IN and rename the MQ Output node DOTNET.EXCEPTIONS.OUT.

    On the MQ Input node Basic properties panel, configure the Queue name to be DOTNET.EXCEPTIONS.IN
    On the MQ Input node Input Message Parsing properties panel, configure the Message domain to be XMLNSC
    On the MQ Output node Basic properties panel, configure the Queue name to be DOTNET.EXCEPTIONS.OUT

    Wire the nodes as shown below and save the message flow: Type Ctrl-S or select File => Save. There will be an error against the .NETCompute node until you configure its assembly:

    Message Flow MyFlow in application App_DotNet_HotSwap
  7. Right-click the .NETCompute node and select Open Microsoft Visual Studio:

    Open Microsoft Visual Studio
  8. When Microsoft Visual Studio is launched, you will see the Start Page. Select New Project, as shown below:

    Microsoft Visual Studio Start Page
  9. The New Project wizard offers three types of project templates in the Message Broker category. Select Project to create a Message Broker message, specify the properties at the bottom of the window as follows, and Click OK:

    Name = HotSwapDotNetProject
    Location = C:\student\DOTNET\lab_exceptions\visual studio 2010\Projects
    Solution Name = HotSwapDotNetProject

    New Project wizard
  10. Edit the UserCode region of the class CreateNode.cs using the code in the listing below. This snippet of C# navigates to an input field, which is expected to contain an integer value. This value has 42 added to it, and is then placed into a field in the output message. Before examining the hot swap capability, we will demonstrate how the catch block of the code works by deliberately sending in some data that contains a string rather than an integer. The string causes a Broker exception of the type NBRecoverableException to be thrown. The logic in the catch branch then re-throws an NBUserException. When you throw this kind of exception in a message flow, the Broker inserts an entry into the Windows Event Log so that you can decide what information to include in the exception. Further context information can be added that would not be available had the original NBRecoverableException not been caught. For example, this scenario includes a serialised copy of the input message as an insert in the log entry. Copy the code below into the UserCode region of CreateNode.cs:
    Listing 14. Code extract for the UserCode region
    #region UserCode
    // Add user code in this region to create a new output message
    try 
    {
      NBElement inputXMLNSC = inputRoot[NBParsers.XMLNSC.ParserName];
      NBElement outputXMLNSC =
        outputRoot.CreateLastChildUsingNewParser(NBParsers.XMLNSC.ParserName);
      NBElement message = outputXMLNSC.CreateFirstChild("Message");
      NBElement field = message.CreateFirstChild("","Field");
      field.SetValue(inputXMLNSC["Message"]["Field"].GetInt32() + 42);
    } 
    catch (NBRecoverableException nbrecov)
    {
     byte[] serialisedInput = inputRoot[NBParsers.XMLNSC.ParserName].AsBitStream(0,1208);
     NBUserException nbuser = new NBUserException("User generated exception",
        7522,
        NBSeverity.Warning,
        nbrecov,
        Encoding.UTF8.GetString(serialisedInput));
     nbuser.MessageAsFirstInsert = true;
     throw nbuser;
    }
    #endregion UserCode
  11. Save CreateNode.cs by typing Ctrl-S and build the assembly from the right-click menu in the Solution Explorer:

    Build Solution
  12. If you have followed the default naming suggested, then the assembly will have been saved to the file:
    C:\student\DOTNET\lab_exceptions\visualstudio 2010\Projects\HotSwapDotNetProject\
    HotSwapDotNetProject\bin\Debug\HotSwapDotNetProject.dll

    . Return to the Message Broker Toolkit and open a Windows Explorer window in front of the message flow you constructed earlier. Drag and drop the assembly HotSwapDotNetProject.dll on top of the .NETCompute node:

    Drag and Drop HotSwapDotNetProject.dll
    This action will configure the Assembly name property of the .NETCompute node:

    Assembly name property of .NETCompute node
  13. Save the message flow: Type Ctrl-S or select File => Save.
  14. Deploy the application: Drag and drop App_DotNet_HotSwap onto the default execution group of the default broker configuration, as shown below:

    Deploy application App_DotNet_HotSwap
  15. Once the deployment completes, switch to Message Broker Explorer to send a test message into the flow. Right-click the input queue DOTNET.EXCEPTIONS.IN and click Put test message:

    Put test message
  16. In the resulting dialog, paste the simple input message in the listing below and click Put message:
    Listing 15. Example XML input message for the scenario
    <Message><Field>1</Field></Message>
    Put test message
  17. Open the Windows Event Log and you should see that several errors have been placed there by the Broker. A BIP2328 error message indicates that the .NETCompute node found A value of SQL datatype ''CHARACTER'' encountered when datatype ''INTEGER'' expected.. The input data was an XML message that was parsed by the Broker without the use of an XML schema, so all elements were interpreted as containing character data. The .NETCompute node then tried to use the GetInt32 method, causing the BIP2328 error because a character was encountered when an integer was expected. You will also find a BIP7522 error message in the Event Log due to the catch block throwing an NBUserException. The inserts in this message include a serialised copy of the input message:

    Windows Event Log
  18. Having demonstrated this deliberate exception, you will now see how to use the Broker to hot swap the .NET assembly, without the need to redeploy the message flow itself. Return to the Microsoft Visual Studio and edit the line of code in the UserCode region of CreateNode.cs that tries to do the numeric addition on the input field in the message. This line of code containing the mistake is shown in the listing below, followed by a line with the corrected code.
    Listing 16. Line of code in UserCode region of CreateNode.cs, with error line and corrected line
    field.SetValue(inputXMLNSC["Message"]["Field"].GetInt32() + 42);
    
    field.SetValue( ((int)inputXMLNSC["Message"]["Field"]) + 42);
  19. After fixing the code, save CreateNode.cs, and then click Rebuild Solution in the Solution Explorer:

    Rebuild solution
  20. Within a few seconds of rebuilding this code, Message Broker should detect that the assembly has been altered. Switch back to the Windows Event Log and you should find that a new entry for BIP7451. This informational message says that a hot swap has occurred and that the application domain has been reloaded:

    Windows Event Log hot swap entry
  21. Return to Message Broker Explorer and the Put Test Message dialog should still be open. Use the same input message as the previous test. Copy the message text from the listing below, paste it into the Message data box, and click Put message:
    Listing 17. Example XML input message for the scenario
    <Message><Field>1</Field></Message>
    Put test message
  22. This time, the corrected code should run successfully and a message should be written to the output queue DOTNET.EXCEPTIONS.OUT. Close the Put message dialog by clicking Close, and then click on the queue DOTNET.EXCEPTIONS.OUT. Press F5 to refresh the display, and you should see that the Current queue depth now has the value 1, as shown below:

    Current queue depth
  23. Right-click the queue and click Browse messages:

    Current queue depth
  24. The Message Browser should show that the output message carries a field containing the value 43, as shown below:

    Message browser

Congratulations -- you have completed Part 4 of this four-part tutorial series, which has demonstrated the range of the WebSphere Message Broker exception handling and hot swap features available with the .NETCompute node. You can continue on to the resource links and author information by clicking Next below, or you can return to Parts 1, 2, or 3 of the tutorial series.

Resources

  • WebSphere Message Broker resources
  • WebSphere resources
    • developerWorks WebSphere developer resources
      Technical information and resources for developers who use WebSphere products. developerWorks WebSphere provides product downloads, how-to information, support resources, and a free technical library of more than 2000 technical articles, tutorials, best practices, IBM Redbooks, and online product manuals.
    • developerWorks WebSphere application integration developer resources
      How-to articles, downloads, tutorials, education, product info, and other resources to help you build WebSphere application integration and business integration solutions.
    • Most popular WebSphere trial downloads
      No-charge trial downloads for key WebSphere products.
    • WebSphere forums
      Product-specific forums where you can get answers to your technical questions and share your expertise with other WebSphere users.
    • WebSphere on-demand demos
      Download and watch these self-running demos, and learn how WebSphere products and technologies can help your company respond to the rapidly changing and increasingly complex business environment.
    • developerWorks WebSphere weekly newsletter
      The developerWorks newsletter gives you the latest articles and information only on those topics that interest you. In addition to WebSphere, you can select from Java, Linux, Open source, Rational, SOA, Web services, and other topics. Subscribe now and design your custom mailing.
    • WebSphere-related books from IBM Press
      Convenient online ordering through Barnes & Noble.
    • WebSphere-related events
      Conferences, trade shows, Webcasts, and other events around the world of interest to WebSphere developers.
  • developerWorks resources
    • Trial downloads for IBM software products
      No-charge trial downloads for selected IBM® DB2®, Lotus®, Rational®, Tivoli®, and WebSphere® products.
    • developerWorks blogs
      Join a conversation with developerWorks users and authors, and IBM editors and developers.
    • developerWorks cloud computing resources
      Access the IBM or Amazon EC2 cloud, test an IBM cloud computing product in a sandbox, see demos of cloud computing products and services, read cloud articles, and access other cloud resources.
    • developerWorks tech briefings
      Free technical sessions by IBM experts to accelerate your learning curve and help you succeed in your most challenging software projects. Sessions range from one-hour virtual briefings to half-day and full-day live sessions in cities worldwide.
    • developerWorks podcasts
      Listen to interesting and offbeat interviews and discussions with software innovators.
    • developerWorks on Twitter
      Check out recent Twitter messages and URLs.
    • IBM Education Assistant
      A collection of multimedia educational modules that will help you better understand IBM software products and use them more effectively to meet your business requirements.

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=795296
ArticleTitle=Using Microsoft .NET in WebSphere Message Broker V8: Part 4: Using the .NETCompute node for exception handling
publish-date=02222012