Blog




The smartics JBoss Modules Maven Plugin allows to create a JBoss modules folder for a project defined by a Maven POM. This articles shows alternatives to this approach and tries to give guidelines on when to use which option.

 

Option 1: The manual Approach

If you follow the documentation on Extending JBoss AS 7 you encounter a Maven archetype that allows to create an extension project. This project contains a generated module.xml file.

The module.xml looks like this:

<module xmlns="urn:jboss:module:1.0" name="com.acme.corp.tracker">
  <resources>
    <resource-root path="acme-subsystem.jar"/>
  </resources>
    
  <dependencies>
    <module name="javax.api"/>
    <module name="org.jboss.staxmapper"/>
    <module name="org.jboss.as.controller"/>
    <module name="org.jboss.as.server"/>
    <module name="org.jboss.modules"/>
    <module name="org.jboss.msc"/>
    <module name="org.jboss.logging"/>
     <module name="org.jboss.vfs"/>
  </dependencies>
</module>

Source: acme-subsystem.zip

If you have further dependencies, you will add them as resources or dependencies manually.

The archetype also creates a configuration for the Maven Antrun Plugin that helps to generate the final module.xml for the distribution package:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-antrun-plugin</artifactId>
  <inherited>false</inherited>
  <version>1.6</version>
  <executions>
    <execution>
      <id>build-dist</id>
      <goals>
        <goal>run</goal>
      </goals>
      <phase>package</phase>
      <configuration>
        <target>
          <!-- Replace the '.' in ${module.name} with '/' to get its path  -->
          <tempfile property="temp.file" />
          <echo message="${module.name}" file="${temp.file}" />
          <replace file="${temp.file}" token="." value="/" />
          <loadfile srcfile="${temp.file}" property="module.path" />
          <delete file="${temp.file}" />
                   
          <delete dir="target/module" />
          <property name="module.dir" value="target/module/${module.path}/main" />
                   
          <copy file="src/main/resources/module/main/module.xml" tofile="${module.dir}/module.xml" />
          <copy file="target/${project.artifactId}.jar" todir="${module.dir}" />
                   
          <echo>Module ${module.name} has been created in the target/module directory. Copy to your JBoss AS 7 installation.</echo>
        </target>
      </configuration>
    </execution>
 </executions>
</plugin>

The positive aspect of this approach is that it comes for free. For small projects with no or just a few dependencies, this may all you need.

 

Any additional resources or artifacts may be deployed with the JBoss AS7 Deployment Plugin via the JBoss CLI. This is out of scope for this article, please refer to Complex Deployment and Resource Examples for more information on this topic.

Option 2: The imperative Approach

If you have to add more dependencies to your project you probably want to synchronize the information in your POM with that of the module.xml. On Stackoverflow Ryan Stewart shows how to do this with a couple of Groovy lines of code:

<plugin>
  <groupId>org.codehaus.gmaven</groupId>
  <artifactId>gmaven-plugin</artifactId>
  <version>1.3</version>
  <configuration>
    <source>
      def sw = new StringWriter()
      def xml = new groovy.xml.MarkupBuilder(sw)
      xml.module(xmlns:'urn:jboss:module:1.0', name:'ats.platform') {
        resources {
          project.runtimeClasspathElements.each {
            def path = it.find(".*?([\\w\\.-]*\\.jar)") { it[1] }
            !path?:'resource-root'(path:path)
          }
        }
      }
      println sw
    </source>
  </configuration>
</plugin>

Source: Generate an xml file with all dependencies with maven

 

Please refer to the author’s article on information on how to integrate this into your build process or go to his example POM directly.

This is a quick and smart solution to create a module.xml upon the dependencies declared in the POM. Due to its imperative way you may also extend this build script to configure additional information into it.

Option 3: The declarative Approach

To be honest, I have not tried the imperative approach. I’m a fan of declaring what I want to accomplish and have the build system figure out for me how to do it. Therefore I like the Maven way, where the imperative code can be outsourced to a plugin that can be reused in different builds. So this is the plugin configuration to create a complete modules folder:

<plugin>
  <groupId>de.smartics.maven.plugin</groupId>
  <artifactId>smartics-jboss-modules-maven-plugin</artifactId>
  <version>0.2.0</version>
  <executions>
    <execution>
      <id>create-modules-archive</id>
      <goals>
        <goal>create-modules-archive</goal>
      </goals>
      <phase>package</phase>
    </execution>
  </executions>
</plugin>

And this is the modules declarations file that controls the creation of the modules:

<modules xmlns="http://smartics.de/ns/jboss-modules-descriptor/1">
  <module name="$g1">
    <match>
      <includes>
        <include>
          <groupId>(de.smartics.exceptions)</groupId>
        </include>
      </includes>
    </match>
  </module>
</modules>

This is just a simple example. Real modules descriptors usually get larger the more control you impose on the generation process (e.g. export or service directives).

By externalizing the modules declarations, they can be easily reused (since writing the whole matching and applying rules over and over again is ridiculous and dissatisfying).

<plugin>
  <groupId>de.smartics.maven.plugin</groupId>
  <artifactId>smartics-jboss-modules-maven-plugin</artifactId>
  <version>0.2.0</version>
  <executions>
    <execution>
      <id>create-modules-archive</id>
      <goals>
        <goal>create-modules-archive</goal>
      </goals>
      <phase>package</phase>
    </execution>
  </executions>
  <dependencies>
    <dependency>
      <groupId>de.smartics.config</groupId>
      <artifactId>config-smartics-jboss-modules</artifactId>
      <version>2.0.1</version>
    </dependency>
  </dependencies>
</plugin>

The example above shows how to add external modules descriptors from config-smartics-jboss-modules to your build.

So the positive side effects are reuse of code and declarations. This has the implied benefits that you do not have to test the configuration that builds your code (since this is the responsibility of the developers of the plugin). This approach also allows to have common dependencies as individual modules. This is because they are not necessarily added as resource root, but as dependencies. If you have a larger library, especially if it provided types that are used by other modules in their interfaces, it is useful to have this library as a separate module. This use case can be handled easily with the plugin.

The drawback compared to the imperative approach is, that you have to learn another DSL – here is the XSD for the modules descriptors. This is in situation quite cumbersome, where you use this language only occasionally. A multi-purpose approach with a script may come handier.

Conclusion

On small projects with no or very few dependencies you might use approach one. But usually things get bigger so that an automated approach that syncs the module.xml with the POM information is mandatory. If you want to use the imperative or the declarative approach is merely a matter of taste. The first may be easier and most pragmatic (in the best sense of the word), while the latter may be easier to distribute to cope with larger projects.

Please refer to the articles on JBoss modules on this blog or to the smartics JBoss Modules Maven Plugin’s homepage for more information on this topic.


Link

Link

Posts