How to discover WildFly resources programmatically

This tutorial will help you to create some advanced CLI scripts programmatically from Java. We will focus in particular on discovering Domain resources (such as Host, Servers, Server Groups and their deployment.

In this tutorial we have already illustrated some examples of interaction with the CLI from Java. Essentially you will just need to include in your classpath the following dependencies so that you can access org.jboss.cli and org.jboss.dmr packages.

The main class that we will use is the org.jboss.as.cli.CommandContext which is able to issue commands as you would do in the CLI shell. Let’s see an example which shows how to retrieve the list of applications deployed on main-server-group:

package browse;

  
import java.io.IOException;
import org.jboss.as.cli.CommandContext;
import org.jboss.as.cli.CommandContextFactory;
import org.jboss.as.cli.CommandFormatException;
import org.jboss.as.cli.CommandLineException;
import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.dmr.ModelNode;

public class CLIDomain {
       public static void main(String[] args) throws CommandLineException, IOException
   {
      String domainController = "localhost";
      int domainPort = 9990;

      CommandContext ctx = CommandContextFactory.getInstance().newCommandContext("admin", "Password1!".toCharArray());
      ctx.connectController(domainController, domainPort);
      ModelNode cliCommand = null; 
      try {
                String request1="/server-group=main-server-group:read-children-names(child-type=deployment)";
                cliCommand = ctx.buildRequest(request1);
                String output = executeCommand(ctx,cliCommand);
          
      } catch (CommandFormatException e) {
                e.printStackTrace();
      } 
            
      ctx.disconnectController();
   }

   public static String executeCommand(CommandContext ctx,ModelNode modelNode) {   
          
         ModelControllerClient client = ctx.getModelControllerClient();
         if(client != null) {
            try {
                  ModelNode response = client.execute(modelNode);
                  System.out.println(response);
                  return (response.toJSONString(true));
            } catch (IOException e) {
                e.printStackTrace();
            }
         } else {
              System.out.println("Connection Error! The ModelControllerClient is not available.");
        }
         return null;
    }
  }

As you can see we are connecting to the Domain controller through the port 9990, therefore this example is fit for WildFly 8 (or newers). If you are using EAP 6 just change the port to 9999. As we have formerly deployed the application demows.war on the main-server-group, the result is the following one:

{
    "outcome" => "success",
    "result" => ["demows.war"]
}

With this knowledge, it’s easy to build a simple class which discovers the Domain Resources, such as the list of Hosts and the list of Servers defined within it.

Here is a quick example:

package browse;
   
import com.google.gson.Gson;
import java.io.IOException;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import org.jboss.as.cli.CommandContext;
import org.jboss.as.cli.CommandContextFactory;
import org.jboss.as.cli.CommandFormatException;
import org.jboss.as.cli.CommandLineException;
import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.dmr.ModelNode;

public class CLIDomainDiscovery {

    static Gson gson = new Gson();

    public static void main(String[] args) throws CommandLineException, IOException {
        String domainController = "localhost";
        int domainPort = 9990;

        CommandContext ctx = CommandContextFactory.getInstance().newCommandContext("admin", "Password1!".toCharArray());
        ctx.connectController(domainController, domainPort);
        ModelNode cliCommand = null;
        try {
            // Get list of Hosts in the Domain
            String request1 = ":read-children-names(child-type=host)";
            cliCommand = ctx.buildRequest(request1);
            String hostJSON = executeCommand(ctx, cliCommand);

            List<String> listHost = parseJSONArray(hostJSON);

            for (String hostName : listHost) {
                System.out.println("--------- Host " + hostName);

                // Get list of Servers in the Host
                String request2 = "/host=" + hostName + ":read-children-names(child-type=server)";
                cliCommand = ctx.buildRequest(request2);
                String serverJSON = executeCommand(ctx, cliCommand);
                List<String> listServers = parseJSONArray(serverJSON);

                for (String server : listServers) {

                    // Get port-offset of each Server
                    String request3 = "/host=master/server-config=" + server + ":read-attribute(name=socket-binding-port-offset)";
                    cliCommand = ctx.buildRequest(request3);
                    String portJSON = executeCommand(ctx, cliCommand);
                    String port = parseJSONString(portJSON);
                    System.out.println("---------------- Server " + server + " port " + port);
                }
            }

        } catch (CommandFormatException e) {
            e.printStackTrace();
        }

        ctx.disconnectController();
    }

    public static String executeCommand(CommandContext ctx, ModelNode modelNode) {

        ModelControllerClient client = ctx.getModelControllerClient();
        if (client != null) {
            try {
                ModelNode response = client.execute(modelNode);
                return (response.toJSONString(true));
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            System.out.println("Connection Error! The ModelControllerClient is not available.");
        }
        return null;
    }

    private static List<String> parseJSONArray(String JSON) {
        JsonArray obj = gson.fromJson(JSON, JsonArray.class);

        return obj.getResult();

    }

    private static String parseJSONString(String JSON) {
        JsonString obj = gson.fromJson(JSON, JsonString.class);

        return obj.getResult();

    }
}

As you can see we have enhanced our first example by including Google Gson which we use to parse the result’s Gson element which can be an array of String or a String. The code should be self-explainatory: we iterate through the list of Host, then through each Server available in the list where we collect the port-offset so that we have a mapping of our Domain.

The following Data Transfer Object are used to parse the JSON’s result into Java objects:

class JsonArray {

    List<String> result = new ArrayList<>();

    public List<String> getResult() {
        return result;
    }

}

class JsonString {

    String result;

    public String getResult() {
        return result;
    }

}

Once executed, you should see the following information, provided that you have started the default Domain configuration:

--------- Host master
---------------- Server server-one port 0
---------------- Server server-two port 150
---------------- Server server-three port 250

As an enhancement you could merge the deployment information available on the Server Groups with the information that we have acquired from our Domain topology.

If you feel like contributing with this complete example just email me ([email protected]), otherwise stay tuned and we will continue this in a second part!

Found the article helpful? if so please follow us on Socials