Masaryk University Faculty of Informatics

WildFly 8 Self Monitor subsystem

Master Thesis

Bc. Vojtˇech Schlemmer

Brno, autumn 2014 Declaration

I hereby declare that this paper is my original authorial work, which I have created entirely by myself. All sources, references and literature used or excerpted during elaboration of this work are properly cited and listed in complete reference to the due source.

Bc. Vojtˇech Schlemmer

Advisor: RNDr. Adam Rambousek

ii Acknowledgement

I would like to thank Onˇrej Ziˇzka,ˇ my technical supervisor from , for sharing his experience in the field of developing JBoss AS and for his highly professional consultations. I’m also grateful to my advisor RNDr. Adam Rambousek for his comments and Barbora Schlemmerov´afor gram- mar corrections. Finally I would like to thank my family and friends for their support.

iii Abstract

The aim of this thesis is to analyze the architecture of WildFly applica- tion server with respect to its resources and related metrics, to design and implement a subsystem for monitoring the metrics at selected intervals to a selected storage type and integrate the subsystem to WildFly 8. The subsystem provides tools to retrieve the monitored values along with aggre- gated statistics and is configurable via the server’s command line interface (CLI).

iv Keywords

WildFly AS, middleware, metrics, monitoring, WildFly subsystem, statis- tics

v Contents

1 Introduction1 1.1 Motivation...... 1 1.2 Aim of the thesis...... 2 1.3 Structure of the thesis...... 2

2 Application servers3 2.1 Types of ASs...... 3

3 Wildfly 85 3.1 Motivation for using Wildfly 8...... 5 3.2 Wildfly and JBoss versions overview...... 6 3.3 Operating modes...... 6 3.4 Basic administration...... 7 3.4.1 Command line interface...... 7 3.4.2 WildFly resources model...... 7 3.4.3 Operations...... 8 3.4.4 Attributes...... 9 3.4.5 Children...... 10 3.5 WildFly architecture...... 10 3.5.1 Modularity...... 10 3.5.2 Metrics - runtime attributes...... 10

4 Self Monitor subsystem implementation 12 4.1 Motivation...... 12 4.2 Extending WildFly...... 12 4.3 Requirements...... 13 4.4 Analysis and design...... 13 4.4.1 Basic entities...... 14 4.4.2 Application structure...... 16 4.4.3 Custom CLI operations...... 17 4.4.4 Metric monitoring...... 18 4.4.5 Selfmonitor Console...... 19 4.5 Implementation...... 22 4.5.1 The detyped API...... 22 4.5.2 Access to the server’s management API...... 23 4.5.3 Scanning the model...... 23 4.5.4 Writing the metrics to the model...... 24 4.5.5 Running a Quartz job for each enabled metric..... 24 4.5.6 Storing the metrics’ values...... 24

vi CONTENTS

4.5.7 Selfmonitor Console...... 25 4.5.8 Testing...... 26 4.5.9 Problems during implementation...... 27

5 Using Self Monitor subsystem 29 5.1 Subsystem configuration...... 29 5.1.1 Configuring standalone.xml ...... 29 5.1.2 Accessing the subsystem via CLI...... 30 5.2 Let’s start monitoring...... 31 5.2.1 The read-metrics custom operation...... 31 5.3 Retrieving the values...... 32 5.3.1 The read-all-values operation...... 32 5.3.2 The read-value operation...... 33 5.3.3 The read-values operation...... 33 5.3.4 The value-occured operation...... 34 5.4 The Selfmonitor Console demonstration...... 34 5.4.1 Deploying application to WildFly...... 34 5.4.2 Monitoring a metric...... 35 5.4.3 Displaying the values in the console...... 35

6 Conclusion 38 6.1 The result of the implementation...... 38 6.2 Extending the subsystem in the future...... 38 6.2.1 Development of the Selfmonitor Console...... 38 6.2.2 Refactor the subsystem configuration...... 40 6.2.3 Involve the Selfmonitor Console into the server’s Web Management Interface...... 40

7 Appendix 44

vii 1 Introduction

The solution of problems encountered in large enterprises is the mis- sion of Enterprise applications (Java EE)1. Developing such applica- tions involves tasks that need to be delegated to third party software so that the developer could focus on the application specific issues. I will not list all possible tasks, but for instance:

• Data management - handling tons of structured data with need of concurrent access

• Security - providing authentication and authorization mechanisms across the whole application

• Web services - providing communication over network

• Mail services - handling sending and receiving emails

• Clustering - gaining the computing power

• Load balancing - distributing workload across multiple computing re- sources

Such a third party software is usually part of a middleware layer and is called (AS). In order to provide such a large amount of functionalities, an AS has to be complex and efficient. This opens a wide field to cover and we will take a look inside of it in the following chapters.

1.1 Motivation

This thesis focuses on the widely used AS called WildFly, its ser- vices and statistics. Java EE applications deployed to WildFly AS may use functionalities structured into modules and each module provides certain statistics describing its current state. Let’s imagine for a moment that you are a developer working on a Java EE application deployed to WildFly AS. Your application implements some persistent data storage, handles client http requests, runs on a cluster and includes several more features. It is essential that the app is scalable, reliable, secure and works fluently and effectively under a high load. This is where services of an AS are useful. But it would be also nice to see what 1Java EE is a platform designed to simplify development of big distributed applica- tions by providing interfaces with which the development effort is decreased and a better performance is achieved [1].

1 1. Introduction is going on under the hood of each service and retrieve certain information giving a deeper insight about application behavior.

1.2 Aim of the thesis

The aim of this thesis is to describe the main features of AS, map current Java EE open-source ASs, look inside WildFly AS with respect to measurable metrics and implement a subsystem that would provide moni- toring of the metrics according to configuration.

1.3 Structure of the thesis

The second chapter gives a basic description of what AS stands for and what features it provides. The third chapter is an introduction to WildFly 8. Besides a basic description, it provides an easy guide to administration and describes the architecture of the AS. The fourth chapter contains details about analyzing, designing and implementing a Self Monitor subsystem for WildFly 8 and the following fifth chapter is a manual of how to include, configure and use it with WildFly. The sixth chapter is a conclusion of what the subsystem brought to the community and what the plans of future improvements of this subsystem are.

2 2 Application servers

Considering Java EE world, AS is an environment where Java EE applications can run. It provides services via service containers [2]. The list of service containers available to developers of Java EE applications is comprehensive. For better view here is a list of several of them:

• Servlet container - presents front-end user interface

• Enterprise JavaBean container - manages back-end business logic

• Naming and directory interface - provides naming and directory func- tionality

• Message service - allows applications to create, send, receive and read messages

• Adapter service - allows access to non-Java or other non-managed services

• Security container

2.1 Types of ASs

When categorized with respect to source availability and scope, we get the following types of ASs (with a few examples along with each type) [3]:

• Open Source - full

– JBoss (WildFly) – Glassfish

• Open Source - only servlet container1

– Tomcat –

• Commercial

– WebSphere (IBM) – WebLogic (Oracle, formerly BEA)

1Servlet container presents the front-end user interface that in most cases involves HTTP protocol [2]

3 2. Application servers

When deciding which AS to choose, it’s good to take into account purpose and scope of the application deployed, what features it really needs. For instance a lightweight web application consisting of few beans (providing back-end functionality) and simple front-end doesn’t need to be deployed to a full featured WildFly AS, but would go just fine with a servlet container like Tomcat or Jetty. Some of the reasons for choosing WildFly for deploying complex Java EE application can be found in the first section of the following chapter.

4 3 Wildfly 8

WildFly 8 is the latest release in series of JBoss open-source appli- cation server offerings. It’s an exceptionally fast, lightweight and powerful implementation of Java Enterprise Edition 7 Platform specifications [4]. 1

3.1 Motivation for using Wildfly 8

Figure 3.1: The ASs popularity report from 2014 [5]

1A full list of Java EE 7 technologies available in WildFly 8 can be found at https: //docs.jboss.org/author/display/WFLY8/Getting+Started+Guide

5 3. Wildfly 8

Rebel Labs have been conducting research of the popularity of ASs every year since 2009, the 2014 ASs popularity report is shown on the Figure 3.1. Considering Tomcat only a servlet container, this gives us JBoss (now called WildFly) the most popular AS.

3.2 Wildfly and JBoss versions overview

JBoss can refer to several things. First, it refers to RedHat’s division focusing on open-source middleware development which profits from pro- viding support and trainings. Second, it refers to Java AS that facilitates developing and deploying Java EE applications. The direction of development of JBoss doesn’t follow a single line. After acquisition of JBoss in 2006 from and introduc- ing several versions of this community project, a new branch called JBoss Enterprise Application Platform (EAP) was released, which is a certified, rigorously tested, stable, supported platform for developing and deploying critical Java applications and services. It integrates code from JBoss.org AS/Clustering project, JBoss Framework and JBoss Seam Frame- work into a single distribution with a single patch and update stream and multi-year maintenance policy [6]. Current stable release of JBoss EAP is 6.3.0 (October 2014). Apart from JBoss EAP, development of JBoss AS continued simulta- neously and was open-source community-driven project with many features but did not provide 24x7 support as the JBoss EAP did. Since February 11th 2014 the project continues with a new name WildFly with the first stable release WildFly 8.0.0 Final. The word WildFly came out as a result of a public vote of JBoss com- munity and is a new name of JBoss AS. It is a direct continuation of the JBoss AS project. The purpose of renaming the community branch of AS was to reduce confusion and make it clear what is supported certified prod- uct (JBoss EAP) and what is a community open-source project (WildFly).

3.3 Operating modes

WildFly 8 can be booted into two different modes depending on the number of server instances to be managed: [7]

• managed domain - allows to run and manage a multi-server topology. It is suitable when multiple instances of the server needed. In such case it provides a common administration for all instances.

• standalone server - is appropriate when managing only a single server instance.

For demonstration puposes, everything in this thesis is referred to the standalone server, but would work the same on managed domain too, only each instance would need to be configured separately.

6 3. Wildfly 8

3.4 Basic administration

WildFly 8 offers three different approaches to configure and manage servers: a web interface, a command line interface and a set of XML config- uration files. Regardless of the approach chosen, the configuration is always synchronized across the different views and finally persisted to the XML files [7]. The command line interface (CLI) will be briefly described in this chapter.

3.4.1 Command line interface Depending on the , the CLI is launched using jboss- cli.sh or jboss-cli.bat located in the WildFly 8 bin directory. The server must be up and running by the time trying to connect to the CLI. The first thing to do after the CLI has started is to connect to a managed WildFly 8 instance. This is done using the command connect as shown in the Code 3.1.

./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 localhost:9990 [standalone@localhost:9990 /] Code 3.1: Connect to the server via CLI

Now the CLI is ready to accept commands. To see all the commands available type help, to quit the CLI type quit. There is also an option for sending commands to CLI in non-interactive mode via --command and -- commands arguments or by providing a file containing commands with --file argument.

3.4.2 WildFly resources model Resources in WildFly are stored in a tree structure of de-typed ad- dressable nodes where each node offers a set of operations to execute.

Figure 3.2: An example of a WildFly resource tree

The path to the node in the tree for a particular resource is its address. Each segment in a resource’s address is a key=value pair [7]:

7 3. Wildfly 8

• The key is the resource’s type, in the context of its parent. So, for example, the root resource of a standalone server has children of type subsystem, interface, socket-binding, etc.

• The value is the name of a particular resource of the given type, e.g. web or messaging for subsystems or http or https for web subsystem connectors.

The full address of a resource is an ordered list of key=value pairs that leads from the root of the tree to the resource. Typical notation is to separate the elements in the address with a ”/” and to separate the key and the value with an ”=”, for instance /subsystem=web/connector=http.

3.4.3 Operations The nodes’ operations are either common or node-specific and may ac- cept an arbitrary number of parameters. Here is a list of common operations available:

• add

• read-attribute

• read-children-names

• read-children-resources

• read-children-types

• read-operation-description

• read-operation-names

• read-resource

• read-resource-description

• remove

• validate-address

• write-attribute

To get the list of node’s operations available (together with node- specific), invoke the read-operation-names operation upon the node. The formal specification of an operation request is: [/node-type=node-name (/node-type=node-name)*] : operation-name [( [parameter-name=parameter-value (,parameter-name=parameter-value) *] )] Code 3.2: Formal specification of an operational request in WildFly

Based on that, an operation of reading the node /subsystem=transaction would be /subsystem=transaction:read-resource and its possible result is shown in the Code 3.3.

8 3. Wildfly 8

{ "outcome" => "success", "result" => { "default-timeout" => 300, "enable-statistics" => false, "enable-tsm-status" => false, "hornetq-store-enable-async-io" => false, "jdbc-action-store-drop-table" => false, "jdbc-action-store-table-prefix" => undefined, "jdbc-communication-store-drop-table" => false, "jdbc-communication-store-table-prefix" => undefined, "jdbc-state-store-drop-table" => false, "jdbc-state-store-table-prefix" => undefined, "jdbc-store-datasource" => undefined, "jts" => false, "node-identifier" => "1", "object-store-path" => "tx-object-store", "object-store-relative-to" => "jboss.server.data.dir", "path" => "var", "process-id-socket-binding" => undefined, "process-id-socket-max-ports" => 10, "process-id-uuid" => true, "recovery-listener" => false, "relative-to" => "jboss.server.data.dir", "socket-binding" => "txn-recovery-environment", "statistics-enabled" => false, "status-socket-binding" => "txn-status-manager", "use-hornetq-store" => false, "use-jdbc-store" => false, "log-store" => {"log-store" => undefined} } } Code 3.3: Result of an operation read-resource invoked upon the transaction subsystem

The format of the result is proprietary and is similar to JSON1.

3.4.4 Attributes Attributes represent a state of a resource. They have a name and a value and are listed when read-resource operation invoked upon the re- source [7]. In the Code 3.3 we can see attributes like default-timeout or node-identifier with values 300 and 1. A description of what each attribute stands for can be retrieved by executing operation /subsystem=transactions:read-resource-description. If there is an undefined value, it means either the attribute is not specified or the line represents a child resource.

1JSON (JavaScript Object Notation) is a lightweight data-interchange format easy for humans to read and write and easy for machines to parse and generate [8]

9 3. Wildfly 8

3.4.5 Children Each resource in the model may contain certain children types and each of the types may contain children themselves. To get a list of children types available we invoke the read-children-types operation and to get the list of children of a certain type we invoke the read-children-names(child- type=child-type) [7].

3.5 WildFly architecture

3.5.1 Modularity Functionalities provided by WildFly are organized into separate mod- ules, also called subsystems. Every library is a module, even deployments themselves are modules. Each module provides a certain API and may set dependencies on other modules. For instance, classes providing logging functionality are situated in logging subsystem, transaction related classes could be found in transaction subsystem, etc. Configuration of the modules along with the configuration of the whole AS resides in an XML file $WILDFLY HOME/standalone/configuration/ standalone.xml (in case of standalone server) and in $WILDFLY HOME/ domain/configuration/domain.xml and $WILDFLY HOME/domain/ configuration/host.xml (in case of managed domain). In order to configure the resources it is recommended to use CLI described in Section 3.4.1.

3.5.2 Metrics - runtime attributes There are plenty of attributes related to modules stored in the con- figuration files, but not all of them. There are attributes of certain type that are not located in the configuration files because their values change in time but can be accessed via CLI and they are called runtime attributes (metrics). For instance, let’s consider the aforementioned transaction subsystem. We can see the result of the read-resource operation in the Code 3.3, but it doesn’t include the metrics of the subsystem. To achieve this, let’s append (include-runtime=true) attribute at the end. So the operation would be /subsystem=transaction:read-resource(include-runtime=true) and its re- sult would be as follows: { "outcome" => "success", "result" => { "default-timeout" => 300, "enable-statistics" => false, "enable-tsm-status" => false, "hornetq-store-enable-async-io" => false, "jdbc-action-store-drop-table" => false, "jdbc-action-store-table-prefix" => undefined, "jdbc-communication-store-drop-table" => false, "jdbc-communication-store-table-prefix" => undefined,

10 3. Wildfly 8

"jdbc-state-store-drop-table" => false, "jdbc-state-store-table-prefix" => undefined, "jdbc-store-datasource" => undefined, "jts" => false, "node-identifier" => "1", "number-of-aborted-transactions" => 0L, "number-of-application-rollbacks" => 0L, "number-of-committed-transactions" => 0L, "number-of-heuristics" => 0L, "number-of-inflight-transactions" => 0L, "number-of-nested-transactions" => 0L, "number-of-resource-rollbacks" => 0L, "number-of-timed-out-transactions" => 0L, "number-of-transactions" => 0L, "object-store-path" => "tx-object-store", "object-store-relative-to" => "jboss.server.data.dir", "path" => "var", "process-id-socket-binding" => undefined, "process-id-socket-max-ports" => 10, "process-id-uuid" => true, "recovery-listener" => false, "relative-to" => "jboss.server.data.dir", "socket-binding" => "txn-recovery-environment", "statistics-enabled" => false, "status-socket-binding" => "txn-status-manager", "use-hornetq-store" => false, "use-jdbc-store" => false, "log-store" => {"log-store" => undefined} } } Code 3.4: Result of an operation read-resource invoked upon the transaction subsystem with metrics included

As we can see, there are more attributes than in the result of the simple read-resource operation, particularly those starting with ”number- of”. This way we are able to retrieve any metric from any resource of the AS.

11 4 Self Monitor subsystem implementa- tion

4.1 Motivation

As introduced in Section 3.5.2, metrics give us information about the inner state of certain AS’s resources. For instance, in the transaction subsys- tem we may want to ask for the current number of transactions or rollbacks. Or having an application deployed, we would like to know the status of the deployment, whether the status is OK, STOPPED or FAILED. As shown in the Code 3.4, the read-resource operation together with include-runtime= true attribute gives us this information. The problem is that AS holds only an actual value of a metric. There might be a moment when we would like to see how the metric’s value has been changed in time. For example, we would like to see in which moment the number of transactions increased sig- nificantly or what was the number of transactions yesterday in comparison with some other day, etc. Another nice example of a metric is server-state located in the root of the model. Value of this metric may be STARTING, RUNNING or RESTART REQUIRED and, again, we can ask for the actual value. But it would be nice to see, for example, at which point the server state changed from RUNNING to RESTART REQUIRED. To achieve this, a Self Monitor subsystem will be implemented. It will be an independent configurable WildFly module and will provide the ability of storing the metrics’ data and presenting them in user-friendly interface.

4.2 Extending WildFly

Since WildFly has a modular structure, every subsystem is a module located in $WILDFLY HOME/modules directory, even deployed applica- tion is a module. Implementation of WildFly Self Monitor subsystem will be a new module residing in that directory. Extending WildFly is straight- forward 1 and consists of extending basic classes of the AS’s model and creating a model subtree that provides the subsystem configuration.

1There is a step by step documentation available at https://docs.jboss.org/author/ display/WFLY8/Extending+WildFly+8

12 4. Self Monitor subsystem implementation

4.3 Requirements

Before creating a design of the subsystem, let’s take a look at the requirements. Here is a list of capabilities that the subsystem should have:

• Initially scan the whole AS’s model and provide a list of metrics avail- able for monitoring along with some information about each one of them. There should be a text information about what the metric rep- resents, an information about type of the data it holds, whether it is suitable for aggregation, where it resides in the model tree and in what interval it should store its value if enabled for monitoring.

• Easy enabling/disabling monitoring of a metric and changing its in- terval. Changing the interval should also be possible while the metric is being monitored without having to disable it.

• Provide an operation of listing enabled or disabled metrics.

• Store the values of the enabled metrics in a selected interval to a selected storage type. The storing procedures should not initialize a new thread for each metric, but should run in one common thread, even though the storing interval of the metrics may differ.

• Display stored values between two dates on demand or display all metric’s values stored so far.

• Provide functions upon the stored data - for example average value, median, minimal and maximal value in case the metric values are suitable for aggregation.

• Create a client web application that could be deployed to WildFly and that could visualize the stored data in a user-friendly UI.

4.4 Analysis and design

Everything in AS is configurable via CLI and so will be the Self Mon- itor subsystem. It will be appended to the server model and will have configurable storage type and a list of metrics. The storage type will be one of the following:

• relational database

• memory

The relational database option was chosen, because it is a mature and widely-used type of storage and is well supported in WildFly. The memory option was chosen as an alternative to the database storage because of its speed and is beneficial in case we want to conduct a one-time monitoring, evaluate the values straight away and we don’t mind the values being lost after stopping the server.

13 4. Self Monitor subsystem implementation

4.4.1 Basic entities In context of analysis there will be three entities in the system: A ModelMetric entity, Metric entity and MetricRecords entity.

4.4.1.1 ModelMetric entity

Figure 4.1: ModelMetric entity

ModelMetric entity will be an internal representation of a metric in the server model, this entity will hold the configuration of a metric. It will consist of the following attributes:

• ID - will be a composition of the metric path (in which the particular segments will be separated by underscore) and the metric name, which by itself would not uniquely identify the metric when accessed via CLI

• path - path to the metric, where the metric resides in the server, for example /subsystem=transactions

• enabled - whether the metric is currently monitored or not

• interval - interval (in seconds) in which the metric will be monitored

• type - type of the data the metric holds (e.g.: String, Long, List, etc.)

• description - a short text description of the metric

• dataType - type of the data in context of aggregation, whether the metric is suitable for aggregation - could be trait or aggr, will be described in more detail in Section 4.4.4

• nillable - whether the metric may hold a null value

The metric ID cannot consist of the path in the original form, because it would cause troubles when accessing the metric for CLI operations - the path’s delimiters would be evaluated as special characters and all operations would fail. The metric will be available as a node in the server model, will be accessible via CLI on address /subsystem=selfmonitor/metric=XY, where XY is an ID if the metric, and will provide operations for configuration of the metric and manipulation with the data.

14 4. Self Monitor subsystem implementation

4.4.1.2 Metric entity

Figure 4.2: Metric entity

Metric entity will serve for object-relational mapping when database storage selected and will consist of the following attributes:

• id - autogenerated identifier

• name - name of the metric

• path - path to the metric, where the metric resides in the server

• time - a timestamp of the moment when the value of the metric was captured (in seconds)

• value - value of the metric (String)

Value of a metric may be of various types as decribed in Section 4.4.4, but in the object-relational mapping it is designed to be a String in order to make the mapping as simple as possible. When mapping values other than string, the conversion is handled by the application.

4.4.1.3 MetricRecords entity

Figure 4.3: MetricRecords entity

When memory storage selected, the metric’s records will be stored to the MetricRecords entity, where each record will have an id of the metric and a Map where key will be a timestamp and value will be the metric’s value in the given time.

15 4. Self Monitor subsystem implementation

4.4.2 Application structure I will not cover the classes that serve for extending WildFly, be- cause except for definitions of custom CLI operations they are similar for all subsystems and their design may be found in the subsystem imple- mentation tutorial at https://docs.jboss.org/author/display/WFLY8/ Extending+WildFly+8. There will be an important class SelfmonitorService implementing the Service interface which defines basic methods of a simple WildFly service and will be given application context after start to initialize the subsystem. Moreover, a thread will be present running continuously during server runtime.

Figure 4.4: The application structure

The Figure 4.4 describes the basic application structure. At the start of the server it will initialize the selected storage (either MetricsDbStorage or MetricsMemoryStorage), scan the model tree using the ModelScanner and extract all the metrics present in the server saving them to the metrics property together with information about each of them.

16 4. Self Monitor subsystem implementation

Having the metrics available with all the attributes necessary, the service will write them to the server model using the ModelWrite, so that each metric could be available at path /subsystem=selfmonitor/metric=XY, it will do nothing in case the metric is already written in the selfmonitor subsystem.

4.4.3 Custom CLI operations All metrics will be available as nodes in the server model and will provide custom CLI operations upon /subsystem=selfmonitor/metric=XY:

• An operation that will retrieve all monitored values of a metric

• An operation that for given time returns the metric’s value in that time

• An operation that for given time interval and given aggregation func- tion applies the function on the values that occurred in the given time interval and returns the result

• An operation that for given value and time interval informs, whether the value occurred in the given time interval

There will be one more operation, which will list all available met- rics stored in the subsystem configuration. Based on the argument, the operation will return list of enabled or list of disabled metrics.

Figure 4.5: Custom CLI operations

17 4. Self Monitor subsystem implementation

The Figure 4.5 shows, what will happen when an operation is invoked. The controller finds the operation definition inside the MetricDefinition and delegates the control to its operation handler. The handler retrieves the desired values from the SelfmonitorService and returns them back to the CLI, which sends the result to the CLI output. The same sequence will be followed when the operation of listing enabled/disabled metrics invoked, only instead of MetricDefinition the delegation of control will be provided by SubsystemDefinition.

4.4.4 Metric monitoring

Monitoring of a metric will be handled by the MonitorMetricJob class. It will run in a separate thread and will communicate with the SelfmonitorService via the MonitorMetricJobHandler to reflect any changes made to metrics during runtime from the client side or to react to any exceptional state the job might get into.

Figure 4.6: Monitoring of the metrics

The values of the metrics may be of one of the following data types:

• Integer

• Long

• Double

• Boolean

18 4. Self Monitor subsystem implementation

• String

• Object

• List

When monitoring the metrics, the application will have to distinguish, whether the value is suitable for aggregation or not. That is to say, whether it makes sense to calculate median and minimum, maximum and average value. This will be indicated by the dataType attribute of the ModelMetric entity, which may be either:

• trait - the values are not suitable for aggregation

• aggr - the values will be aggregated

At the initial start of the server when the subsystem scans the whole model for metrics (as described in Section 4.5.3), the dataType attribute ob- tains a default value, which is trait in case of non-numeric types (Boolean, String, Object, List) or aggr in case of numeric ones (Integer, Long, Double). This may be changed by the user at any time via the CLI. According to usage of the dataType attribute it would be sufficient for it to be of a boolean type, but certain new aggregation types might be introduced in the future developement of the subsystem. For example, in case we have a metric representing state of some resource and its value may be either UP or DOWN, it would be beneficial to store the time when the value changed and what value it changed to instead of storing the values repeatedly. There may also be a situation when we want the monitoring of a metric to be additive - at each iteration add the value to an amount that we’ve calculated so far instead of storing the value itself. To facilitate these types of aggregation, the dataType attribute is ready to accept new values in the future.

4.4.5 Selfmonitor Console The Selfmonitor Console will be a standalone client web application deployable to WildFly 8. It will provide an interface to retrieve the metrics’ values with an ability to filter them, see the evolution of the values in time and aggregations of metrics that are suitable for it. It will show each metric in a hiearchical menu under its subsystem.

19 4. Self Monitor subsystem implementation

Figure 4.7: The preliminary design of the Selfmonitor Console

As shown on the Figure 4.7, when metric selected from the hierarchical menu, its information will be presented in the right segment of the page consisting of two tabs: All values and Statistics. The All values tab will contain all metric’s values ordered by the date along with filtering option above. As shown on the Figure 4.8, the Statistics tab will display the overall information about metric’s values, again filterable by date. There will be a chart depicting the evolution of the value in time and at the bottom there will be results of aggregation functions. In case the metric has its dataType attribute set to trait, there will be an appropriate message saying that it’s not possible to calculate the statistics and show the chart.

20 4. Self Monitor subsystem implementation

Figure 4.8: The Statistics tab of the Selfmonitor Console

Considering the business layer of the Selmonitor Console, there will be two basic beans: TreeBean and ContentBean. The TreeBean will provide the logic for dynamic generating of the tree with available metrics, which will be done with the MetricHandler involved, invoking the read-metrics operation in CLI, as shown on the Figure 4.9. The ContentBean will serve for operating with values of a selected metric, filtering the values and retrieving statistics. This bean will use MetricValuesHandler class, which handles retrieving appropriate data by communicating with the CLI and invoking the custom operations described in Section 4.4.3.

21 4. Self Monitor subsystem implementation

Figure 4.9: The analysis of the business layer of the Selfmonitor Console

4.5 Implementation

4.5.1 The detyped API When working with the AS’s management API, we may encounter many logical concepts involved, for instance servers, subsystems, datasources, web connectors, etc., and each of them could logically correspond to a sin- gle java class. This wouldn’t be very practical since it would require users of the API to include many various dependencies. For these reasons and also in order to provide forward compatibility, a detyped API located in the jboss-dmr library is employed [9].

4.5.1.1 The ModelNode object

The org.jboss.dmr.ModelNode object is an internal detyped represen- tation of a single server resource. It is basically a wrapper around some value, which is typically some basic JDK type (or a ModelNode itself), which may be obtained using the getType() method returning a value of type org .jboss.dmr.ModelType, which is an enum of all available types of values [9]. To set and get a value of the ModelNode we use the set() and get() methods, for instance: import org.jboss.dmr.ModelNode;

ModelNode node = new ModelNode(); node.set("Hello World!"); // This way we may set String, integer, boolean, etc. System.out.println(node.get()); // Will print ’Hello World!’

// we may also set a ModelNode as a value to another ModelNode ModelNode anotherNode = new ModelNode(); anotherNode.set(node);

22 4. Self Monitor subsystem implementation

System.out.println(another.asString()); // Will print ’Hello World!’ too Code 4.1: Example of manipulation with a value using the ModelNode object

4.5.2 Access to the server’s management API As described in Section 3.4.1, the server model resources provide cer- tain operations to retrieve or manipulate data. As we could see in the Code 4.2, the ModelNode class gives us an API to access the model resources no matter what type of the resource we’re working with. With this in mind we can access the CLI and invoke an arbitrary operation upon an arbitrary resource. import org.jboss.dmr.ModelNode; import org.jboss.as.controller.client.ModelControllerClient;

ModelNode op = new ModelNode(); op.get(’operation’).set(’read-resource’); op.get(’include-runtime’).set(true); op.get(’address’).add(’/subsystem=transaction’); ModelNode returnValue = null; try { returnValue = client.execute(op); } catch (IOException ex) {} return returnValue; Code 4.2: Example of accessing the CLI and invoking a read-resource operation upon a resource

There is an add method not mentioned yet, which is a method that adds an element to ModelType.LIST, which is a more complex type with which we can build complex data structures [9]. Providing a connected client of type ModelControllerClient, this will return a ModelNode that contains the result of a read-resource operation invoked upon transaction subsystem with metrics included - the same result as in the Code 3.4, but this time we hold the result in a java object and we may handle with it. Now we are able to retrieve the metrics from a node and get its value.

4.5.3 Scanning the model

After launching the server, the SelfmonitorService is started, auto- matically scans the whole model and retrieves all current metrics and their basic properties. This is done by the org.jboss.as.selfmonitor.model. ModelScanner class and since the server’s resources are of a tree structure, a recursive method for traversing the tree is employed. The metrics are retrieved by accessing the CLI as shown in the Code 4.2, a new ModelMetric object is created for each one of them and added to the service’s metrics property.

23 4. Self Monitor subsystem implementation

4.5.4 Writing the metrics to the model

So far the metrics are stored in the service’s metrics property, but not in the model yet. Leaving it like this would cause the configuration to be lost after shutting the server down and the metrics wouldn’t be accessible via the CLI at all. The org.jboss.as.selfmonitor.model.ModelWriter class handles writ- ing the metrics to the model by invoking an add operation upon /subsystem =selfmonitor node via the CLI. An example of a metric configuration is as follows: Code 4.3: Example of a metric configuration

4.5.5 Running a Quartz job for each enabled metric

Each metric with its enabled attribute set to true is supposed to store the values in selected interval to the selected storage type. In order to pre- vent creating a separate thread for each one of them, the Quartz Scheduler is employed. It provides API for initializing jobs that are runnable in custom interval and therefore suits this usecase perfectly. Moreover, the scheduler runs all the jobs in a single thread [10]. The class org.jboss.as.selfmonitor .service.MonitorMetricJob handles running of the jobs and there is an im- portant class org.jboss.as.selfmonitor.service.MonitorMetricJobHandler which provides an API for making changes to the jobs that are actually running. For instance if we want to change the metric’s interval and we want the change to propagate to the corresponding job, we do so in the CLI and the MonitorMetricJobHandler does the work for us. This handler also initializes and destroys jobs.

4.5.6 Storing the metrics’ values

Storing the metrics’ values is provided by the API defined in the org. jboss.as.selfmonitor.storage.IMetricsStorage interface having the capa- bilities of storing the given value (along with metric and time) and retrieving all records of the given metric. The concrete storing method depends on the selected implementation, so far there are two implementations available:

• Storing to memory

• Storing to database

24 4. Self Monitor subsystem implementation

4.5.6.1 Storing the metrics’ values to memory First storage type option is memory. This option may cause high mem- ory demands when simultaneously monitoring high number of metrics with short intervals and should be used with care. As presented in the analysis, storing to memory is provided by the org.jboss.as.selfmonitor.storage. MetricsMemoryStorage class, which is an IMetricsStorage implementation. There is a metricRecords property containing the values as follows: private Map> metricRecords; metricRecords = new HashMap<>(); metricRecords = Collections.synchronizedMap(metricRecords); Code 4.4: The metricRecords structure

The metricRecords structure is an implementation of java.util.Map interface and the key here is the metricId (unique identification of a metric) and value is another Map, where key is a timestamp and value is the value of the metric in the given time.

4.5.6.2 Storing the metrics’ values to database

Second storage type option is database and is handled by the org .jboss.as.selfmonitor.storage.MetricsDbStorage class. As a persistence object-relational mapping framework was chosen Hibernate, since it is a well established and documented open source framework [11] and is available as a module in WildFly 8 in version 4.3.5.Final. Initially the storage handler creates an EntityManagerFactory and stores it to its property in order to generate instances of EntityManager later during the lifecycle. The javax.persistence.EntityManagerFactory was chosen over the org.hibernate.SessionFactory because the second one is Hibernate-specific while the first one is defined by the JPA standard. Moreover, an EntityManager invokes a Hibernate session under the hood. As described in Section 4.4.1.2 in analysis, the Metric entity provides an object-relational mapping. Each record represents a value of a metric in certain moment and each running job stores the data via this entity in case database storage selected.

4.5.7 Selfmonitor Console The result of the implementation of the Selfmonitor Console is a war archive deployable to the AS. It is a web application made on JavaServer Faces (JSF) technology, which is a component-based framework for develop- ing user interface of a web application [12]. It was chosen among others since it is a well established and documented framework and offers sophisticated components like data tables and trees, which are useful for this purpose. Moreover, it works well with AJAX (Asynchronous JavaScript and XML), which is a technique of creating web applications which uses current technologies like JavaScript, XML, DOM, XHTML, etc., and interchanges data with the server and facilitates refreshing particular segments of the page without reloading the whole page [13].

25 4. Self Monitor subsystem implementation

There is also PrimeFaces framework involved, which is a component front-end JavaScript library for JSF providing UI components that are flex- ible, easy to create and is delivered along with built-in AJAX [14]. In this case it is used to add a chart component to display the evolution of a metric’s value. There are few things that are implemented in a different way than planned in the analysis:

• the filtering of the values - while in the analysis it was located inside each tab, during implementation it was put above the tabs, because the filtering is applied to the both scopes - all values and statistics and therefore it’s reasonable to locate it to a common space

• the chart with the evolution of a metric’s value - while in the analysis it was located inside the Statistics tab to be displayed together with the statistics-related data, during implementation it was put above the tabs because of a bug in the current PrimeFaces release, which is described in more detail in Section 4.5.9.2

• the metrics attribute in the TreeBean - in the analysis it is designed as a list of ModelMetric entities but during implementation if was changed to a list of Strings, because in this case the entity is not required and a metric’s ID is more effective and sufficient to identify a metric while invoking operations in the CLI

Figure 4.10: The structure of the JSF pages

Since the Selfmonitor Console renders all components with AJAX, there is a hierarchy of pages, each of which controls a particular part of the Console. As depicted on the Figure 4.10, the allValues.xhtml file contains code of the All values tab, the statistics.xhtml file contains code of the Statistics tab and both files are included in the content.xhtml file, which handles filtering of the values and displays the chart with the evolution of the metric’s value. The menu.xhtml file contains the tree component with the metrics themselves and is together with the content.xhtml file included in the index.xhtml file.

4.5.8 Testing There are two types of tests used:

26 4. Self Monitor subsystem implementation

• unit tests - applied to each separate component of the implementation, in most cases verify, that an operation or function returns an expected value for given attributes or that the monitored values are present in the declared storage

• integration tests - used for testing of how the components work to- gether and communicate with the server, for instance to check parsing of the configuration, interaction with the relational database, etc.

All tests are automated and are performed at the time of build of the project in order to discover defects before even launching the server. The integration tests require certain libraries for their execution, for instance server, relational database or XML parser, and therefore the Ar- quillian library is employed, which is a testing platform for Java that enables developers to easily create automated integration, functional and acceptance tests for Java middleware [15].

4.5.9 Problems during implementation 4.5.9.1 Class loading and initializing Hibernate persistence unit Class loading in WildFly is different to previous versions of JBoss AS - instead of hierarchical class loading it is based on modules that define explicit dependencies on other modules. As a consequence of this it may happen that while trying to reach certain class in a module from another module, it may not be visible until a class loader of the calling class is changed [16]. private EntityManagerFactory createEntityManagerFactory(String persistenceUnit){ return Persistence.createEntityManagerFactory(persistenceUnit); } Code 4.5: Erroneous initializing of the Hibernate persistence unit

While having imported corresponding packages and defined corre- sponding explicit dependencies, initializing the Hibernate persistence unit as we can see it in the Code 4.5 would normally work fine, but in context of WildFly 8 it throws an exception, because the Hibernate classes are not visible to the class loader of the context and therefore in needs to be changed to the class loader of the calling class as follows: private EntityManagerFactory createEntityManagerFactory(String persistenceUnit){ EntityManagerFactory emf = null; ClassLoader originalClassLoader = Thread.currentThread() .getContextClassLoader(); try { Thread.currentThread().setContextClassLoader( this.getClass().getClassLoader()); emf = Persistence.createEntityManagerFactory(persistenceUnit) ; } finally {

27 4. Self Monitor subsystem implementation

Thread.currentThread().setContextClassLoader( originalClassLoader); } return emf; } Code 4.6: Proper initializing of the Hibernate persistence unit

4.5.9.2 Rendering PrimeFaces chart inside of a tab The chart component doesn’t render when put into another compo- nent, which is loaded with AJAX and is not initialized at the first load of the page. A possible solution seemed to be assigning the chart component an id, marking the parent component as dynamic and adding a JavaScript callback to the parent component that would rerender the chart, but this didn’t work neither. After some research a bug report with this description has been found and the fix is expected to be in the next release. In the end the chart was put above the tabs to the area that is common to both All values and Statistics sections.

28 5 Using Self Monitor subsystem

5.1 Subsystem configuration

In order to make the subsystem work, we first need to copy the jar along with the module.xml file to the $WILDFLY HOME/modules/system/ layers/base/org/jboss/as/selfmonitor/main folder in the AS. After that, the subsystem is physically there, but the AS is not aware of it until it is con- figured in the standalone.xml.

5.1.1 Configuring standalone.xml In order to configure the subsystem, open the $WILD- FLY HOME/standalone/configuration/standalone.xml file, locate the section (should be somewhere at the beginning of the file) and add the following line: Code 5.1: Adding the subsystem to the standalone.xml

With this we are telling the AS to involve the selfmonitor extension and expect its configuration later on. The next step is to locate the section. This sec- tion contains configurations of all subsystems of the AS and this is where the configuration of our new subsystem will go. Code 5.2: Adding the subsystem configuration to the standalone.xml

As shown in the Code 5.2, the subsystem configuration consists of and tags, between which the config- uration of the metrics will reside. We will leave it like this for now, because the subsystem scans the model and inserts the configuration of each metric after the server starts, as described in secion 4.5.3. Now the subsystem is configured and the AS is ready to start with the subsystem inside. The CD enclosed to this thesis contains the WildFly 8 AS with the subsystem already configured.

29 5. Using Self Monitor subsystem

5.1.2 Accessing the subsystem via CLI To access the subsystem via the CLI, we need to launch the server first. This might take a bit longer than normal, because the subsystem scans the whole model and writes all available metrics. At first a message saying Scanning the whole model for metrics, please wait... shows up in the log and when the scan is finished, a message Added X metrics shows, while X is the number of metrics that were found during the scan and were written to the subsystem cofiguration. One more message shows saying Number of metrics monitored: Y, where Y will be 0 in case we’re doing our very first scan and haven’t previously enabled any metric. Now we may connect to the CLI (as described in Section 3.4.1) and access the subsystem. [standalone@localhost:9990 /] /subsystem=selfmonitor:read-resource { "outcome" => "success", "result" => {"metric" => { "subsystem_infinispan_cache-container_ejb_local-address" => undefined, "subsystem_transactions_number-of-nested-transactions" => undefined, ... }} } Code 5.3: Reading the selfmonitor subsystem

Here we can see that the metrics are there even though we didn’t explicitly add them to the standalone.xml. The three dots mean there would be more of them in the real client, but only two of them are listed here in order to save space. All these metrics were added during the initial scan. To retrieve some concrete information about each of the metrics we might add recursive=true attribute to the read-resource operation, but in my opinion this would cause a bit mess, because all the metrics along with their info would be listed together. Instead, we will take one of them (for instance subsystem_transactions_number-of-committed-transactions - we will use this one for demonstration purposes later on) and invoke the read -resource operation upon it together with the recursive attribute set to true like this: /subsystem=selfmonitor/metric= subsystem_transactions_number-of-committed-transactions :read-resource(recursive=true) Code 5.4: Reading the metric details

The above command needs to be put to CLI in a single line. As a result we get something like this: { "outcome" => "success", "result" => { "enabled" => false, "interval" => 5,

30 5. Using Self Monitor subsystem

"metric-description" => "The number of committed transactions .", "metric-type" => "LONG", "nillable" => true, "path" => "/subsystem=transactions" } } Code 5.5: Result of reading metric details

The meaning of each of the attributes is shown in Section 4.4.1.1 describing the ModelMetric entity, which is an internal representation of what we just got in the CLI. Default value of the attribute enabled is false and default value of the attribute interval is 5.

5.2 Let’s start monitoring

To start monitoring a metric, there are two things to be done: • set the interval

• set the enabled attribute to true To set the interval to a value that is appropriate for the metric (for example to 10 seconds) we invoke the following operation: /subsystem=selfmonitor/metric= subsystem_transactions_number-of-committed-transactions :write-attribute(name=interval, value=10) Code 5.6: Setting the metric’s interval

The write-attribute operation is common to all nodes and always needs these two parameters. To enable the metric for monitoring we invoke the same operation but with a different name attribute: /subsystem=selfmonitor/metric= subsystem_transactions_number-of-committed-transactions :write-attribute(name=enabled, value=true) Code 5.7: Enabling the metric

From the very moment of executing this command, the subsystem_transactions_number-of-committed-transactions metric is being monitored - its value is being stored to the selected storage in the selected interval.

5.2.1 The read-metrics custom operation At some point we may want to get a list of metrics that are currently enabled or disabled for monitoring. It is possible with the read-metrics operation as follows: /subsystem=selfmonitor:read-metrics(show-enabled=true) Code 5.8: Listing all currently monitored metrics

31 5. Using Self Monitor subsystem

Having only a single metric currently monitored will result in follow- ing: { "outcome" => "success", "result" => [{ "id" => "subsystem_transactions_number-of-committed- transactions", "path" => "/subsystem=transactions", "interval" => 10, "type" => "LONG", "description" => "The number of committed transactions.", "nillable" => true }] } Code 5.9: Result of the read-metrics operation

Notice that this operation is not invoked upon the metric node, but upon the selfmonitor subsystem node and is node-specific, therefore it can’t be found anywhere else in the model except for this node.

5.3 Retrieving the values

To retrieve the values of the metric along with the time when the value occured, we may invoke some of the following operations:

• the read-all-values operation

• the read-value operation

• the read-values operation

• the value-occured operation

5.3.1 The read-all-values operation

The read-all-values operation takes no argument and when invoked upon a metric, it retrieves all its values along with time when the value occured. It may be used as follows: [standalone@localhost:9990 /] /subsystem=selfmonitor/metric= core-service_platform-mbean_type_buffer-pool_name_direct_memory-used :read-all-values { "outcome" => "success", "result" => [ { "time" => "2014-12-23.18:51:24", "value" => "148780L" }, { "time" => "2014-12-23.18:51:09", "value" => "146872L" },

32 5. Using Self Monitor subsystem

{ "time" => "2014-12-23.18:51:29", "value" => "148795L" }, { "time" => "2014-12-23.18:51:14", "value" => "148545L" }, { "time" => "2014-12-23.18:51:19", "value" => "148765L" } ] } Code 5.10: Example of the read-all-values operation

For this example I have chosen metric memory-used at the path /core -service=platform-mbean/type=buffer-pool/name=direct (where ID of the metric is core-service_platform-mbean_type_buffer-pool_name_direct_memory -used), which reflects an amount of memory that the is using for this buffer pool in bytes (or -1 if an amount of memory usage is not available).

5.3.2 The read-value operation

The read-value operation takes a date for argument and retrieves the value of the metric in the selected date. For instance: [standalone@localhost:9990 /] /subsystem=selfmonitor/metric= core-service_platform-mbean_type_buffer-pool_name_direct_memory-used :read-value(date=2014-12-23.18:51:14) { "outcome" => "success", "result" => "148545" } Code 5.11: Example of the read-value operation

5.3.3 The read-values operation

The read-values operation is there to apply a function on the values of the metrics. As arguments it takes date-from, which is the lower bound from when to take the values, date-to, which is the higher bound to when to take the values, and function-type. As a function-type we may add one of the following options:

• avg - returns average value of the values that were stored between the two selected dates • median - returns median value of the values that were stored between the two selected dates • min - returns the lowest value of the values that were stored between the two selected dates

33 5. Using Self Monitor subsystem

• max - returns the highest value of the values that were stored between the two selected dates

[standalone@localhost:9990 /] /subsystem=selfmonitor/metric= core-service_platform-mbean_type_buffer-pool_name_direct_memory-used :read-values(date-from=2014-12-22.00:00:00, date-to =2014-12-24.00:00:00, function-type=avg) { "outcome" => "success", "result" => "148351" } Code 5.12: Example of the read-values operation Since all of the function types may be applied on numeric values only, the read-values operation can’t be invoked upon metric the values of which are non-numeric.

5.3.4 The value-occured operation

The value-occured operation finds whether the given value occurred in the selected date interval. It takes the date-from and date-to arguments (same as the read-values operation) and value argument, which is the value we’re looking for. [standalone@localhost:9990 /] /subsystem=selfmonitor/metric= core-service_platform-mbean_type_buffer-pool_name_direct_memory-used :value-occurred(date-from=2014-12-22.00:00:00, date-to =2014-12-24.00:00:00, value=148765) { "outcome" => "success", "result" => [{ "date" => "Tue Dec 23 18:51:19 CET 2014", "value" => "148765" }] } Code 5.13: Example of the value-occurred operation

5.4 The Selfmonitor Console demonstration

This chapter describes deploying the Selfmonitor Console to WildFly 8 AS and displaying values of a metric that has been previously monitored.

5.4.1 Deploying application to WildFly There are several ways of deploying a war archive to WildFly 8:

• By invoking the deploy command in the CLI providing the path to the war archive, for instance: deploy /home/user/Desktop/SelfmonitorConsole.war, to undeploy, just invoke the undeploy command upon the archive in the CLI

34 5. Using Self Monitor subsystem

• By copying the war archive directly to the server folder with deploy- ments - the server’s deployment scanner discovers the archive himself, for instance: cp SelfmonitorConsole.war $WILDFLY_HOME/standalone/deployments/, to undeploy just delete the archive from the deployments folder

• Via the Web Management Interface (see Section 6.2.3 for more infor- mation about what it is and how to launch it) by hitting the Create Deployment link on the home page and adding the archive

5.4.2 Monitoring a metric The same metric as in the demonstration of the CLI operations in Section 5.3 was selected for monitoring with interval set to 5s.

5.4.3 Displaying the values in the console After the Selfmonitor Console war archive is deployed to WildFly and the server is started, the console may be accessed on http://:8080/ SelfmonitorConsole-1.0-SNAPSHOT/index.xhtml

Figure 5.1: Truncated illustration of the tree menu in the Selfmonitor Console

After the initial start, the console displays the server name and the tree menu with the subsystems, as shown on the Figure 5.1. Each metric is listed under the subsystem it belongs to and is labeled with its ID, only the first two parts of the ID indicating the subsystem are removed, because this information is already present in the label of the subsystem. After selecting a metric, a section containing information about the metric’s values shows in the right part of the web. There is a line chart displaying the evolution of the values in time at the top of the section. As shown on the Figure 5.2, the chart’s X axis holds the time infor- mation and the Y axis holds the value. Both X and Y are limited by the minimum and maximum times/values that occurred during monitoring of the selected metric.

35 5. Using Self Monitor subsystem The line chart displaying the evolution of the metric’s values in time in the Selfmonitor Console Figure 5.2:

36 5. Using Self Monitor subsystem

The Figure 5.3 shows the filtering segment and the part with All values and Statistics tabs. When selecting a date in the filter form, a calendar pops up in order to facilitate the date selection.

Figure 5.3: Filtering and displaying values in the Selfmonitor Console

The Statistics tab holds the Miminum value, Maximum value, Average value and Median of the metric’s values.

Figure 5.4: Statistics in the Selfmonitor Console

37 6 Conclusion

This thesis successfully implements a new subsystem for monitoring metrics of the WildFly application server. To introduce the reader to the topic of Java EE applications and application servers, there is a brief de- scription of these technologies at the beginning. Since the result is a WildFly AS subsystem and it is essential to be familiar with the AS’s configuration approach in order to work with the subsystem, the third chapter describes basic manipulation with the server and how to administer its resources. The fourth chapter brings up motivation why the subsystem for mon- itoring metrics is needed and where it helps users with their work. Followed by analysis and implementation itself, it covers the whole process of creating the subsystem from the beginning to the very end.

6.1 The result of the implementation

After comparing the determined specification with the implementa- tion, there are almost no cases where it differs. The implementation didn’t bring any situation where the requirements could not be accomplished for technological or any other reasons. The subsystem works with all possible data types and handles monitoring of multiple metrics at the same time with whatever interval the user chooses - for 1 second at least. Even though the subsystem works well and is ready to use, there are several features that would be valuable for the subsystem to offer and have not been implemented in cotext of this thesis either for their time requirements or because they didn’t fit into the scope of this thesis. The Section 6.2 is a recommendation of what to implement in the near future.

6.2 Extending the subsystem in the future

6.2.1 Development of the Selfmonitor Console 6.2.1.1 Tree menu The tree menu on the left side of the console that contains the list of metrics along with their parent subsystems would look better and the metrics would be more accessible if the tree was of the same structure as the AS’s model. A quick draft is proposed on the Figure 6.1.

38 6. Conclusion

Figure 6.1: The preliminary design of the extended tree menu

Moreover, it would be better for the metrics to be listed with their normal short name instead of the metric ID presented in the section 4.4.1.1.

6.2.1.2 Lazy loading of the metrics’ values In real production use, the Self Monitor subsystem may run for days or weeks collecting the values in order to provide an overview of what has been happening in the parts of the server during runtime. Therefore the number of values of a certain metric could be very high. With the current design, all values will show in the table in the All values tab of the console. The values are filterable, so it’s possible to narrow the number of values down in order to inspect them, but the time needed to show the page is high. It would be better to involve a pagination mechanism that would put the values into separate pages and on page load would display only an initial portion of the values and other values would be retrieved from the server on user request.

6.2.1.3 Administer the subsystem from the console All operations are currently available from the server’s CLI, which is used for administration of the whole server. To increase the usability and user-friendliness, the console could pro- vide the operations so that it would not serve for reading the values only, but it would be possible to turn the metrics on or off for monitoring, adjust the interval, etc. Moreover, each metric might have an indication, whether it is currently monitored or not.

39 6. Conclusion

6.2.1.4 Optimization of the time of response In the current implementation there is quite a considerable amount of time between selecting a metric and displaying its values. This could be fixed in the next versions employing caching mechanisms and calculating the aggregation values on demand.

6.2.2 Refactor the subsystem configuration 6.2.2.1 Remove the information about metrics from the stan- dalone.xml In the current implementation the information about each metric is present in the configuration section of the subsystem in the standalone.xml file. With hundreds of metrics in the system, the subsystem causes lower readability of the configuration file. In the next versions of the subsystem it would be nice to have the information about each metric only in the CLI and the standalone.xml would provide only a configuration of the whole subsystem.

6.2.2.2 Add configuration of custom datasource When the database storage type selected, the monitored values are currently stored to the AS’s default datasource called ExampleDS. This datasource is always present in the server, so the operation doesn’t fail because of datasource unavailability, but there is no other option. In the next versions of the subsystem it would be beneficial to have this feature configurable, so that the user could specify his custom datasource in the subsystem configuration in order to provide desired security level and have full control over the storage.

6.2.3 Involve the Selfmonitor Console into the server’s Web Management Interface The Web Management Interface is a web application that uses the HTTP management API to configure a management domain or standalone server [7]. It is a web alternative for configuring the server and is available on address http://:9990/console. In it’s Runtime tab (as shown on the Figure 6.2) there is a tree on the left side similar to the tree implemented in the Selfmonitor Console and after selecting a subsystem it shows its metrics. In this case, there are only current values of the metrics shown.

40 6. Conclusion

Figure 6.2: The Web Management Interface

In the next versions of the Self Monitor subsystem it would be practical to have all information about the metrics together in the Web Management Interface - the current value and the evolution of the value in history.

41 Bibliography

[1] JENDROCK, E., EVANS, I., GOLLAPUDI, D., HAASE, K., SRIVATHSA, C., The Java EE 6 Tutorial: Basic Concepts, Fourth Edition. Addison-Wesley Professional, 2010. ISBN: 978- 0137081851

[2] OTTINGER, J., What is an App Server? [online; available in October 2014]. URL: http://www.theserverside.com/news/ 1363671/What-is-an-App-Server

[3] Java EE Compatibility [online; available in November 2014]. URL: http://www.oracle.com/technetwork/java/javaee/ overview/compatibility-jsp-136984.html

[4] LOFTHOUSE, D., MUMFORD, S., MCGOWAN, S., MAR- TINS, E., Getting Started Guide. February 2012 [on- line; available in October 2014]. Last revision on March 10, 2014. URL: https://docs.jboss.org/author/display/ WFLY8/Getting+Started+Guide

[5] GUPTA, A., JBoss/WildFly: Top Java EE Application Server for 5 years in ZeroTurnaround Reports [online; available in October 2014]. URL: http://blog.arungupta.me/2014/05/ jboss-wildfly-top-javaee-appserver-zeroturnaround-report

[6] JBOSS COMMUNITY, JBoss Application Server 5.0.0 Admin- istration And Development Guide. March 2008 [online; available in October 2014]. URL: https://docs.jboss.org/jbossas/ docs/Server_Configuration_Guide/beta500/html/index. html

[7] LOFTHOUSE, D., WELLS, T., STANSBERRY, B., Admin Guide. May 2012 [online; available in October 2014]. Last re- vision on October 17, 2014. URL: https://docs.jboss.org/ author/display/WFLY8/Admin+Guide

[8] CROCKFORD, D., JSON, The Fat-Free Alternative to XML. [online; available in October 2014]. URL: http://www.json. org/xml.html

[9] STANSBERRY, B., Detyped management and the jboss- dmr library. July 2011 [online; available in Novem- ber 2014]. Last revision on July 14, 2011. URL:

42 BIBLIOGRAPHY

https://docs.jboss.org/author/display/AS7/Detyped+ management+and+the+jboss-dmr+library

[10] Quartz Scheduler [online; available in December 2014]. URL: http://quartz-scheduler.org

[11] BAUER, CH., KING, G., Hibernate in Action. Manning Publi- cations, 2004. ISBN: 978-1932394153

[12] GEARY, D., HORSTMANN, C., Core JavaServer Faces, Third Edition. Prentice Hall, June 6, 2010. ISBN: 978-0137012893

[13] Holdener III, A. T., Ajax: The Definitive Guide. O’Reilly Media, February 4, 2008. ISBN: 978-0596528386

[14] Why PrimeFaces [online; available in January 2015]. URL: http: //www.primefaces.org/whyprimefaces

[15] Arquillian [online; available in January 2015]. URL: http:// arquillian.org/invasion

[16] DOUGLAS, S., CERAR, T., MORGAN, J., CROFT, D. W., SAUPPER, H., WELLMANN, H., Class Loading in WildFly. February 2013 [online; available in December 2014]. Last revision on August 21, 2014. URL: https://docs.jboss.org/author/ display/WFLY8/Class+Loading+in+WildFly

43 7 Appendix

The enclosed CD contains:

• thesis.pdf The text of the thesis in PDF format

• packed-wildfly-selfmonitor.zip WildFly 8 AS with the Self Monitor subsystem integrated and the Selfmonitor Console deployed

• wildfly-selfmonitor-src.zip The source code of the Self Monitor subsystem

• wildfly-selfmonitor-console-src.zip The source code of the Selfmonitor Console

• modules Folder containing external libraries used by the subsystem and not included in the standard WildFly 8 release

The current version of the source codes is available in the following public repositories:

• https://github.com/bender-futur/wildfly-self-monitor

• https://github.com/bender-futur/SelfmonitorConsole

In order to build the project successfully, it requires:

• Java JDK 1.7

• Maven 3

44