You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 49 Next »

Creating a Hello World JBI Service Engine

This tutorial describes how to create a very simple Hello World style of JBI service engine (SE) component. It demonstrates some best practices for creating JBI components. The example in this tutorial is as minimalistic as possible so as to focus on key concepts and not drown in details. The example component will respond to all requests with the message:

<hello>Hello World! Message [<original message here>] contains [??] bytes.</hello>

Prerequisites

  • Maven 2.0.4 or higher
    • If you have never used Maven previously the Maven Getting Started Guide explains some valuable concepts surrounding Maven
  • ServiceMix 3.1 or higher
  • A broadband internet connection (so Maven can automatically download dependencies)

A Very Brief Introduction to Java Business Integration

The Java Business Integration (JBI) spec provides a standards-based, service-oriented approach to application integration through the use of an abstract messaging model, without reference to a particular protocol or wire encoding. JBI introduces the concepts of Binding Components (BCs), Service Engines (SEs) to Service Units (SUs) and Service Assemblies (SAs) to define an architecture for vendor-neutral pluggable components. The purpose of this architecture is to provide standards-based interoperability amongst components/services.

JBI components are can be thought of as the smallest applications or services accessible in a service-oriented architecture. Each service has a very specific purpose and therefore a narrow scope and set of functionality. Components come in two flavours: Service Engine (SE) and Binding Components (BC). Several SUs are packed into a SA. An SA is a complete application consisting of one or more services interacting with one another.

See also the page providing information on working with service units

Below are some quick definitions:

  • Component Architecture
    • Binding Components - Components that provide or consume services via some sort of communications protocol or other remoting technology
    • Service Engines - Components that supply or consume services locally (within the JBI container)
  • Component Packaging
    • Service Units - Packaging for an individual service that allows deployment to the JBI container; similar to a WAR file from J2EE
    • Service Assemblies - Packaging for groups of SUs for deployment to the JBI container; similar to an EAR file from J2EE

For further information on JBI, see the JBI section of the User's Guide. See also the JBIforSOI document for a decent introduction to JBI.

Creating the Maven Projects for Each Component

Creating a Maven Subproject For the JBI Service Engine

The focus of this section is on the creation of a JBI component. For this task, a Maven archetype will be used to create a Maven project skeleton to house the component. Maven archetypes are templates for Maven projects that jumpstart project creation via the automation of repetitive tasks by following standard conventions. The result of using an archetype to create a Maven project is a directory structure, a Maven POM file and, depending on the archetype being used, sometimes Java objects and JUnit tests.

As this text describes how to create a Hello World service engine and pack it into a SU and SA, the project name is hello-world-se and each piece of the SA puzzle are named using a similar pattern. For a given project, the IDs and names shall be altered such that they describe the purpose or function of the given piece of the SA.

1) Create a directory named hello-world-smx and switch to that directory:

$ mkdir hello-world-smx
$ cd hello-world-smx

2) Use the servicemix-service-engine Maven archetype to generate a Maven project for the SE:

$ mvn archetype:create \
-DarchetypeGroupId=org.apache.servicemix.tooling \
-DarchetypeArtifactId=servicemix-service-engine \
-DarchetypeVersion=3.1-incubating-SNAPSHOT \
-DgroupId=org.apache.servicemix.samples.helloworld.se \
-DartifactId=hello-world-se

The command above will create a directory named hello-world-se that houses a Maven project for the JBI service engine being created here. The name of the directory is taken from the artifactId parameter.

The first three parameters to the mvn command (-DarchetypeGroupId=org.apache.servicemix.tooling -DarchetypeArtifactId=servicemix-service-engine -DarchetypeVersion=3.1-incubating-SNAPSHOT) identify which Maven archetype to use for the archetype:create goal, while the last two parameters (-DgroupId=org.apache.servicemix.samples.helloworld -DartifactId=hello-world-se) uniquely identify the Maven project that is being generated. The groupId (printed in pink) is used as the Java package and the artifactId is used as the project name. Therefore, only alphanumeric characters are valid values for the groupId and artifactId parameters.

The value of the archetypeVersion parameter in the command above (3.1-incubating-SNAPSHOT) may need to be updated to the current ServiceMix version in order for the command to work correctly. The latest version can always be found in the top level ServiceMix POM in the <version> element.

The output from executing the archetype:create goal is shown below (only relevant information has been preserved):

[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'archetype'.
[INFO] ----------------------------------------------------------------------------
[INFO] Building Maven Default Project
[INFO] task-segment: [archetype:create] (aggregator-style)
[INFO] ----------------------------------------------------------------------------
...
[INFO] <span style="color: #ff00ff">Defaulting package to group ID: org.apache.servicemix.samples.helloWorldSE</span>
...
[INFO] *********** End of debug info from resources from generated POM *********************
[INFO] <span style="color: #009900">Archetype created in dir: /Users/bsnyder/src/hello-world-se/hello-world-se</span>
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------

Again, Maven creates a directory using the artifactId provided (printed in green in the command and output). Inside this directory resides the pom.xml and the src directory.

In case of a BUILD ERROR: Maven plugin version requirement

The maven-archetype-plugin 1.0-alpha4 or above is required for this tutorial. When an older version is installed, a build error will occur. The version of this plugin can be checked by verifying the name of the following directories:

Unix
\~/.m2/repository/org/apache/maven/plugins/maven-archetype-plugin 
Windows
C:\Documents and Settings\<USERNAME>

In case the only version available of the maven-archetype-plugin is an older one, a minimal pom.xml file will need to be created manually in the hello-world-se directory. Below is a simple POM to use for this purpose:

Minimal pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.apache.servicemix.samples</groupId>
  <artifactId>hello-world-se</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>

  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-archetype-plugin</artifactId>
          <version>1.0-alpha-4</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

Creating the JBI Service Engine

Let's first examine the classes created by the servicemix-service-engine Maven archetype in this simple SE we're developing. These classes extend class from either the JBI spec APIs or from the servicemix-common package. Now let's look at the classes created by the servicemix-service-engine Maven archetype:

  • MyBootstrap.java - Implements javax.jbi.component.Boostrap which is called by the JBI container when the component is installed and uninstalled. This is where you place logic to set up and tear down things when the component is started and stopped.
  • MyComponent.java - Extends the DefaultComponent, a convience class that makes creating JBI components much easier and provides lifecycle management of components deployed to the JBI container. This class should be fleshed out by overriding methods in the DefaultComponent to configure and initialize the component.
  • MyEndpoint.java - Extends Endpoint and implements ExchangeProcessor. Endpoint provides a referenceable resource for the component and the ExchangeProcessor provides the ability for the JBI container to process a message exchange with the component. The ExchangeProcessor.process() method is where we will make a call to a method containing the logic to print out the Hello World message.

Adding the Logic to Print the Message

When creating a JBI component, how a message exchange is handled depends on whether a component is a consumer or a provider. Because the Hello World SE will not be consuming any other service (i.e., sending a message to another service), it is a provider (i.e., it will only be providing its service via a return message). As mentioned above, the ExchangeProcessor.process() method is of interest because it is where the message exchange is handled, so let's examine this method:

public void process(MessageExchange exchange) throws Exception {
        // The component acts as a provider, this means that another component has requested our service
        // As this exchange is active, this is either an in or a fault (out are send by this component)
        if (exchange.getRole() == MessageExchange.Role.PROVIDER) {
            // Check here if the mep is supported by this component
            if (exchange instanceof InOut == false) {
               throw new UnsupportedOperationException("Unsupported MEP: " + exchange.getPattern());
            }
            // In message
            if (exchange.getMessage("in") != null) {
                NormalizedMessage in = exchange.getMessage("in");
                // TODO ... handle the in message
                // If the MEP is an InOnly, RobustInOnly, you have to set the exchange to DONE status
                // else, you have to create an Out message and populate it
                // For now, just echo back
                NormalizedMessage out = exchange.createMessage();
                out.setContent(in.getContent());
                exchange.setMessage(out, "out");
                channel.send(exchange);
            // Fault message
            } else if (exchange.getFault() != null) {
                // TODO ... handle the fault
                exchange.setStatus(ExchangeStatus.DONE);
                channel.send(exchange);
            // This is not compliant with the default MEPs
            } else {
                throw new IllegalStateException("Provider exchange is ACTIVE, but no in or fault is provided");
            }
        // The component acts as a consumer, this means this exchange is received because
        // we sent it to another component.  As it is active, this is either an out or a fault
        // If this component does not create / send exchanges, you may just throw an UnsupportedOperationException
        } else if (exchange.getRole() == MessageExchange.Role.CONSUMER) {
            // Exchange is finished
            if (exchange.getStatus() == ExchangeStatus.DONE) {
                return;
            // Exchange has been aborted with an exception
            } else if (exchange.getStatus() == ExchangeStatus.ERROR) {
                return;
            // Exchange is active
            } else {
                // Out message
                if (exchange.getMessage("out") != null) {
                    // TODO ... handle the response
                    exchange.setStatus(ExchangeStatus.DONE);
                    channel.send(exchange);
                // Fault message
                } else if (exchange.getFault() != null) {
                    // TODO ... handle the fault
                    exchange.setStatus(ExchangeStatus.DONE);
                    channel.send(exchange);
                // This is not compliant with the default MEPs
                } else {
                    throw new IllegalStateException("Consumer exchange is ACTIVE, but no out or fault is provided");
                }
            }
        // Unknown role
        } else {
            throw new IllegalStateException("Unkown role: " + exchange.getRole());
        }
    }

The implementation of this method was provided by the servicemix-service-engine Maven archetype and is shown in the code snippet above. Because the archetype can be used to create a consumer or a provider, this method is very generic and contains a conditional block for handling either a consumer or a provider role. But this method will still require us to make the decision of which style of Message Exchange Pattern (MEP) to handle as well. In the case of the Hello World SE, we know that it is a provider so it will need to send a return message. Therefore it will need to handle an In-Out MEP.

Instead of having MyEndpoint extend the very basic Endpoint class, we're going to extend a different class that is specifically for provider endpoints named ProviderEndpoint. Notice the diagram above showing the class hierarchy of Endpoint. The ProviderEndpoint supplies some additional conveniences for provider components and will make the job of implementing MyEndpoint as a provider much easier. So change the definition of MyEndpoint from this:

public class MyEndpoint extends Endpoint implements ExchangeProcessor

to this:

public class MyEndpoint extends ProviderEndpoint implements ExchangeProcessor

Because the ProviderEndpoint.process() method already handles an In-Out MEP, MyEndpoint will simply need to override the ProviderEndpoint.processInOut() method. Below is the content for this method:

protected void processInOut(MessageExchange exchange, NormalizedMessage in, NormalizedMessage out) throws Exception {
	SourceTransformer sourceTransformer = new SourceTransformer();
	String inMessage = sourceTransformer.toString(in.getContent()); 
	out.setContent(new StringSource("<hello>Hello World! Message [" + inMessage + "] contains [" + inMessage.getBytes().length + "] bytes</hello>."));
}

Testing the Hello World SE

Thanks to the archetype, testing the component is very easy because it already created a test. All that is necessary is to change the string being sent by the client code. In the src/test/java directory is the org.apache.servicemix.samples.helloworld.se.MySpringComponentTest test. Simple open this test and change line #36 from this:

me.getInMessage().setContent(new StringSource("<hello>world</hello>"));

to something more meaningful, like this:

me.getInMessage().setContent(new StringSource("<hello>Ski Colorado!</hello>"));

To execute the test, simply run the Maven install goal from within the hello-world-se directory like so:

$ mvn install 

Below is the output that will print to the console:

[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[INFO] Building Hello World Service Engine
[INFO] task-segment: [install]
[INFO] ----------------------------------------------------------------------------
[INFO] [xbean:mapping {execution: default}]
Checking: org.apache.servicemix.samples.helloworld.se.MyComponent
Checking: org.apache.servicemix.samples.helloworld.se.MyEndpoint
[INFO] Generating META-INF properties file: /Users/bsnyder/src/hello-world-smx/hello-world-se/target/xbean/META-INF/services/org/apache/xbean/spring/http/org.apache.servicemix.samples.helloworld/1.0 for namespace: http://org.apache.servicemix.samples.helloworld/1.0
[INFO] Generating Spring 2.0 handler mapping: /Users/bsnyder/src/hello-world-smx/hello-world-se/target/xbean/META-INF/spring.handlers for namespace: http://org.apache.servicemix.samples.helloworld/1.0
[INFO] Generating Spring 2.0 schema mapping: /Users/bsnyder/src/hello-world-smx/hello-world-se/target/xbean/META-INF/spring.schemas for namespace: http://org.apache.servicemix.samples.helloworld/1.0
[INFO] Generating HTML documentation file: /Users/bsnyder/src/hello-world-smx/hello-world-se/target/xbean/hello-world-se.xsd.html for namespace: http://org.apache.servicemix.samples.helloworld/1.0
[INFO] Generating XSD file: /Users/bsnyder/src/hello-world-smx/hello-world-se/target/xbean/hello-world-se.xsd for namespace: http://org.apache.servicemix.samples.helloworld/1.0
[INFO] Generating WIKI documentation file: /Users/bsnyder/src/hello-world-smx/hello-world-se/target/xbean/hello-world-se.xsd.wiki for namespace: http://org.apache.servicemix.samples.helloworld/1.0
Warning, could not load class: org.apache.servicemix.samples.helloworld.se.MyEndpoint
[INFO] ...done.
Downloading: http://repo.mergere.com/maven2/xml-security/xmlsec/1.3.0/xmlsec-1.3.0.pom
[WARNING] Unable to get resource from repository central (http://repo1.maven.org/maven2)
Downloading: http://repo.mergere.com/maven2/wss4j/wss4j/1.5.0/wss4j-1.5.0.pom
[WARNING] Unable to get resource from repository central (http://repo1.maven.org/maven2)
[INFO] [jbi:generate-jbi-component-descriptor]
[INFO] Generating jbi.xml
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [surefire:test]
[INFO] Surefire report directory: /Users/bsnyder/src/hello-world-smx/hello-world-se/target/surefire-reports

-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.apache.servicemix.samples.helloworld.se.MySpringComponentTest
<hello>Hello World! Message [<hello>Ski Colorado!</hello>] contains [28] bytes.</hello>
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.009 sec

Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] [jar:jar]
[INFO] Building jar: /Users/bsnyder/src/hello-world-smx/hello-world-se/target/hello-world-se-1.0-SNAPSHOT.jar
[INFO] [jbi:jbi-component]
[INFO] Generating installer /Users/bsnyder/src/hello-world-smx/hello-world-se/target/hello-world-se-1.0-SNAPSHOT-installer.zip
[INFO] Building jar: /Users/bsnyder/src/hello-world-smx/hello-world-se/target/hello-world-se-1.0-SNAPSHOT-installer.zip
[INFO] [install:install]
[INFO] Installing /Users/bsnyder/src/hello-world-smx/hello-world-se/target/hello-world-se-1.0-SNAPSHOT.jar to /Users/bsnyder/.m2/repository/org/apache/servicemix/samples/helloworld/hello-world-se/1.0-SNAPSHOT/hello-world-se-1.0-SNAPSHOT.jar
[INFO] Installing /Users/bsnyder/src/hello-world-smx/hello-world-se/target/xbean/hello-world-se.xsd to /Users/bsnyder/.m2/repository/org/apache/servicemix/samples/helloworld/hello-world-se/1.0-SNAPSHOT/hello-world-se-1.0-SNAPSHOT.xsd
[INFO] Installing /Users/bsnyder/src/hello-world-smx/hello-world-se/target/xbean/hello-world-se.xsd.html to /Users/bsnyder/.m2/repository/org/apache/servicemix/samples/helloworld/hello-world-se/1.0-SNAPSHOT/hello-world-se-1.0-SNAPSHOT-schema.html
[INFO] Installing /Users/bsnyder/src/hello-world-smx/hello-world-se/target/hello-world-se-1.0-SNAPSHOT-installer.zip to /Users/bsnyder/.m2/repository/org/apache/servicemix/samples/helloworld/hello-world-se/1.0-SNAPSHOT/hello-world-se-1.0-SNAPSHOT-installer.zip
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 15 seconds
[INFO] Finished at: Thu Jan 04 15:21:00 MST 2007
[INFO] Final Memory: 13M/24M
[INFO] ------------------------------------------------------------------------

Notice that not only do we see that the build was successful, but notice the bold text of the message that was printed. If you see this, you just wrote your a JBI component and tested it successfully.


Creating the Maven Subprojects For the Service Unit and Service Assembly

The archetypes for SUs and SAs do not contain much code, but rather help with tasks related to Maven. Later, we will only need to adapt the POMs to our project. Below are the steps for to achieve this:

1) From within the hello-world-smx directory, execute the following commands to create the project for the SU:

$ mvn archetype:create \
    -DarchetypeGroupId=org.apache.servicemix.tooling \
    -DarchetypeArtifactId=servicemix-service-unit \
    -DarchetypeVersion=3.1-incubating-SNAPSHOT \
    -DgroupId=org.apache.servicemix.samples.helloworld \
    -DartifactId=hello-world-su

2) From within the hello-world-smx directory, execute the following commands to create the project for the SA:

$ mvn archetype:create \
    -DarchetypeGroupId=org.apache.servicemix.tooling \
    -DarchetypeArtifactId=servicemix-service-assembly \
    -DarchetypeVersion=3.1-incubating-SNAPSHOT \
    -DgroupId=org.apache.servicemix.samples.helloworld \
    -DartifactId=hello-world-sa

Upon successful execution of the archetype:create goals, look for the BUILD SUCCESSFUL output. The hello-world-smx directory should now contain the following directories:

hello-world-sa
hello-world-se
hello-world-su

If you see the above directories, proceed to the next section.

If instead you see the BUILD FAILED output, you'll need to analyze the rest of the output to troubleshoot the issue. Assistance with any issue you might experience is available from the ServiceMix community via the ServiceMix mailing lists archive.

Incorporating the Subprojects Into a Top Level POM

Now that we have created the SU and SA projects, a top level pom.xml must be manually created and made aware of each subproject. In the hello-world-se directory create a file named pom.xml containing the following content:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.apache.servicemix.samples</groupId>
  <artifactId>hello-world-se</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>Hello World JBI Sample</name>

  <modules>
    <module>hello-world-sa</module>
    <module>hello-world-su</module>
  </modules>

  <dependencies>
    <dependency>
      <groupId>org.apache.servicemix.samples.helloworld</groupId>
      <artifactId>hello-world-su</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
  </dependencies>

</project>

This POM will allow the example to be easily folded in to the ServiceMix samples. The <modules> element denotes the subprojects that were created using the Maven archetypes and the <dependencies> element tells Maven to include the SU into the SA when it is constructed.

Give Each of the Maven Subprojects a Name

When sitting in the hello-world-smx directory, you should now see the following:

hello-world-sa
hello-world-se
hello-world-su
pom.xml

Now we need to give each component's pom.xml an appropriate name. This name will allow Maven's output to denote a component's name in its output making our development work a bit easier. To name each project, simply edit each pom.xml and replace <name>A custom project</name> with an appropriate name. Below are the instructions for naming each component's project:

  • Edit hello-world-sa/pom.xml and replace <name>a custom project</name> with <name>Hello World Service Assembly</name>
  • Edit hello-world-se/pom.xml and replace <name>a custom project</name> with <name>Hello World Service Engine</name>
  • Edit hello-world-su/pom.xml and replace <name>a custom project</name> with <name>Hello World Service Unit</name>

A Quick Look at the Directory Hierarchy

After executing the Maven archetypes above, you should now be able to see the following directory hierarchy:

./hello-world-sa
./hello-world-sa/pom.xml
./hello-world-se
./hello-world-se/pom.xml
./hello-world-se/src
./hello-world-se/src/main
./hello-world-se/src/main/java
./hello-world-se/src/main/java/org
./hello-world-se/src/main/java/org/apache
./hello-world-se/src/main/java/org/apache/servicemix
./hello-world-se/src/main/java/org/apache/servicemix/samples
./hello-world-se/src/main/java/org/apache/servicemix/samples/helloworld
./hello-world-se/src/main/java/org/apache/servicemix/samples/helloworld/MyBootstrap.java
./hello-world-se/src/main/java/org/apache/servicemix/samples/helloworld/MyComponent.java
./hello-world-se/src/main/java/org/apache/servicemix/samples/helloworld/MyEndpoint.java
./hello-world-se/src/test
./hello-world-se/src/test/java
./hello-world-se/src/test/java/org
./hello-world-se/src/test/java/org/apache
./hello-world-se/src/test/java/org/apache/servicemix
./hello-world-se/src/test/java/org/apache/servicemix/samples
./hello-world-se/src/test/java/org/apache/servicemix/samples/helloworld
./hello-world-se/src/test/java/org/apache/servicemix/samples/helloworld/MySpringComponentTest.java
./hello-world-se/src/test/resources
./hello-world-se/src/test/resources/log4j.properties
./hello-world-se/src/test/resources/spring.xml
./hello-world-su
./hello-world-su/pom.xml
./hello-world-su/src
./hello-world-su/src/main
./hello-world-su/src/main/resources

Unix

To show the entire directory hierarchy, simply execute find . from the command line

Windows

To show the entire directory hierarchy, simply execute find from the command line

According to the archetype rules, all Java objects generated from the archetype:create goal are prefixed with the word My. The Java objects can be renamed to whatever you prefer, making sure to also change the names in the corresponding resource files and all tests and {{pom.xml}}s) as well.

The content of the <version> element is arbitrary and is used to describe not the version of ServiceMix but of the version of projects that were just created. We just have to use consistently the same version when we reference this project.

How to Build and Package the Components

By now, it is already possible to call Maven with the relevant goals.

Compiling the Components

In order to, among other things, build and package the components, execute the following command from within hello-world-smx directory:

mvn install 
...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] ------------------------------------------------------------------------
[INFO] Hello World Service Assembly .......................... SUCCESS [11.583s]
[INFO] Hello World Service Unit .............................. SUCCESS [0.656s]
[INFO] Hello World JBI Sample ................................ SUCCESS [1.517s]
[INFO] ------------------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 14 seconds
[INFO] Finished at: Fri Dec 01 00:35:06 MST 2006
[INFO] Final Memory: 13M/25M
[INFO] ------------------------------------------------------------------------

Upon successful execution of the install goal, look for the BUILD SUCCESSFUL output as shown above. In addition, because each pom.xml has been given a name, each project can be easily identified. If instead you see the BUILD FAILED output, you'll need to look at the rest of the output to troubleshoot the issue. In case this success information does not appear, the output will provide some information about what might have gone awry. Assistance with any issue you might experience is available from the ServiceMix community via the ServiceMix mailing lists archive.

Testing the Components

Performing automated testing of the components is possible via Maven as well. Because the ServiceMix root POM prevents tests from being executed at the top level, this functionality must be activated so that the coponents can be tested. To do so, the <build> element of the hello-world-se/pom.xml must be augmented using the following content:

<pluginManagement>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
          <skip>false</skip><!-- this overrides the ServiceMix root POM's setting for test execution -->
        </configuration>
      </plugin>
   </plugins>
</pluginManagement>

By adding the configuation above, the install goal will now including test execution in addition to building and packaging the components. To run the tests, execute the test goal this time and you should see the following output:

$ mvn test
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[INFO] Building A custom project
[INFO]    task-segment: [test]
[INFO] ----------------------------------------------------------------------------
...
[INFO] [compiler:compile]
...
[INFO] [surefire:test]
[INFO] Setting reports dir: c:\java\tmp\servicemix-helloWorldSE\target/surefire-reports
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
[surefire] Running org.apache.servicemix.samples.helloWorldSE.MySpringComponentTest
...
[surefire] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 1,422 sec
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
...

TODO

Maybe add further testing at the end of the tutarial ("how to continue when having the working example")

Generation and Deployment of the SA

The execution of the install goal above packages not only each component individually, it also packages the components together into a single SA. Of course, the code does not yet do anything, but we can already deploy the SA ServiceMix by switching to the hello-world-se/hello-world-sa directory and executing the jbi:projectDeploy goal like so:

$ mvn jbi:projectDeploy

This tells the Maven JBI plugin to deploy the components to ServiceMix. When the deployment is complete, ServiceMix will output the following:

INFO  - ServiceAssemblyLifeCycle       - Starting service assembly: hello-world-sa

This output tells us that the SA was successfully deployed to ServiceMix.

Deploying Component Dependencies

When working with the jbi:projectDeploy you may want to disable dependency deployment. When deploying to a server which has other components sharing these dependencies, they can cause problems during deployment. To stop the Maven JBI plugin from undeploying and redeploying dependencies each time, alter its configuration by disabling the deployment of dependencies using the following:

<build>
<plugins>
  <plugin>
    <artifactId>jbi-maven-plugin</artifactId>
    <configuration>
      <deployDependencies>false</deployDependencies>
    </configuration>
  </plugin>
</plugins>
</build>

The configuration above introduces the deployDependencies element to the Maven JBI plugin and sets it to false.

For a few more configurable options on the Maven JBI plugin, see also Ability to configure jbi:projectDeploy goal to exclude updating dependencies.

Adding Functionality to the Component

We're now ready to add a bit of functionality to the component. Using an IDE like IntelliJ IDEA or Eclipse make this task much easier. The steps described here apply to Eclipse.

Generate Eclipse Project Files

In order to import the SE into Eclipse, tell Maven to generate the necessary project and classpath files, switch to the hello-world-se directory and execute the following Maven goal:

$ mvn eclipse:eclipse

This will allow the SE to be imported into Eclipse for adding functionality.

TODO

The default implementation of the component accepts InOut MEPs (ADD
LINK TO FURTHER READING CONCERNING MEPs) and return the input content
as the out message. This is already nearly what we want.

OUTLINE for further work:

  • Get Messages
  • read Messages
  • count the bytes
    Maybe easiest by XSLT endpoint (can be used to apply an XSLT stylesheet to the incoming exchange and will return the transformed result as the output message.) see [ servicemix-saxon|servicemix-saxon]

  • send a message back
  • Configure SA so that the example receives messages
    create & populate
    C:\hello-world-SE-SU-SA\hello-world-SU\src\main\resources\servicemix.xml
  • as MyDeployer extends AbstractXBeanDeployer create xbean.xml for SU
  • make something send messages (eg quartz timer, HTTP POST,...) and dump the answer (eg TraceComponent, FireWriter, EIP,...)
  • add a chapter what user may do now / "how to continue when having the working example"

Classpath for SU to include manually till v3.1, see mail

manually editing http://goopen.org/confluence/display/SM/Working+with+Service+Units
manually editing http://www.servicemix.org/site/working-with-service-assemblies.html
use the SU archetype like in http://www.servicemix.org/site/creating-a-protocol-bridge.html
use the SA archetype like in http://www.servicemix.org/site/creating-a-protocol-bridge.html

INS When to use this JBI Component
INS Using the component that you created

provide exact position in the SVN!
/samples/hello-world-SE-SU-SA/
integrate from SVN source like it is done at Configuration at http://www.servicemix.org/site/visualisation.html

maybe moving the content of overlapping existing docus to this new tut and - where appropriate - delete the old ones (only leaving a redirect).
http://www.servicemix.org/site/notes-on-creating-jbi-component-using-maven2.html version14
http://www.servicemix.org/site/creating-a-standard-jbi-component.html version26
are already fully incorporated in the mentioned versions, so delete content and point from there to here (and delete note at the very top)

This shall already include everything stated at
http://www.servicemix.org/site/maven-jbi-plugin.html#MavenJBIplugin-GettingStarted
and
http://www.servicemix.org/site/working-with-components.html

provide additional reading
Creating a protocol bridge.for a "bigger" example
The examples page lists examples providing more information, showing further possibilities and components.

Additional Resources

  • No labels