How to deploy to JBoss EAP 7 with Gradle, Cargo, and Jenkins

It took me quite a while to get my Java EE 7 application automatically deployed to a target JBoss EAP 7 server from within Jenkins using Gradle as the build tool and Cargo for managing the deployment. So here’s my final solution for you to use! đŸ˜‰

build.gradle

dependencies {
    classpath 'com.bmuschko:gradle-cargo-plugin:2.2.3'
}

apply plugin: 'com.bmuschko.cargo'

dependencies {
    cargo "org.codehaus.cargo:cargo-core-uberjar:1.5.0",
          "org.codehaus.cargo:cargo-ant:1.5.0",
          "org.wildfly:wildfly-controller-client:8.2.1.Final"
}

cargo {
    containerId = 'wildfly10x'

    deployable {
        context = 'MyContext'
    }

    remote {
        hostname = '10.1.1.1'
        username = 'remote'
        password = 'remote'

        containerProperties {
            property 'cargo.jboss.management-http.port', 9990
        }
    }
}

Jenkinsfile

stage("Deployment") {
    bat('gradlew cargoRedeployRemote --stacktrace')
}

Deploying to JBoss EAP 7 is the same as deploying to Wildfly 10

First of all, there’s no Cargo containerId for JBoss EAP 7. However, you can use Wildfly 10 instead, as you can read here: Codehaus Cargo – WildFly 10.x:

The WildFly 10.x container can be used with the JBoss Enterprise Application Platform (EAP) version 7; i.e. the version released in May 2016

Finding the right versions of Cargo and its Gradle plugin

You need to use the right versions of Cargo and the Cargo Gradle plugin. I’ve found that version 2.2.3 of the Gradle plugin and version 1.5.0 of Cargo itself work fine with Wildfly 10/JBoss EAP 7 (see Execution failed for task ‘:cargoRunLocal’. #152). The latest versions as of this writing of Cargo (1.6.6) and the plugin (2.3) also work in my environment.

If the versions don’t work correctly, you might get an error like this:

> gradle cargoRedeployRemote

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':cargoRedeployRemote'.
> org.codehaus.cargo.container.ContainerException: Cannot create configuration. 
There's no registered configuration for the parameters (container [id = [wildfly10x],
type = [remote]], configuration type [runtime]). Actually there are no valid types
registered for this configuration. Maybe you've made a mistake spelling it?

Deploying to JBoss EAP 7 with the Wildfly Controller Client

Cargo needs a controller client to be able to deploy artifacts to a remote Wildfly 10/JBoss EAP 7 as you can read here: Codehaus Cargo – JBoss Remote Deployer. I’ve found that version 8.2.1.Final of the Wildfly Controller Client org.wildfly:wildfly-controller-client works fine. However, the latest version of org.wildfly.core:wildfly-controller-client (3.0.10.Final) also works.

You need to add it to cargo.dependencies in your build script as shown above. Otherwise you might end up with an error message like this:

> gradle cargoRedeployRemote

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':cargoRedeployRemote'.
> org.codehaus.cargo.container.ContainerException: Failed to create deployer
with implementation class org.codehaus.cargo.container.wildfly.WildFly10xRemoteDeployer
for the parameters (container [id = [wildfly10x]], deployer type [remote]).

Changing the JBoss management port

In my case, the target JBoss server uses a different port for remote management. The default is 9990, but I use 19990. Simply adding cargo.port = 19990 to the build file didn’t cut it:

> org.codehaus.cargo.util.CargoException: HTTP request failed, response code: -1,
response message: java.net.ConnectException: Connection refused: connect, response body: null

And by adding --info to the call to gradle I got:

Starting action 'redeploy' for remote container 'wildfly10x' on 'http://localhost:9990'

It took me a while to find the correct way of telling Cargo to use the custom port. The Cargo documentation (see Codehaus Cargo – JBoss Remote Deployer) states:

WildFly 8.x, 9.x and 10.x use the cargo.jboss.management-http.port port

However, setting this property isn’t as easy as adding cargo.jboss.management-http.port = 19990 to your build file, because this results in:

(cargo.jboss.management - http.port) is a binary expression, but it should be a variable expression

And adding the following lines…

cargo {
    jboss {
        management-http {
            port = 19990
        }
    }
}

…leads to a different error:

> Could not find method jboss() for arguments [cargo_61gwz9gjyqje40dvlr47klkas$_run_closure3$_closure6@22ff8f9]
on object of type com.bmuschko.gradle.cargo.convention.CargoPluginExtension.

Finally, I’ve found the right way of setting the property in this article: Local redeployment #123

containerProperties {
    property 'cargo.jboss.management-http.port', 19990
}

However, if you use the newest versions of Cargo and the plugin cargo.port = 19990 seems to work again.

Example build.gradle using the latest versions of Cargo and the plugin

dependencies {
    classpath 'com.bmuschko:gradle-cargo-plugin:2.3'
}

apply plugin: 'com.bmuschko.cargo'

dependencies {
    cargo "org.codehaus.cargo:cargo-core-uberjar:1.5.0",
          "org.codehaus.cargo:cargo-ant:1.5.0",
          "org.wildfly.core:wildfly-controller-client:3.0.10.Final"
}

cargo {
    containerId = 'wildfly10x'
    port = 9990

    deployable {
        context = 'MyContext'
    }

    remote {
        hostname = '10.1.1.1'
        username = 'remote'
        password = 'remote'
    }
}

Automating Your Natural Build Process – Legacy Coder Podcast #2

Automating Your Natural Build Process

How can you automate the build process for your application based on Software AG’s Adabas and Natural? I talk about our journey towards a completely automated build from scratch after each push to Git in the second episode of the Legacy Coder Podcast.

How to automate the build process for an Adabas/Natural application

  • Why would I want to automate the build process?
    • What hurts should be done more often!
    • No more long integration phases before each release!
    • You’ll get a faster time to market for new features.
    • You can get rid of knowledge silos concerning the release of your application.
  • What steps may need to be automated?
    • Upload (transfering the Natural source code to the server)
    • Compile (CATALOG, STOW, CATALL etc.)
    • Unit Tests (e.g. with NatUnit, see Unit Testing Natural Applications)
    • Deployment (the actual release of the new version on the target stage)
    • Restarting RPC servers or whatever individual steps might be necessary in your environment
  • What tools are available for automating the Natural build process?
    • It all starts with Git or any other versioning control system (Subversion, TFS, CVS).
    • You can use Jenkins for Continuous Integration.
    • Software AG’s command line tools (ftouch etc.) can be scripted.
    • Even the CATALL can be scripted by calling into Natural BATCHMODE.
    • NaturalONE’s ant scripts for uploading and compiling Natural sources.
    • Any additional tool that you might need (Bash scripts etc.)
  • How can I get started?
    • Make your project fully compilable. There can be no compile errors whatsoever.
    • Start with a single step, e.g. automate only the compile step first.
    • Script everything (e.g. with Bash) right from the beginning. You can easily call these scripts from Jenkins later on.
    • Hook Jenkins up to your source code repository. It provides plugins for every major system (e.g. Git, Subversion).
    • Try to automate the build with Jenkins. It’s completely free and easy to setup. Perhaps ask a Java colleague if he can help you.
  • How can you go even further than what’s possible today?
    • Try to automate imports of Adabas data that’s important for your application.
    • Try to automate Adabas schema migrations.
    • Implement feature toggles for more fine grained control over your application’s functionality at runtime.

Recommended reading

Links