2

I'm working on automatically deploying to a remote JBoss AS 7.1.1 server from a Jenkins build server as part of a build pipeline and have a small jar file that I call from ant (based on this).

My question is how do I find out if an application is already installed? Doing a deploy plan will fail if the application is already deployed(I could catch the exception that's thrown but that's not great).

Ondra Žižka
  • 43,948
  • 41
  • 217
  • 277
blank
  • 17,852
  • 20
  • 105
  • 159

2 Answers2

3

You can read the resource before doing the deploy. From there you can either redploy it or do nothing.

Here is an example that would work on a standalone server.

private boolean exists(final ModelControllerClient client, final String deploymentName) {
    final ModelNode op = new ModelNode();
    op.get(OP).set("read-children-names");
    op.get("child-type").set(ClientConstants.DEPLOYMENT);
    final ModelNode result;
    try {
        result = client.execute(op);
        // Check to make sure there is an outcome
        if (result.hasDefined(ClientConstants.OUTCOME)) {
            if (result.get(ClientConstants.OUTCOME).asString().equals(ClientConstants.SUCCESS)) {
                final List<ModelNode> deployments = (result.hasDefined(ClientConstants.RESULT) ? result.get(ClientConstants.RESULT).asList() : Collections.<ModelNode>emptyList());
                for (ModelNode n : deployments) {
                    if (n.asString().equals(deploymentName)) {
                        return true;
                    }
                }
            } else if (result.get(ClientConstants.OUTCOME).asString().equals(ClientConstants.FAILED)) {
                throw new IllegalStateException(String.format("A failure occurred when checking existing deployments. Error: %s",
                        (result.hasDefined(ClientConstants.FAILURE_DESCRIPTION) ? result.get(ClientConstants.FAILURE_DESCRIPTION).asString() : "Unknown")));
            }
        } else {
            throw new IllegalStateException(String.format("An unexpected response was found checking the deployment. Result: %s", result));
        }
    } catch (IOException e) {
        throw new IllegalStateException(String.format("Could not execute operation '%s'", op), e);
    }
    return false;
}

If you're using maven, there is a maven plugin you could use too.

James R. Perkins
  • 16,800
  • 44
  • 60
  • No maven, just ant. Thanks for that will try it out tomorrow. Where's the documentation for this kind of thing? – blank Mar 14 '12 at 18:59
  • @BedwyrHumphreys Most of it is here https://docs.jboss.org/author/display/AS71/Management+API+reference. Other that you just kind have to explore the structure. You can see an overview if you execute $JBOSS_HOME/bin/jboss-cli.sh --connect "/:read-resource" >> output.txt – James R. Perkins Mar 15 '12 at 00:11
  • Couple of points - I think op.get(OP) should be op.get(ClientConstants.OP) and ClientConstants.FAILED doesn't seem to exist in org.jboss.as.controller.client.helpers.ClientConstants – blank Mar 15 '12 at 07:54
  • Oops, nice catch. Sorry about that I copied and pasted from some other code :-) – James R. Perkins Mar 15 '12 at 15:12
  • Yes, that's where I mostly copied it from. I tried to modify to work, but clearly I missed some things. But hey, I did write the maven plugin ;-) – James R. Perkins Mar 26 '12 at 15:28
0

An alternative:

ModelNode res = AS7CliUtils.executeRequest("/deployment=* /:read-resource", ctx.getAS7Client() );

{
    "outcome" => "success",
    "result" => [{
        "address" => [("deployment" => "jboss-as-wicket-ear-ear.ear")],
        "outcome" => "success",
        "result" => {
            "content" => [{"hash" => bytes { ... }}],
            "enabled" => true,
            "name" => "jboss-as-wicket-ear-ear.ear",
            "persistent" => true,
            "runtime-name" => "jboss-as-wicket-ear-ear.ear",
            "subdeployment" => {
                "jboss-as-wicket-ear-ejb.jar" => undefined,
                "jboss-as-wicket-ear-war.war" => undefined
            },
            "subsystem" => {"datasources" => undefined}
        }
    }]
}

JBoss AS CLI client lib contains some API for that, can't find it right now.

This is a primitive implementation of query parsing (doesn't support nested values and doesn't care about escaping etc.).

/**
 *  Parse CLI command into a ModelNode - /foo=a/bar=b/:operation(param=value,...) .
 * 
 *  TODO: Support nested params.
 */
public static ModelNode parseCommand( String command ) {
   return parseCommand( command, true );
}
public static ModelNode parseCommand( String command, boolean needOp ) {
    String[] parts = StringUtils.split( command, ':' );
    if( needOp && parts.length < 2 )  throw new IllegalArgumentException("Missing CLI command operation: " + command);
    String addr = parts[0];

    ModelNode query = new ModelNode();

    // Addr
    String[] partsAddr = StringUtils.split( addr, '/' );
    for( String segment : partsAddr ) {
        String[] partsSegment = StringUtils.split( segment, "=", 2);
        if( partsSegment.length != 2 )  throw new IllegalArgumentException("Wrong addr segment format - need '=': " + command);
        query.get(ClientConstants.OP_ADDR).add( partsSegment[0], partsSegment[1] );
    }

    // No op?
    if( parts.length < 2 )  return query;

    // Op
    String[] partsOp = StringUtils.split( parts[1], '(' );
    String opName = partsOp[0];
    query.get(ClientConstants.OP).set(opName);

    // Op args
    if( partsOp.length > 1 ){
        String args = StringUtils.removeEnd( partsOp[1], ")" );
        for( String arg : args.split(",") ) {
            String[] partsArg = arg.split("=", 2);
            query.get(partsArg[0]).set( unquote( partsArg[1] ) );
        }
    }
    return query;
}// parseCommand()
Ondra Žižka
  • 43,948
  • 41
  • 217
  • 277