The JBoss EAP / Wildfly provides a powerful concept for management, configuration, and monitoring of the application server itself and its Java EE applications.
In the previous post we focused on some useful runtime metrics, which are of interest when monitoring your application server and applications. This post introduces the management clients provided by the JBoss EAP / Wildfly Application Server to manage and configure server instances.
Regardless which client you choose to manage your server instances, all changes are persistent in the XML configuration file with a consistent state and, as fallback, all changes are versioned in the configuration history directory of the application server. By default all remote connections are secured.
The management concept is based on the detyped management API. All management clients of the application server use this detyped management API to interact with the server. This library is called jboss-dmr. The primary class is the ModelNode as basic type. The ModelNode is a generic wrapper for the representation of the manageable resources of the application server. The resources are identifiable by unique addresses. All ressources provides generic operations, such as wirte or read operations.
Command Line Interface (CLI)
The Command Line Interface (CLI) is the most powerful management client to manage domain and standalone server. It provides a lot of convenient operations and a Tab-completion.
The CLI is launched with the jboss-cli.sh or jboss-cli.bat script located in the bin directory of the application server.
$ ./bin/jboss-cli.sh You are disconnected at the moment. Type 'connect' to connect to the server or 'help' for the list of supported commands. [disconnected /] connect [standalone@localhost:9990 /]
By default, the CLI connects itself to localhost on port 9990. Connections to a remote server are also possible, by adding the host and port as additional parameter.
$ ./bin/jboss-cli.sh You are disconnected at the moment. Type 'connect' to connect to the server or 'help' for the list of supported commands. [disconnected /] connect 192.168.1.1:9990 Authenticating against security realm: ManagementRealm Username: admin Password: [standalone@192.168.1.1:9990 /]
CLI commands are an ordered map with addresses of resources and an operation.
/address=name/child=name/:operation(param1=value)
The following is an example of a CLI command to read the full configuration with runtime and default values and all child resources from the subsystem undertow of the server resource:
[standalone@localhost:9990 /] /subsystem=undertow/server=default-server/ :read-resource(include-defaults=true, include-runtime=true, recursive=true) { "outcome" => "success", "result" => { "default-host" => "default-host", "servlet-container" => "default", "ajp-listener" => undefined, "host" => {"default-host" => { "alias" => ["localhost"], "default-web-module" => "ROOT.war", "filter-ref" => { "server-header" => {"predicate" => undefined}, "x-powered-by-header" => {"predicate" => undefined} }, "location" => {"/" => { "handler" => "welcome-content", "filter-ref" => undefined }}, "setting" => undefined }}, "http-listener" => {"default" => { "allow-encoded-slash" => false, "allow-equals-in-cookie-value" => false, "always-set-keep-alive" => true, "buffer-pipelined-data" => true, "buffer-pool" => "default", "certificate-forwarding" => false, "decode-url" => true, "enabled" => true, "max-buffered-request-size" => 16384, "max-cookies" => 200, "max-header-size" => 51200, "max-headers" => 200, "max-parameters" => 1000, "max-post-size" => 10485760L, "proxy-address-forwarding" => false, "receive-buffer" => undefined, "record-request-start-time" => false, "redirect-socket" => "https", "send-buffer" => undefined, "socket-binding" => "http", "tcp-backlog" => undefined, "tcp-keep-alive" => undefined, "url-charset" => "UTF-8", "worker" => "default" }}, "https-listener" => undefined } }
In addition the Command Line Interface supports some nice features, such as Batch-Mode, Non-interactive Mode with CLI-scripts, and a command history.
CLI scripting
The CLI can also be used with any JVM-based scripting language, such as Groovy, Jython, etc. The source code below shows a simple Groovy script that connects to a local server and executes a CLI commando to read the current server state.
import org.jboss.as.cli.scriptsupport.* cli = CLI.newInstance() cli.connect("localhost", 9990, "admin", "password".toCharArray()) result = cli.cmd(":read-attribute(name=server-state) ") response = result.getResponse() serverstate = response.get("result") println("Current server state: " + serverstate) cli.disconnect()
To execute the script the jboss-cli-client.jar must be added to the classpath.
groovy -cp bin/client/jboss-cli-client.jar cliscripting.groovy Current server state: "running"
The CLI API can also be used in Java programs.
RESTful Management Interfaces
Another management interface are the RESTful Interfaces with a JSON representation of the mode node. The REST API is accessible through the context-root management. The API supports GET requests to execute read only operations and POST request to execute write and read operations.
curl --digest http://localhost:9990/management/ -u admin
The default operation of a GET request on a resource is read-resource. Other read operation can be executed via query params, as shown in the example below.
curl --digest 'http://localhost:9990/management/subsystem/ejb3/?operation=attribute&name=default-security-domain' -u admin Enter host password for user 'admin': "other"
The API supports all generic operation with the read prefix. Parameters can be passed to the operation with query params. The query parameter ?json.pretty formats the JSON String and makes the response body more human readable.
$ curl http://localhost:9990/management/?json.pretty Enter host password for user 'admin': { "management-major-version" : 2, "management-micro-version" : 0, "management-minor-version" : 1, "name" : "test", "namespaces" : [], "product-name" : null, "product-version" : null, "profile-name" : null, "release-codename" : "Kenny", "release-version" : "8.1.0.Final", "schema-locations" : [], "core-service" : { "management" : null, "service-container" : null, "module-loading" : null, "server-environment" : null, "platform-mbean" : null, "patching" : null }, "deployment" : {"web-application-example.ear" : null}, …
To execute commands that change the configuration, POST requests can be executed. The body payload of the POST request is the node representation as a JSON String. The node representation includes the operation, parameters, and the address of the node resource.
The following request is an example to change the value of the default transaction timeout. This operation also writes the changes to the XML configuration file.
$ curl --digest http://localhost:9990/management --header "Content-Type: application/json" -d '{"operation":"write-attribute", "name":"default-timeout", "value":"600", "address":["subsystem","transactions"]}' -u admin Enter host password for user 'admin': {"outcome" : "success", "response-headers" : {"operation-requires-reload" : true, "process-state" : "reload-required"}}
The resources can only identified with the address in the model node representation and not with the URI.
Web-Console
The JBoss EAP / Wildfly Application Server comes in addition with a Web-based Console. The console can be accessed via the same port as the other management interfaces. The URL is http://host:9990/console. The console offers intuitive user interfaces for configuration tasks, management of host, and server instances and UIs for operational tasks.
The Web-Console is a GWT-based application. It interacts with the server through the REST-based interfaces. The only difference is that the Web-Console uses the DMR-specific representation of the model node as content-type.
JMX Management Beans
By default all resources are exposed as JMX Management Bean with the ObjectName jboss.as:*. These MBeans can be accessed, for example, with the JConsole or programmatically.
The Wildfly Application Server provides the script jconsole.sh to start the JConsole with the Wildfly client libraries. The script is located in the bin directory of the application server. The client libraries are necessary to connect the JConsole with a remote Wildfly JVM process via a JMX service URL and the remoting-jmx protocol. The JVM process does not need to be started with additional JVM options.
In standalone mode the connection is established through the management endpoint and secured with the ManagementRealm. The JMX service URL to connect the JConsole with a server running in standalone mode is: service:jmx:remoting-jmx://{management_interface}:{http-management-port}
Connecting to server instances, that are managed in a domain, requires to establish a connection through the public interfaces and the HTTP port. This requires the following configuration of the subsystem jmx in the assigned profile of the server instance:
[domain@localhost:9990 /]/profile=default/subsystem=jmx/remoting-connector=jmx :add(use-management-endpoint=false)
In this case the connection is secured with the ApplicationReam and Application User.
The JMX service URL to connect the JConsole with a server that is managed within a domain is: service:jmx:remoting-jmx://{public_interface}:{http-port}
Java API
The Wildfly Application server offers in addition a Java API to implement a custom client. The class org.jboss.as.controller.client.ModelControllerClient implements a factory to create a client and establish a connection to a server instance.
The following implementation is a simple example for the Java API to connect with a server instance and execute an operation that is wrapped with the org.jboss.dmr.ModelNode:
import java.io.IOException; import java.net.InetAddress; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.sasl.RealmCallback; import org.jboss.as.controller.client.ModelControllerClient; import org.jboss.dmr.ModelNode; public class Main { public static void main(final String[] args) throws Exception { ModelControllerClient client = ModelControllerClient.Factory.create( InetAddress.getByName("localhost"), 9990, new CallbackHandler() { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback current : callbacks) { if (current instanceof NameCallback) { NameCallback ncb = (NameCallback) current; ncb.setName(args[0]); } else if (current instanceof PasswordCallback) { PasswordCallback pcb = (PasswordCallback) current; pcb.setPassword(args[1].toCharArray()); } else if (current instanceof RealmCallback) { RealmCallback rcb = (RealmCallback) current; rcb.setText(rcb.getDefaultText()); } else { throw new UnsupportedCallbackException(current); } } } }); ModelNode operation = new ModelNode(); operation.get("operation").set("read-attribute"); operation.get("name").set("servlet-container"); ModelNode address = operation.get("address"); address.add("subsystem", "undertow"); address.add("server", "default-server"); System.out.println("ModelNode operation"); System.out.println(operation.toJSONString(false)); try { ModelNode returnVal = client.execute(operation); System.out.println("Result:"); System.out.println(returnVal.toJSONString(false)); } finally { client.close(); System.exit(1); } } }
Below the console output of the custom client implementation:
$ java -cp "../wildfly-8.1.0.Final/bin/client/jboss-cli-client.jar:." Main admin password ModelNode operation: { "operation" : "read-attribute", "name" : "servlet-container", "address" : [ { "subsystem" : "undertow" }, { "server" : "default-server" } ] } Result: "default"
Summary
The application server provides many ways for the management, monitoring and configuration. This allows the seamless integration of the management interfaces in existing DevOps tools and monitoring tools. Especially the REST interfaces allow the integration in heterogeneous environments. With the generic management model, it is possible to obtain a complete overview of the current state and the current configuration of the application server. Remember the good old days when we had to configure thousands XML files.
Any questions or feedback? If so, feel free to comment on this post or contact me via email: heinz.wilming@akquinet.de