Introducing the WebSphere sMash PHPCompute node in WebSphere Message Broker

The PHPCompute node is a new general-purpose programmable node in IBM® WebSphere® Message Broker that embeds the IBM WebSphere sMash runtime for PHP. This article shows how you can use the PHPCompute node to write PHP scripts that transform and route messages in WebSphere Message Broker. You will then be able to expand your use of the PHPCompute node to many more tasks that will help you solve problems and increase productivity. This content is part of the IBM WebSphere Developer Technical Journal.

Ant Phillips, Software Developer, IBM

Ant Phillips is a Software Developer in IBM's Java Technology Centre in Hursley, United Kingdom. His current focus is on WebSphere sMash, a simple environment for creating dynamic Web applications. Before joining IBM, Ant was the technical lead at an innovative startup based in Newbury, UK. In previous lives, Ant worked for Sony® and Microsoft® and thoroughly enjoyed visiting Tokyo, Seattle, and several places in between. In his spare time, he plays as much sport as his wife and two children let him get away with.



Andrew Coleman (andrew_coleman@uk.ibm.com), Advisory Software Engineer, IBM

Andrew Coleman is an Advisory Software Engineer on the WebSphere Message Broker Development Team at the IBM Hursley Software Lab in the UK. He has been responsible for key areas of broker development for eight years, including the Java UDN API, the JavaCompute node, and the Collector node. You can contact Andrew at andrew_coleman@uk.ibm.com.



08 April 2009

Also available in

Introduction

IBM® WebSphere® Message Broker (hereafter called Message Broker) enables business information to flow between disparate applications across multiple hardware and software platforms. Business rules can be applied to the data flowing through Message Broker to route and transform the information.

IBM WebSphere sMash is an agile Web application platform for developing and running modern Web applications. WebSphere sMash introduces a simple environment for creating, assembling, and running applications based on popular Web technologies, such as Groovy, PHP, Java™, REST services, rich Ajax Web user interfaces, integration mash-ups, and others.

IBM WebSphere sMash and IBM WebSphere sMash Developer Edition are based on the acclaimed Project Zero incubator project. Project Zero is the development community for WebSphere sMash and will continue to offer developers a cost-free platform for developing applications with the latest builds, the latest features, and the support of the community.

The PHPCompute node is a new general-purpose programmable node in Message Broker that embeds the WebSphere sMash runtime for PHP, which is an implementation of the PHP language that is compatible with PHP V5.2.

The article introduces the PHPCompute node and shows how to write PHP scripts that transform and route messages in Message Broker. As of this writing, the PHPCompute node in WebSphere Message Broker V6.1.0.3 is available on Windows® only.


Why PHP?

WebSphere Message Broker supports a range of node types to customize, transform, and route messages. Each node type has a particular resonance with different user skill sets -- so why introduce PHP?

PHP is a dynamic scripting language most frequently used to implement Web sites. It is easy to use, has a gentle learning curve, and creates impressive results with minimal code. It is also very popular, with more than three million active developers worldwide. Indeed, it is often referred to as the fourth most popular programming language (after Java, C, and Visual Basic).

The PHPCompute node enables you to write transformation and routing scripts in PHP, and provides an API to work with messages and interact with the broker. As you will see, it also provides a clean and simple syntax for manipulating messages. The PHPCompute node provides a full XPath 1.0 engine for querying messages, and supports the creation of dynamic output terminals for message routing.

As you follow this article, you will write several examples using the PHPCompute node. To implement these examples, you will need to have:

  • WebSphere Message Broker V6.1.0.3 installed on a Windows machine along with the Message Broker Toolkit.
  • A default Message Broker configuration setup where the examples can be deployed.

This article assumes that you are familiar with Message Broker and the tasks involved in message flow development and deployment.


Create a PHP transformation

The first step is to create a message flow. To do this:

  1. In the Message Broker Toolkit, change the current perspective to Broker Application Development. Click File => New => Project and select Message Flow Project. Enter a name for the new flow project and click Finish. The new project will be created in the current workspace.
  2. Right click on the project and select New => Message Flow. Enter a name for the message flow and click Finish.
  3. Click on the Transformation category in the tool palette. Drag and drop a PHPCompute node onto the message flow (Figure 1).
    Figure 1. Add a PHPCompute node to the message flow
    Figure 1. Add a PHPCompute node to the message flow
  4. Right click on the flow and select New => Other. Select General => File and enter the name of the PHP script (for example, Transform.php).
  5. Copy and paste the sample PHP script in Listing 1 into the editor and save the file.
    Listing 1
    <?php
    
    class Transform {
    
    /**
     * @MessageBrokerCopyTransform
     */
    function evaluate($output_assembly, $input_assembly) {
         	$output_assembly->XMLNSC->document->
    chapter[1]["title"] = "Overview";         
        }
    }
    
    ?>

    The class name must match the name of the PHP script. In this example, the PHP file name is transform.php and the class name is Transform (it is case insensitive).
  6. Next, configure the message flow so that it will receive some data. To keep this example short, we will use file input/output nodes. In the message flow editor, add a File Input node to the flow. The Out terminal of the File Input node should be connected to the In terminal on the PHP node (Figure 2).
    Figure 2. Add the File Input node to the message flow
    Figure 2. Add the File Input node to the message flow
  7. The File Input node needs to be given an Input directory and File name. The node will check the directory every few seconds to see if a file with a matching name has appeared. When a matching file appears, the input node reads the file and sends the contents of the file in a message to the PHPCompute node.
  8. Change the parser on the Input Message Parsing tab to be XMLNSC (Figure 3).
    Figure 3. Change the parser on the File Input node
    Figure 3. Change the parser on the File Input node
  9. Now, add a File Output node to the message flow. Connect the Out terminal of the PHPCompute node to the In terminal on the File Output node (Figure 4).
    Figure 4. Add the File Output node to the message flow
    Figure 4. Add the File Output node to the message flow
  10. The File Output node needs to be given a Directory and File name. When the node receives a message, it writes the contents of the message to the file.

That completes the configuration of a PHP transformation message flow. The next step is to create a Broker Archive file (BAR) and deploy the flow to the default domain:

  1. Right click on the project and select New => Message Broker Archive. Enter a name for the archive file and click OK.
  2. In the BAR file editor (Figure 5), select the PHP transform and message flow items. Click on Build Broker Archive. Click OK when the build completes successfully.
    Figure 5. Configure the Message Broker archive
    Figure 5. Configure the Message Broker archive
  3. You will now deploy the Message Broker archive to the default domain. Change the perspective back to Message Broker Administration. Drag and drop the Message Broker archive file onto the default execution group in the Domains view. After a few seconds it should look like Figure 6.
    Figure 6. Deploying the Message Broker archive
    Figure 6. Deploying the Message Broker archive

At this point, you have successfully created a PHP transformation message flow and deployed it to the local default domain. The final step is to test the message flow:

  1. In a text editor, create a text file called "Transform.txt" and paste the sample XML script from Listing 2 into it. Save the file into a location different from the directory being monitored by the File Input node.
    Listing 2
    <document>
        <chapter title="Introduction">
    		Some text containing the introduction!
        </chapter>
        <chapter title="Beginnings">
    		And more text for the next section here!
        </chapter>
  2. Drag and drop the file using Windows Explorer (or copy the file using a command line) into the directory the File Input node is monitoring (C:\Article). After a few seconds, the Transform.txt file should be deleted and, shortly after, be replaced by another file called "Transform.out" that contains the text in Listing 3.
    Listing 3
    <document>
        <chapter title="Introduction">
    		Some text containing the introduction!
        </chapter>
        <chapter title="Overview">
    		And more text for the next section here!
        </chapter>

Success! The PHP script has processed a message passed to it by the File Input node. The output from the transformation was passed to the File Output node and was saved to the file. As you can see in Listing 3, the title of the second chapter in the text has changed in the output message.


Transform messages with PHP

It is important to remember that all PHP code must appear between <?php and ?> tags. Anything outside of these tags is copied to the standard output stream for the execution group and has no effect on input or output messages. PHP is also inherently stateless; the PHP runtime resets itself after each message has been transformed.

The following sections show you how to use these main features of the PHPCompute node:

Class evaluation or global script

Two PHP script styles are supported. The transform you used earlier was defined in a class. However, transformations can also be coded as a global script with no class definition. The code in Listing 4 performs exactly the same message transformation.

Listing 4
<?php

$output_message  = new MbsMessage($assembly[MB_MESSAGE]);

$output_message->XMLNSC->document->
chapter[1]["title"] = "Overview";         
$output_assembly = new MbsMessageAssembly(
$assembly, $output_message);

$output_assembly->propagate('out');

?>

The version that uses a class is simpler and shorter because it uses an annotation. Annotations are only available when using a class to transform messages. Several other annotations are available to control message routing and copying. Class definitions also provide a more structured approach while global scripts are convenient for fast experimentation with PHP code snippets.

Navigate the message tree

Many transformation and routing scripts need to navigate the message trees. The PHPCompute node makes this easy and intuitive with the path operator syntax (->). An MbsElement object represents each element in the message tree. In the PHP example, you can see the element tree being navigated using path syntax:

$output_message->XMLNSC->document->chapter[1]["title"]

It is also possible to navigate the message tree using a method on MbsElement (Listing 5).

Listing 5
$xml = $output_message->getChild("XMLNSC");
$document = $xml->getChild("document");
$chapter = $document->getChild("chapter", 1);
$title = $chapter->getAttribute("title");

MbsElement has several methods for traversing the message tree (Figure 7).

Figure 7. MbsElement methods
Figure 7. MbsElement methods

To get a child element by name (with an optional occurence) use:

getChild(string $name [, int $occurrence])

To get an array containing all children (with an optional namespace) use:

getChildren([string $namespace])

MbsElement represents a logical element of the tree; it also has these methods:

Listing 6
getName() 	// String name of the current element
getValue()	// Value of parser determined type 
getNamespace() // Namespace (XML parsers only)
getType()		// Parser specific element type (integer)

Create elements in the message tree

The path syntax can create elements as well as navigate existing message trees:

  1. Update the PHP script with the code in Listing 7 and re-deploy to the broker domain.
    Listing 7
    <?php
    
    class Transform {
    
    /**
     * @MessageBrokerCopyTransform
     */
    function evaluate($output_assembly, $input_assembly) {
         	$output_assembly->XMLNSC->document->
    introduction = "Some introduction here!";         
        }
    }
    
    ?>
  2. Copy the input file into the test directory. The output file contains:
    Listing 8
    <document>
        <chapter title="Introduction">
    		Some text containing the introduction!
        </chapter>
        <chapter title="Beginnings">
    		And more text for the next section here!
        </chapter>
        <introduction>Some introduction here!</introduction>
    </document>

The input file does not contain an element called introduction under the document element. The element is created automatically when navigating the message tree.

Repeating elements

Many documents (including the input file in this article) contain repeating elements. So how do you navigate them in PHP? The input file in this article contains repeating chapters. The PHPCompute node supports two features to simplify working with repeating elements:

  • The first feature is iterating over repeating elements using the foreach keyword.
  • The second feature is creating repeating elements using the [] syntax.
Listing 9
<?php

class Transform {

	/**
	 * @MessageBrokerCopyTransform
	 */
	function evaluate($output_assembly, $input_assembly) {
		foreach ($output_assembly->XMLNSC->
document->chapter as $element) {
				$contents .= $element->getValue();
		}
     	$output_assembly->XMLNSC->document->
chapter[] = $contents;         
    }
}

?>

Copy the input file in Listing 9 into the test directory. The output file contains:

Listing 10
<document>
    <chapter title="Introduction">
		Some text containing the introduction!
    </chapter>
    <chapter title="Beginnings">
		And more text for the next section here!
    </chapter>
    <chapter>
		Some text containing the introduction!
    
		And more text for the next section here!
    </chapter>
</document>

The script iterates over all the chapter elements in the input message using the PHP foreach statement. The value of each chapter element is appended to a variable called $contents. The [] syntax instructs the PHPCompute node to append an element instead of updating an existing chapter element in the message tree.

Create repeating elements from an array

Arrays are widely used in PHP as a flexible and multi purpose data structure. An array can be used to create a repeating structure as follows:

Listing 11
<?php

class Transform {

	/**
	 * @MessageBrokerCopyTransform
	 */
	function evaluate($output_assembly, $input_assembly) {
		$contents = array("Hello World!", 
"More contents here!");
     	$output_assembly->XMLNSC->
document->chapter[] = $contents;         
    }
}

?>

Copy the input file from Listing 11 into the test directory. The output file contains:

Listing 12
<document>
    <chapter title="Introduction">
		Some text containing the introduction!
    </chapter>
    <chapter title="Beginnings">
		And more text for the next section here!
    </chapter>
    <chapter>Hello World!</chapter>
    <chapter>More contents here!</chapter>
</document>

The script creates an array containing the chapter contents. The array is then assigned into a repeating chapter element in the message tree. The PHPCompute node creates a new chapter element for each value in the array.

Create elements from an array

Arrays can be used to create arbitrary message tree structures.

Listing 13
<?php

class Transform {

	/**
	 * @MessageBrokerCopyTransform
	 */
	function evaluate($output_assembly, $input_assembly) {
		$contents = array("created" => "03-02-2009",
"author" => "Ant", "location" => "Hursley");
     	$output_assembly->XMLNSC->
document->about = $contents;         
    }
}

?>

Copy the input file from Listing 13 into the test directory. The output file contains:

Listing 14
<document>
    <chapter title="Introduction">
		Some text containing the introduction!
    </chapter>
    <chapter title="Beginnings">
		And more text for the next section here!
    </chapter>
    <about>
        <created>03-02-2009</created>
        <author>Ant</author>
        <location>Hursley</location>
    </about>
</document>

The assignment is not using the [] syntax to create a repeating element. The PHPCompute node creates a message tree element for each key and value in the array.

Create complex messages with nested arrays

Arrays can contain other arrays recursively to create complex message trees.

Listing 15
<?php

class Transform {

	/**
	 * @MessageBrokerCopyTransform
	 */
	function evaluate($output_assembly, $input_assembly) {
		$contents = array(
"created" => "03-02-2009",
"location" => "Hursley",
			"author" => array(
"name" => "Ant", 
				"resident" => "UK", 
"employer" => "IBM")
);
			
     	$output_assembly->XMLNSC->
document->about = $contents;         
    }
}

?>

Copy the input file from Listing 15 into the test directory. The output file contains:

Listing 16
<document>
    <chapter title="Introduction">
		Some text containing the introduction!
    </chapter>
    <chapter title="Beginnings">
		And more text for the next section here!
    </chapter>
    <about>
        <created>03-02-2009</created>
        <location>Hursley</location>
        <author>
            <name>Ant</name>
            <resident>UK</resident>
            <employer>IBM</employer>
        </author>
    </about>
</document>

Create and attach elements

Message tree elements can be created separately and attached to the message tree. This is a convenient way to construct messages by placing the construction code in a helper method or function. The method or function creates and returns a message fragment. The caller then attaches the message fragment into the message tree wherever they so choose.

Listing 17
<?php

class Transform {

	/**
	 * @MessageBrokerCopyTransform
	 */
	function evaluate($output_assembly, $input_assembly) {
     	$output_assembly->XMLNSC->
document->about = $this->createAbout();         
    }

	/**
	 * Creates an about message element.
	 */    
	private function createAbout() {
$element = new MbsElement();
    		$element->created = "03-02-2009";
    		$element->location = "Hursley";
	    
	    	$author = new MbsElement();	    	
	    	$author->name = "Ant";
	    	$author->resident = "UK";
	    	$author->employer = "IBM";
	    
		$element->author = $author;
    		return $element;
  	}    
}

?>

Copy the input file from Listing 17 into the test directory. The output file contains:

Listing 18
<document>
    <chapter title="Introduction">
		Some text containing the introduction!
    </chapter>
    <chapter title="Beginnings">
		And more text for the next section here!
    </chapter>
    <about>
        <created>03-02-2009</created>
        <location>Hursley</location>
        <author>
            <name>Ant</name>
            <resident>UK</resident>
            <employer>IBM</employer>
        </author>
    </about>
</document>

This technique can be used to simplify complex transformation code so that helper methods on the class create elements that are later assigned into the output message.

XML attributes

XML is a commonly used message format in flows. Unlike other message tree formats, XML message trees contain attributes. XML attributes behave as arrays on an element with key name lookups. This script in Listing 19 sets the title of the first chapter to match the second. This example also references an intermediate document element from the message tree ($document).

Listing 19
<?php

class Transform {

	/**
	 * @MessageBrokerCopyTransform
	 */
	function evaluate($output_assembly, $input_assembly) {
		$document = $output_assembly->XMLNSC->document;
     	$document->chapter[0]["title"] = 
     		$document->chapter[1]["title"];
    }
}

?>

Annotations

Annotations control the context in which the evaluate method is called. Annotations also reduce the amount of boilerplate code that would otherwise need to be written.

Listing 20
class Transform {

	/**
	 * @MessageBrokerCopyTransform
	 */
	function evaluate($output_assembly) { }
}

The MessageBrokerCopyTransform annotation instructs the PHPCompute node to copy the input message and pass the copied message to the evaluate method. There are several other annotations that specify message transformation options.

In Message Broker, the input message and assembly are always read only. Therefore, new messages must be created to build a transformed message. In the case of the message assembly, the new object must encapsulate the new output message and the other (environment) trees from the input message assembly.

The MessageBrokerSimpleTransform annotation creates a new message assembly and an empty output message. The input and output assemblies are passed to the evaluate method. The output assembly contains a copy of the local environment from the input assembly (and any other message assembly trees).

The local environment is another logical tree in the message assembly. It is a scratch pad for information about the message, but not part of the message itself. It is populated and accessed by many Message Broker nodes, but can also be modified by the user. It is good practice (but not enforced) to make a copy of the local environment before modifying it. The MessageBrokerLocalEnvironmentTransform does just this. The output message assembly contains a copy of the local environment tree.

By default, the output message assembly is propagated to the Out terminal after the evaluate method has been executed. Users can create new dynamic output terminals for a PHPCompute node in the Message Broker Toolkit. The PHP script instructs the PHPCompute node to route to a specific terminal by returning string from evaluate. The script must also declare the MessageBrokerRouter annotation on the evaluate method.

If no string is returned, the message isn’t propagated to any terminal. Alternatively, the script can call the propagate method on the output message assembly object to manually propagate the assembly to a terminal (pass the terminal name as the parameter). This is useful for multiple propagate use cases; for example, message-shredding. Listing 21 shows an update to the local environment message tree.

Listing 21
<?php

class Transform {

	/**
   	 * @MessageBrokerCopyTransform
   	 * @MessageBrokerLocalEnvironmentTransform
	 */
	function evaluate($output_assembly, $input_assembly) {
    		$output_assembly->XMLNSC->document->filename =
$input_assembly[MB_LOCAL_ENVIRONMENT]->
File->Name;
    }
}

?>

Copy the input file in Listing 21 into the test directory. The output file contains:

Listing 22
<document>
    <chapter title="Introduction">
		Some text containing the introduction!
    </chapter>
    <chapter title="Beginnings">
		And more text for the next section here!
    </chapter>
    <filename>Transform.txt</filename>
</document>

The script combines the MessageBrokerCopyTransform annotation with the MessageBrokerLocalEnvironmentTransform annotation. The output message contains the file name populated by the File Input node. The local environment annotation can also be combined with the MessageBrokerSimpleTransform annotation.


Message assemblies

The message assembly contains four objects:

  • Message: business data
  • Local environment: node and message metadata
  • Global environment: general scratchpad
  • Exception list: error information, used for failure processing.

These objects can be accessed using array notation:

Listing 23
$input[MB_MESSAGE] 
$input[MB_LOCAL_ENVIRONMENT]
$input[MB_GLOBAL_ENVIRONMENT]
$input[MB_EXCEPTION_LIST]

The $input[MB_MESSAGE] is the same as $input, just without the subscript. The previous example could have been written using the MB_MESSAGE subscript (Listing 24).

Listing 24
<?php

class Transform {

	/**
   	 * @MessageBrokerCopyTransform
   	 * @MessageBrokerLocalEnvironmentTransform
	 */
	function evaluate($output_assembly, $input_assembly) {
    		$output_assembly[MB_MESSAGE]->
XMLNSC->document->filename =
$input_assembly[MB_LOCAL_ENVIRONMENT]->
File->Name;
    }
}

?>

Summary

If you followed the steps in this article, then you have successfully:

  • Created a message flow containing a PHPCompute node.
  • Deployed the PHP message flow to a local Message Broker domain.
  • Run several PHP scripts that highlight features of the node; specifically to:
    • Define a transformation class
    • Navigate the message tree
    • Create elements in the message tree
    • Handle repeating elements
    • Access and update XML attributes
    • Use annotations to control message processing behaviour.

With these skills, you have an excellent starting point for solving a wide variety of transformation and routing problems with the PHPCompute node. Furthermore, as you grow your PHP skills, so you will see the productivity that the PHP language brings to message flow development.

You can expand your use of the PHPCompute Node in IBM WebSphere Message Broker. There are many more related topics not covered here that you might want to explore, including message shredding, XPATH, routing to labels, and Java integration through the PHP/Java Bridge. To learn more about the PHPCompute node and related topics, refer to the WebSphere Message Broker v6.1.0.3 documentation library.

To learn more about PHP and scripting in WebSphere sMash, see the WebSphere sMash documentation on the Project Zero Web site, and the developerWorks Web development and PHP zones for comprehensive PHP project resources.

Resources

Learn

Get products and technologies

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. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. 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, Web development
ArticleID=380333
ArticleTitle=Introducing the WebSphere sMash PHPCompute node in WebSphere Message Broker
publish-date=04082009