O JMX é uma tecnologia que permite o gerenciamento de recursos como aplicações, dispositivos, serviços, etc. A maioria dos servidores de aplicações utiliza essa tecnologia que já vem por padrão no J2SE 5 e 6. O único problema é que é complicado realizar as operações. O primeiro passo é realizar um conexão com o servidor que possui os MBeans, criar uma interface, carregar um proxy e executar métodos por essa interface. O procedimento passo a passo, é descrito aqui ou nesse tutorial.
Resolvi encapsular o lógica de execução em uma classe, mas queria evitar de ter que implementar uma interface para cada MBean a ser utilizado. E esse pensamento resultou na seguinte classe:
package org.gvlabs.weblogic.mbean; import java.io.IOException; import java.util.Hashtable; import java.util.Map; import javax.management.AttributeNotFoundException; import javax.management.InstanceNotFoundException; import javax.management.MBeanException; import javax.management.MBeanServerConnection; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import javax.management.ReflectionException; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; import javax.naming.Context; /** * MBean Connector * * @author Thiago Galbiatti Vespa * */ public class MBeanConnector { private static final int TIMEOUT = 10000; private MBeanServerConnection connection; private String hostname; private int port; private String username; private String password; /** * Constructor with connection info * * @param hostname * hostname to connect * @param port * port fo the server to connect * @param username * username of the server * @param password * username's password */ public MBeanConnector(String hostname, int port, String username, String password) { super(); this.hostname = hostname; this.port = port; this.username = username; this.password = password; } /** * Connect to server * * @throws IOException * @throws MalformedURLException */ protected void connect() throws IOException { String protocol = "t3"; // t3, t3s, http, https, iiop, iiops String jndiroot = "/jndi/"; /** * Domain Runtime MBean Server - weblogic.management.mbeanservers.domainruntime * Runtime MBean Server - weblogic.management.mbeanservers.runtime * Edit MBean Server - weblogic.management.mbeanservers.edit */ String mserver = "weblogic.management.mbeanservers.domainruntime"; JMXServiceURL serviceURL = new JMXServiceURL(protocol, hostname, port, jndiroot + mserver); Map<String, Object> h = new Hashtable<String, Object>(); h.put(Context.SECURITY_PRINCIPAL, username); h.put(Context.SECURITY_CREDENTIALS, password); h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, "weblogic.management.remote"); h.put("jmx.remote.x.request.waiting.timeout", TIMEOUT); JMXConnector connector = JMXConnectorFactory.connect(serviceURL, h); connection = connector.getMBeanServerConnection(); } /** * Retrieve connection * * @return connection * @throws IOException * @throws MalformedURLException * @throws Exception */ public MBeanServerConnection getConnection() throws IOException { if (connection == null) { connect(); } return connection; } protected ObjectName initMBean(String mbName) throws MalformedObjectNameException { // TODO: Create a cache? return new ObjectName(mbName); } /** * Get the value of an attribute of a MBean * * @param mbName * MBean name * @param attributeName * attribute name * @return value * @throws MalformedObjectNameException * @throws IOException * @throws MalformedURLException * @throws ReflectionException * @throws MBeanException * @throws InstanceNotFoundException * @throws AttributeNotFoundException * @throws Exception */ public Object getAttribute(String mbName, String attributeName) throws MalformedObjectNameException, AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException, IOException { ObjectName service = initMBean(mbName); return getConnection().getAttribute(service, attributeName); } /** * Invoke a MBean method * * @param mbName * MBean name * @param methodName * method name * @param signature * method signature * @param params * method params * @return method return value * @throws MalformedObjectNameException * @throws IOException * @throws MalformedURLException * @throws ReflectionException * @throws MBeanException * @throws InstanceNotFoundException * @throws Exception */ public Object invokeMethod(String mbName, String methodName, String[] signature, Object[] params) throws MalformedObjectNameException, InstanceNotFoundException, MBeanException, ReflectionException, IOException { ObjectName service = initMBean(mbName); return getConnection().invoke(service, methodName, params, signature); } /** * Invoke a MBean method * * @param mbName * MBean name * @param methodName * method name * @param params * method params * @return method return value * @throws IOException * @throws MalformedURLException * @throws ReflectionException * @throws MBeanException * @throws InstanceNotFoundException * @throws MalformedObjectNameException * @throws Exception */ public Object invokeMethod(String mbName, String methodName, Object... params) throws MalformedObjectNameException, InstanceNotFoundException, MBeanException, ReflectionException, IOException { if (params == null) { return this.invokeMethod(mbName, methodName, new String[] {}, new Object[] {}); } String[] signature = new String[params.length]; for (int sigIdx = 0; sigIdx < signature.length; sigIdx++) { signature[sigIdx] = params[sigIdx].getClass().getCanonicalName(); } return this.invokeMethod(mbName, methodName, signature, params); } /** * Invoke a MBean method * * @param mbName * MBean name * @param methodName * method name * @return method return value * @throws IOException * @throws MalformedURLException * @throws ReflectionException * @throws MBeanException * @throws InstanceNotFoundException * @throws MalformedObjectNameException * @throws Exception */ public Object invokeMethod(String mbName, String methodName) throws MalformedObjectNameException, InstanceNotFoundException, MBeanException, ReflectionException, IOException { return this.invokeMethod(mbName, methodName, (Object[]) null); } }
A conexão aqui está específica para o WebLogic que é o meu servidor alvo. Caso você tenha interesse, pode modificar para qualquer outro servidor. Para utilizar essa classe, existe algumas informações que você vai precisar, como os nomes dos MBeans :). No WebLogic, acesse o Enterprise Manager, vá em WebLogic Domain e selecione o domínio alvo. No menu superior, escolha WebLogic Domain, System MBean Browser. No meu caso, eu tenho um servidor SOA e gostaria de saber quais são as partições e repositórios que existem nele. Para isso vou escolher o MBean que está localizado em Application Defined MBeans em oracle.mds.lcm, Domain:soa_domain, MDSDomainRuntime, MDSDomainRuntime:
Ao lado irão abrir as informações dos atributos, métodos e notificações. A parte mais importante nesse momento é um "+ Show MBean Information" que existe na parte superior, clique nele e copie a informação sobre o nome do MBean:
Escolhe um atributo ou operação e agora é só utilizar a classe da seguinte forma:
MBeanConnector mbConn = new MBeanConnector("localhost", 7001, "weblogic", "weblogic1"); String[] repositories = (String[]) mbConn.invokeMethod( "oracle.mds.lcm:name=MDSDomainRuntime,type=MDSDomainRuntime", "listRepositories");
No array repositories você terá a lista de repositórios MDS, pois invoquei o método listRepositories do MBean com o nome que recuperei do EM: oracle.mds.lcm:name=MDSDomainRuntime,type=MDSDomainRuntime.
Se precisar passar parâmetros, você pode executar o seguinte código:
String[] p = (String[]) mbConn .invokeMethod( "oracle.mds.lcm:name=MDSDomainRuntime,type=MDSDomainRuntime", "listPartitions", "mds-soa");
Você pode executar qualquer método ou recuperar a informação de qualquer atributo de um MBean de maneira simples. Agora é só se aventurar.