Search |
||
Client context in the new JMX APIPosted by emcmanus on December 5, 2008 at 5:37 AM PST
I've mentioned in the past that one of the new features in version 2.0 of the JMX API is "client contexts", which will allow a client to communicate context information to a server, and a server to adjust its behaviour accordingly. The most obvious example is locale, where for example the client says that it is in the French locale and the server translates its messages and descriptions into French. A slightly less obvious example is transaction ids. Here the client sets up a transaction (perhaps related to a database), performs a number of requests on the server in the context of that transactions, then commits or aborts the transaction. Updating configuration is the most obvious example where this is useful, especially if the configuration is controlled by several JMX MBeans. You want the update to have the usual transaction properties, like atomicity and consistency, and for this to be possible the participating MBeans must know their common transaction id. (I should add that we don't have explicit support for transactions in the JMX API, but we do now have everything you need to build the transactional solution that is appropriate for you.) Generalizing, a client context is
a So what does all this look like in code? Let's take the French example to see. Client sideSuppose the client has created a connection to the server in the usual way:
JMXServiceURL url = ...server address...;
JMXConnector connector = JMXConnectorFactory.connect(url);
MBeanServerConnection connection = connector.getMBeanServerConnection();
All the new stuff related to client contexts is in the
unimaginatively
named ClientContext
class. We can make a
MBeanServerConnection frenchConnection =
ClientContext.withContext(connection, "jmx.locale", "fr");
For the particular case of
MBeanServerConnection frenchConnection =
ClientContext.withLocale(connection, Locale.FRENCH);
In either case, you can do everything
with
String message = (String)
frenchConnection.getAttribute(objectName, "Message");
Server sideNow suppose we want to write the MBean named
by
public interface ExampleMBean {
public String getMessage();
}
public class Example implements ExampleMBean {
public String getMessage() {
return "My hovercraft is full of eels";
}
}
Here's a simplified context-aware version:
public class Example implements ExampleMBean {
public String getMessage() {
Locale locale = ClientContext.getLocale();
String language = locale.getLanguage();
if (language.equals(Locale.FRENCH.getLanguage()))
return "Mon aéroglisseur est rempli d'anguilles";
else
return "My hovercraft is full of eels";
}
}
(In reality you would want to use ResourceBundles and the like, rather than hard-coding translations like this.) Like
String xid = ClientContext.getContext().get("com.example.xid");
Context for local clientsA client in the same Virtual Machine as the server may have a
direct reference to the MBeanServer object. In that case it has
an alternative way of setting the context. Instead of
using
Map<String,String> newContext =
Collections.singletonMap("jmx.locale", Locale.FRENCH.toString());
String message =
ClientContext.doWithContext(
newContext,
new Callable<String>() {
return (String)
mbeanServer.getAttribute(objectName, "Message");
}
);
If you want to add items to the context rather than replacing it, you can do that straightforwardly:
Map<String,String> newContext =
new HashMap<String,String>(ClientContext.getContext());
The Map returned by No need to care after this pointThat's basically all you need to know to understand contexts. If you're not interested in the gory details, you can stop reading now. How it works: the ugly truthIf we had designed contexts into the JMX Remote API from the very beginning then this would all work in an obvious way. Each protocol request from the client to the server would include the context, if any. On the server side, the context would be decoded from the request and attached to thread handling the request. While we could have modified the JMX Remote API to work this way in the 2.0 API, it would have posed interoperability concerns. Contexts would only have been available if the client, server, and connector were all running the latest version. Pre-2.0 clients would have had no way to send contexts to servers; pre-2.0 servers would have had no way to receive contexts from clients; and pre-2.0 connector protocols (which is all connectors today) would have been unable to communicate contexts. Instead, based on an idea
by Simone Bordet, we
defined a way to encode the context of a request into the target
ObjectName of that request. We do this with a special
pseudo-namespace
called I called For these reasons, we simulate
a
»
Related Topics >>
Open JDK Comments
Comments are listed in date ascending order (oldest first)
Submitted by vlioutyi_i2 on Fri, 2009-01-30 16:11.
Eamon,
http://weblogs.java.net/blog/emcmanus/archive/2007/02/index.html
We consider use JMX for monitoring complex distributed application that runs on multiple hosts and seems like using mirrors would greatly simplify our management application. MBeanServerDelegate could be used to synchronize lifetime of mirror and mirrored beans. We are trying to decide if we want to use Relation Service to describe relationships between beans or not.
We can use mirror for Relation Service beans of sub-agents, assuming that relations may be established only between beans that are from the same JVM. But this would be rather strong restriction. Or we can try to replicate relations from Relation Service of sub-agent to Relation Service of an agent, using notifications of relation service.
What would be you recommendation for using relation service and presenting relations from sub-agents on master agent, considering that we have to use JDK 1.5?
Thanks a lot,
Viktor
Submitted by b_eckenfels on Mon, 2009-04-27 15:39.
Hello Eamonn,
how are you doing? Got quiet here on the Blog.
I have a somewhat (to the article) unrelated point to discuss. Do you know if any work on the platform management side is going on? The current MemoryPool, MemoryManager and GarbageCollection PlatformMBeans fall short in monitoring application performance. For example it is hard to track the serial GC if you have lots of allocation failures in CMS. It is also hard to support the new G1 metrics.
It is also not so easy to measure object allocation rates or distinguish between concurrent and stop-the-world times.
Even jstat fails to deliver that, and you would have to parse it from verbose GC logs. Its really a think some JMX counters could greatly improve.
Greetings
Bernd
Submitted by ecki on Sun, 2008-12-07 22:16.
Is the authorisation context (subject, user, role,...) also something which should be propagated this way. I am not sure if JAAS in connection to JMX is somewhere defined?
Session and transaction IDs are really usefull. If only there would be a way to actually access a TX id in a JavaEE CMT component...
Submitted by emcmanus on Mon, 2008-12-08 02:34.
ecki, that's a very interesting question! I think the answer is no, because in general you cannot trust a client to be telling the truth about its authorized identity. You need to have some kind of authentication mechanism between the client and the server.
The JMX Remote API already has provision for "subject delegation". The idea is that you can say that if the client has authenticated with a certain identity then it is allowed to claim certain other identities. So you can set up an authenticated connection as TrustedClient and then do operations on behalf of IdentityA and IdentityB. See JMXConnector.getMBeanServerConnection(Subject) and SubjectDelegationPermission.
By the way this is the nearest thing we have to client contexts today, and people have sometimes (ab)used it to communicate things like transaction IDs.
|
||
|
|