Spring Support
A lot has changed since Jolokia initial release. While Spring Framework was already popular back then, in the meantime we’ve observed a general shift away from XML into Java and annotation-based configuration.
W also can’t forget about popularity of Spring Boot.
Support for Jolokia in Spring Boot
Jolokia support was added to Spring Boot in version 0.5.0. It was Jolokia 1.1.5.
Jolokia support is based on the concept of actuator and when Spring Boot detects Jolokia libraries on the CLASSPATH, special /actuator/jolokia
endpoint becomes available.
Spring Boot uses auto-configuration to detect potential @Configuration
classes and this mechanism is described in Locating Auto-configuration Candidates chapter of Spring Boot documentation.
In particular, org.springframework.boot:spring-boot-actuator-autoconfigure
library declares org.springframework.boot.actuate.autoconfigure.jolokia.JolokiaEndpointAutoConfiguration in /META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
and when Jolokia libraries are available on the CLASSPATH, special org.springframework.boot.actuate.autoconfigure.jolokia.JolokiaEndpoint
annotated with @org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpoint
is available. This makes Jolokia’s AgentServlet part of actuator infrastructure of Spring Boot.
However, Spring Boot 3, which moved to JDK 17 and JakartaEE 9+ removed support for Jolokia in org.springframework.boot:spring-boot-actuator-autoconfigure
. See this issue for more details.
To get fuller picture, an attempt to restore Spring Boot 3 support for Jolokia 2 was closed, with good explanation.
The following paragraphs describe support for Spring Framework and Spring Boot in Jolokia (so the opposite of the above).
Adding Jolokia Spring support library
Maven users can simply add this dependency to their project:
<dependency>
<groupId>org.jolokia</groupId>
<artifactId>jolokia-support-spring</artifactId>
<version>2.1.2</version>
</dependency>
Transitive dependencies for Jolokia core and service libraries will be automatically available.
Support for Spring Framework in Jolokia
Fundamental support for integrating Jolokia with Spring Framework application is through XML Schema Authoring.
Using custom XML Schema available here we can author Spring XML configuration files where Jolokia agent can easily be declared.
Here’s an example Spring XML configuration which starts org.jolokia.support.spring.SpringJolokiaAgent
(an extension of Jolokia JVM Agent's org.jolokia.jvmagent.JolokiaServer
). This agent
uses JDK’s own HTTP Server which comes with OpenJDK/Oracle JVMs (Version 1.6 or later).
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jolokia="http://www.jolokia.org/jolokia-spring/schema/config"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.jolokia.org/jolokia-spring/schema/config
https://www.jolokia.org/jolokia-config.xsd">
<jolokia:agent lookupConfig="false" systemPropertiesMode="never">
<jolokia:config autoStart="true" host="0.0.0.0" port="8778" .... />
</jolokia:agent>
</beans>
Just in case you don’t want to use the Jolokia Spring namespace you can also use plain beans to configure a JVM agent. The following examples shows the example above with only base Spring bean configurations (including an Spring EL expression):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util
https://www.springframework.org/schema/util/spring-util.xsd">
<util:map id="configuration">
<entry key="jmx.jolokiaPort" value="8778"/>
</util:map>
<bean name="server" id="jolokia" class="org.jolokia.support.spring.SpringJolokiaAgent">
<property name="lookupConfig" value="false"/>
<property name="systemPropertiesMode" value="never"/>
<property name="config">
<bean class="org.jolokia.support.spring.SpringJolokiaConfigHolder">
<property name="config">
<util:map>
<entry key="autoStart" value="true"/>
<entry key="host" value="0.0.0.0"/>
<entry key="port" value="#{configuration['jmx.jolokiaPort']}"/>
</util:map>
</property>
</bean>
</property>
</bean>
</beans>
This style is not recommended, as Jolokia configuration namespace is much easier to read.
Jolokia custom XML Schema supports few top-level elements which are described next.
An example of application based on pure Spring Framework is available at examples/spring
in Jolokia GitHub repository.
<jolokia:agent>
<jolokia:agent>
declares a Jolokia server with a configuration as defined in an embedded <jolokia:config>
configuration section.
Supported attributes are:
Name | Description | Default value |
---|---|---|
|
If set to |
|
|
If set to |
|
|
Specifies how system properties with
|
|
|
If set to |
|
<jolokia:agent>
element may contain child <jolokia:config>
element that can be used to configure the agent in-place.
<jolokia:config>
takes as attributes all
the configuration parameters for the JVM agent as described in
JVM agent configuration options. In addition, there is an extra
attribute autoStart
which allows for
automatically starting the HTTP server during the initialization
of the application context. By default this is set to
true
, so the server starts up automatically. <jolokia:config>
has an
order
attribute, which determines the
config merge order: The higher order configs will be merged
later and hence will override conflicting parameters. By
default, external config lookup is disabled.
<jolokia:log>
child element may be specified to configure one of the supported log handles used by Jolokia. These are:
-
stdout
- log to standard output -
quiet
- don’t log -
jul
- usejava.util.logging
-
slf4j
- use Simple Logging Framework for Java, which is usually combined with Logback or Log4j2. -
log4j2
- use Apache Logging Log4j2 directly -
commons
- use Apache Commons Logging
<jolokia:mbean-server>
With <jolokia:mbean-server>
the Jolokia specific
MBeanServer can be specified. This is especially useful for
adding it to <context:mbean-export>
so that this MBeanServer is used for registering
@ManagedResource
and
@JsonMBean
. Remember, MBean registered at
the Jolokia MBeanServer never will show up in an JSR-160 client
except when annotated with @JsonMBean
.
See JMX Support for more information.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jolokia="http://www.jolokia.org/jolokia-spring/schema/config"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.jolokia.org/jolokia-spring/schema/config https://www.jolokia.org/jolokia-config.xsd">
<context:mbean-export server="jolokiaServer"/>
<jolokia:mbean-server id="jolokiaServer"/>
</beans>
Support for Spring Boot in Jolokia
Spring Boot is using all functionality from Spring Framework and adds a lot of convenient programming and architecture patterns (idioms) for developers.
With pure Spring Framework, we had to declare org.jolokia.support.spring.SpringJolokiaAgent
directly or using <jolokia:agent>
custom element. We could also use @Configuration
and @Bean
annotations. However Spring Boot provides several other methods to provide Jolokia functionality to your Spring application.
Registering Agent servlet as Spring bean
Servlets, Filters, and Listeners can be registered directly as @Bean
annotated beans and Spring Boot will register them directly into embedded servlet container.
In simplest form we could use:
@Configuration
public class AppConfig {
@Bean
public AgentServlet jolokia() {
return new AgentServlet();
}
}
However without a way to specify URL mapping we may conflict with registration of Spring’s own DispatcherServlet
.
This is why it’s better to declare beans of org.springframework.boot.web.servlet.ServletRegistrationBean
class:
@Configuration
public class AppConfig {
@Bean
public ServletRegistrationBean<AgentServlet> jolokia() {
ServletRegistrationBean<AgentServlet> jolokiaServlet = new ServletRegistrationBean<>(new AgentServlet(), "/jolokia/*");
jolokiaServlet.setLoadOnStartup(0);
jolokiaServlet.setAsyncSupported(true);
jolokiaServlet.setInitParameters(Map.of(ConfigKey.DEBUG.getKeyValue(), "true"));
jolokiaServlet.setInitParameters(Map.of(ConfigKey.AGENT_DESCRIPTION.getKeyValue(), "Spring Servlet Jolokia Agent"));
return jolokiaServlet;
}
}
This is enough for Spring Boot with org.springframework.boot:spring-boot-starter-web
starter to register Jolokia Servlet under /jolokia/*
mapping.
An example of application using Spring Boot is available at examples/spring-boot
in Jolokia GitHub repository.
Registering Agent servlet under Spring Boot actuator
Spring Boot actuator endpoints allow to access various controls in your application.
While Spring Boot 3 removed auto-configuration of Jolokia 1 actuator endpoint (because of JakartaEE 9+ incompatibility with Jolokia 1 servlet), Jolokia 2 now provides own auto-configuration in org.jolokia:jolokia-support-spring
.
With just few dependencies:
<dependency>
<groupId>org.jolokia</groupId>
<artifactId>jolokia-support-spring</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>${version.spring-boot}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${version.spring-boot}</version>
</dependency>
We can run a Spring Boot application without single Jolokia bean configuration. This is entire main()
method:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
And this is the application.properties
configuration file:
server.port = 8181 management.endpoint.jolokia.config.debug = true management.endpoint.jolokia.config.agentDescription = Jolokia Spring Boot Actuator agent management.endpoints.web.exposure.include = health, jolokia
Having all this, Spring Boot with actuator enabled will discover Jolokia own auto-configuration.
Because Jolokia is properly exposed, we may now access Jolokia Agent using http://localhost:8181/actuator/jolokia
URL:
$ curl -s 'http://localhost:8181/actuator/jolokia' | jq . { "request": { "type": "version" }, "value": { "agent": "2.1.2", "protocol": "7.2", "details": { "agent_version": "2.1.2", "agent_id": "192.168.0.221-91398-4ee6c0f5-servlet", "agent_description": "Jolokia Spring Boot Actuator agent", "secured": false, "url": "http://192.168.0.221:8181/actuator/jolokia" }, "id": "192.168.0.221-91398-4ee6c0f5-servlet", "config": { "agentId": "192.168.0.221-91398-4ee6c0f5-servlet", "debug": "true", "agentDescription": "Jolokia Spring Boot Actuator agent" }, "info": { "proxy": {}, "jmx": {} } }, "status": 200, "timestamp": 1702653722 }
/jolokia
actuator is listed under http://localhost:8181/actuator:
What’s more, with IDE support, Jolokia configuration properties are suggested:
An example of application using Spring Boot and its actuator features is available at examples/spring-boot-actuator
in Jolokia GitHub repository.