Applies to: JBoss 4.0.5 GA
As I am working on a rather complex application with a lot of dependancy bounded MBeans I found it necessary to have a small application, in a different JVM, invoke a MBean method for administrative purposes. Even if this sounded easy at the begining it seemed that I had to face 2 problems:
- JBoss JMX implementation
- JAAS access to the secured console
Since I both googled and searched JBoss forums without much help I decided, upon succeding, to write this article as it might help someone futher.
The ideea was to get access to a MBean service with the name:
ro.nit.test:service=Test
and to be able to get it’s “Message” attribute and also invoke a remove method called: “printMessage”. The jmx-console was protected with admin/simple
The working code is:
AppCallbackHandler handler = new AppCallbackHandler("admin", "simple".toCharArray());
LoginContext lc = new LoginContext("TestClient", handler);
System.out.println("Created LoginContext");lc.login();
Hashtable env = new Hashtable();
String factory = "org.jnp.interfaces.NamingContextFactory";
env.put(Context.INITIAL_CONTEXT_FACTORY, factory);
String url1 = "jnp://localhost:1099";env.put(Context.PROVIDER_URL, url1);
env.put(Context.SECURITY_CREDENTIALS, "simple");
env.put(Context.SECURITY_PRINCIPAL, "admin");
env.put(Context.SECURITY_PROTOCOL, "testLoginInitialContext");
Context ctx = new InitialContext(env);
MBeanServerConnection mconn = (MBeanServerConnection) ctx.lookup("jmx/invoker/RMIAdaptor");
ObjectName name = new ObjectName("ro.nit.test:service=Test");
Object val = mconn.getAttribute(name, "Message");
System.out.println(name + "\n\tmessage=" + val);
mconn.invoke(name, "printMessage", null, null);
This makes use of the following CallbackHandler implementation:
static class AppCallbackHandler implements CallbackHandler {
private String username;
private char[] password;
public AppCallbackHandler(String username, char[] password) {
this.username = username;
this.password = password;
}
public void handle(Callback[] callbacks) throws java.io.IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof NameCallback) {
NameCallback nc = (NameCallback) callbacks[i];
nc.setName(username);
} else if (callbacks[i] instanceof PasswordCallback) {
PasswordCallback pc = (PasswordCallback) callbacks[i];
pc.setPassword(password);
} else {
throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
}
}
}
}
The “auth.conf” file required by JAAS:
other {
// jBoss LoginModule org.jboss.security.ClientLoginModule required ;
// Put your login modules that need jBoss here};
The JVM parameters:
-Djava.security.auth.login.config=file:${path to file}/auth.conf
Links with helped me found the solution:
- http://www.jboss.com/index.html?module=bb&op=viewtopic&t=95530&view=previous
- http://www.jboss.org/index.html?module=bb&op=viewtopic&t=84303
- http://www.jboss.org/index.html?module=bb&op=viewtopic&t=83861
Some errors which I got on the way:
- Exception in thread “main” java.lang.SecurityException: Failed to authenticate principal=null, securityDomain=jmx-console
The original code (according to JSR160):
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:8080/jmx-console");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
ObjectName stdMBeanName = new ObjectName("ro.nit.test:service=Test");
mbsc.setAttribute(stdMBeanName, new Attribute("Message", "New message set from remote"));
// TODO, will not work with JBOSS since it does not implement the
// JMX properly
// http://www.jboss.com/index.html?module=bb&op=viewtopic&t=95530&view=previous
Recent Comments