org.eclipse.jetty.docs.programming.JMXDocs Maven / Gradle / Ivy
The newest version!
//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under
// the terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0
//
// This Source Code may also be made available under the following
// Secondary Licenses when the conditions for such availability set
// forth in the Eclipse Public License, v. 2.0 are satisfied:
// the Apache License v2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//
package org.eclipse.jetty.docs.programming;
import java.lang.management.ManagementFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.jmx.ConnectorServer;
import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.jmx.ObjectMBean;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.ManagedOperation;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.ssl.SslContextFactory;
@SuppressWarnings("unused")
public class JMXDocs
{
public void server()
{
// tag::server[]
Server server = new Server();
// Create an MBeanContainer with the platform MBeanServer.
MBeanContainer mbeanContainer = new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
// Add MBeanContainer to the root component.
server.addBean(mbeanContainer);
// end::server[]
}
public void client()
{
// tag::client[]
HttpClient httpClient = new HttpClient();
// Create an MBeanContainer with the platform MBeanServer.
MBeanContainer mbeanContainer = new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
// Add MBeanContainer to the root component.
httpClient.addBean(mbeanContainer);
// end::client[]
}
public void remote() throws Exception
{
// tag::remote[]
Server server = new Server();
// Setup Jetty JMX.
MBeanContainer mbeanContainer = new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
server.addBean(mbeanContainer);
// Setup ConnectorServer.
// Bind the RMI server to the wildcard address and port 1999.
// Bind the RMI registry to the wildcard address and port 1099.
JMXServiceURL jmxURL = new JMXServiceURL("rmi", null, 1999, "/jndi/rmi:///jmxrmi");
ConnectorServer jmxServer = new ConnectorServer(jmxURL, "org.eclipse.jetty.jmx:name=rmiconnectorserver");
// Add ConnectorServer as a bean, so it is started
// with the Server and also exported as MBean.
server.addBean(jmxServer);
server.start();
// end::remote[]
}
public static void main(String[] args) throws Exception
{
new JMXDocs().remote();
}
public void remoteAuthorization() throws Exception
{
// tag::remoteAuthorization[]
Server server = new Server();
// Setup Jetty JMX.
MBeanContainer mbeanContainer = new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
server.addBean(mbeanContainer);
// Setup ConnectorServer.
JMXServiceURL jmxURL = new JMXServiceURL("rmi", null, 1099, "/jndi/rmi:///jmxrmi");
Map env = new HashMap<>();
env.put("com.sun.management.jmxremote.access.file", "/path/to/users.access");
env.put("com.sun.management.jmxremote.password.file", "/path/to/users.password");
ConnectorServer jmxServer = new ConnectorServer(jmxURL, env, "org.eclipse.jetty.jmx:name=rmiconnectorserver");
server.addBean(jmxServer);
server.start();
// end::remoteAuthorization[]
}
public void tlsRemote() throws Exception
{
// tag::tlsRemote[]
Server server = new Server();
// Setup Jetty JMX.
MBeanContainer mbeanContainer = new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
server.addBean(mbeanContainer);
// Setup SslContextFactory.
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath("/path/to/keystore");
sslContextFactory.setKeyStorePassword("secret");
// Setup ConnectorServer with SslContextFactory.
JMXServiceURL jmxURL = new JMXServiceURL("rmi", null, 1099, "/jndi/rmi:///jmxrmi");
ConnectorServer jmxServer = new ConnectorServer(jmxURL, null, "org.eclipse.jetty.jmx:name=rmiconnectorserver", sslContextFactory);
server.addBean(jmxServer);
server.start();
// end::tlsRemote[]
}
public void tlsJMXConnector() throws Exception
{
// tag::tlsJMXConnector[]
// System properties necessary for an RMI client to trust a self-signed certificate.
System.setProperty("javax.net.ssl.trustStore", "/path/to/trustStore");
System.setProperty("javax.net.ssl.trustStorePassword", "secret");
JMXServiceURL jmxURL = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://domain.com:1100/jmxrmi");
Map clientEnv = new HashMap<>();
// Required to connect to the RMI registry via TLS.
clientEnv.put(ConnectorServer.RMI_REGISTRY_CLIENT_SOCKET_FACTORY_ATTRIBUTE, new SslRMIClientSocketFactory());
try (JMXConnector client = JMXConnectorFactory.connect(jmxURL, clientEnv))
{
Set names = client.getMBeanServerConnection().queryNames(null, null);
}
// end::tlsJMXConnector[]
}
public void jmxAnnotation() throws Exception
{
// tag::jmxAnnotation[]
// Annotate the class with @ManagedObject and provide a description.
@ManagedObject("Services that provide useful features")
class Services
{
private final Map services = new ConcurrentHashMap<>();
private boolean enabled = true;
// A read-only attribute with description.
@ManagedAttribute(value = "The number of services", readonly = true)
public int getServiceCount()
{
return services.size();
}
// A read-write attribute with description.
// Only the getter is annotated.
@ManagedAttribute(value = "Whether the services are enabled")
public boolean isEnabled()
{
return enabled;
}
// There is no need to annotate the setter.
public void setEnabled(boolean enabled)
{
this.enabled = enabled;
}
// An operation with description and impact.
// The @Name annotation is used to annotate parameters
// for example to display meaningful parameter names.
@ManagedOperation(value = "Retrieves the service with the given name", impact = "INFO")
public Object getService(@Name(value = "serviceName") String n)
{
return services.get(n);
}
}
// end::jmxAnnotation[]
}
public void jmxCustomMBean()
{
// tag::jmxCustomMBean[]
//package com.acme;
@ManagedObject
class Service
{
}
//package com.acme.jmx;
class ServiceMBean extends ObjectMBean
{
ServiceMBean(Object service)
{
super(service);
}
}
// end::jmxCustomMBean[]
}
public void jmxCustomMBeanOverride()
{
// tag::jmxCustomMBeanOverride[]
//package com.acme;
// No Jetty JMX annotations.
class CountService
{
private int count;
public int getCount()
{
return count;
}
public void addCount(int value)
{
count += value;
}
}
//package com.acme.jmx;
@ManagedObject("the count service")
class CountServiceMBean extends ObjectMBean
{
public CountServiceMBean(Object service)
{
super(service);
}
private CountService getCountService()
{
return (CountService)super.getManagedObject();
}
@ManagedAttribute("the current service count")
public int getCount()
{
return getCountService().getCount();
}
@ManagedOperation(value = "adds the given value to the service count", impact = "ACTION")
public void addCount(@Name("count delta") int value)
{
getCountService().addCount(value);
}
}
// end::jmxCustomMBeanOverride[]
}
}