Published on

Adding a new Camel component to the WildFly Camel subsystem. Part 1

Authors
  • avatar
    Name
    James Netherton
    Twitter

I wanted to explain the process of adding a new Camel component to the WildFly Camel project, as it's often the source of confusion for first time contributors.

Part 1 shows how to add a new component module XML descriptor to the project. part 2 covers integration testing.

Prerequisites

First, some obvious prerequisites to get started. You'll need:

  • Java / Maven installed
  • Git installed so that you can fork / clone the WildFly Camel project
  • An issue created via the project issue tracker which you can reference later in your commit comment

1. Adding the new Camel component dependency

With the project cloned, edit feature/modules/pom.xml and add a new dependency for the component you want to integrate.

Note the order of dependencies is in alphabetical order. This should be preserved unless there's a good reason not to.

2. Creating a Camel component module definition

Next we need to create a JBoss Modules XML descriptor for the new component. We use the Smartics JBoss Modules Maven Plugin to help with this.

Open feature/modules/etc/smartics/camel-modules.xml and create a module descriptor for the new component module.

For example, the definition for the geocoder component looks like this:

<module name="org.apache.camel.component.geocoder">
    <include artifact="com.google.code.geocoder-java:geocoder-java" />
    <include artifact="org.apache.camel:camel-geocoder" />
    <apply-to-dependencies skip="true">
        <include module="org.apache.camel.apt" />
        <include module="org.springframework.boot" />
    </apply-to-dependencies>
    <dependencies>
        <module name="org.slf4j" />
    </dependencies>
    <exports>
        <include path="com/google/code/geocoder/model" />
        <exclude path="com/google**" />
    </exports>
</module>

Here's a quick breakdown of what this all means.

Module name

The unique name assigned to the module. This also determines the directory structure on the filesystem. E.g org.apache.camel.component.geocoder is translated to a path of org/apache/camel/component/geocoder/main.

Include artifact

The resources that should be part of the module. There can be 0 or more of these. The artifact attribute is a Maven coordinate in the form groupId:artifactId.

Expressions are also allowed. E.g to include all dependencies matching camel- you could do:

<include artifact="org.apache.camel:camel-(.*)"/>

Sometimes it makes sense to bundle resource dependencies withing the same module as the camel component JAR. Otherwise, it's best to define new module definitions for resources in feature/modules/etc/smartics/other-modules.xml. If possible, try to group resources into logical units.

apply-to-dependencies

This is a block operation to apply to each module dependency. In our example we skip the dependencies defined in this block. Dependencies for org.apache.camel.apt and org.springframework.boot are skipped for all Camel component modules as they are not required by the Camel subsystem.

dependencies

Other modules on which the module depends on. In our example we only need to define a dependency on org.slf4j. Sometimes you will need to define others. The Smartics Maven plugin does a good job of determining dependencies for you at build time, so you can avoid explicitly listing all of them manually.

Note, org.slf4j is a mandatory dependency for all Camel component modules.

imports / exports

Sometimes you need to control what is exported onto the classpath. In our example we include a package path which users will need access to, but also exclude others which are not required.

3. Registering the component

The final task is to ensure that the WildFly Camel subsystem has access to the new component module. To do this edit feature/modules/etc/managed/wildfly/modules/system/layers/fuse/org/apache/camel/component/main/module.xml.

4. Finishing up

With the module definition created, we can generate the JBoss Modules module.xml file by running the build.

$ mvn clean install

When the build completes it will have generated your module.xml file and will have synchronized its directory structure back into the project tree at feature/pack/src/main/resources/modules/system/layers/fuse.

In part 2 we'll discover how to write an integration test for our new component module.