Please note that this documentation is not final and is subject to change.

Java™ Platform
Standard Ed. 7

DRAFT ea-b76

javax.management
Class ClientContext

java.lang.Object
  extended by javax.management.ClientContext

public class ClientContext
extends Object

Methods to communicate a client context to MBeans. A context is a Map<String, String> that is provided by the client and that an MBean can consult using the getContext() method. The context is set on a per-thread basis and can be consulted by any code that the target MBean calls within the thread.

One common usage of client context is to communicate the client's Locale to MBeans. For example, if an MBean has a String attribute LastProblemDescription, the value of that attribute could be a description of the last problem encountered by the MBean, translated into the client's locale. Different clients accessing this attribute from different locales would each see the appropriate version for their locale.

The locale case is sufficiently important that it has a special shorthand, the getLocale() method. This method calls getContext().get(LOCALE_KEY) and converts the resultant String into a Locale object.

Here is what an MBean with a localized LastProblemDescription attribute might look like:

 public class LocaleSensitive implements LocaleSensitiveMBean {
     ...
     public String getLastProblemDescription() {
         Locale loc = ClientContext.getLocale();
         ResourceBundle rb = ResourceBundle.getBundle("MyResources", loc);
         String resourceKey = getLastProblemResourceKey();
         return rb.getString(resourceKey);
     }
     ...
 }
 

Here is how a client can communicate its locale to the target MBean:

 JMXConnector connector = JMXConnectorFactory.connect(url);
 MBeanServerConnection connection = connector.getMBeanServerConnection();
 MBeanServerConnection localizedConnection =
     ClientContext.withLocale(connection, Locale.getDefault());
 String problem = localizedConnection.getAttribute(
          objectName, "LastProblemDescription");
 

In the more general case where the client wants to communicate context other than the locale, it can use withContext instead of withLocale, and the target MBean can retrieve the context using getContext().

Remote use of contexts

The various with* methods, for example withLocale, transmit the context of each request by encoding it in the ObjectName of the request. For example, if a client creates a connection in the French locale like this...

 MBeanServerConnection mbsc = ...;
 Locale french = new Locale("fr");
 MBeanServerConnection localizedConnection = ClientContext.withLocale(mbsc, french);
 

...or, equivalently, like this...

 MBeanServerConnection localizedConnection =
     ClientContext.withContext(mbsc, "jmx.locale", "fr");
 

...then the context associates "jmx.locale" with "fr" and a request such as
localizedConnection.getAttribute("java.lang:type=Runtime", "Name")
is translated into
mbsc.getAttribute("jmx.context//jmx.locale=fr//java.lang:Runtime", "Name").
A special namespace jmx.context// extracts the context from the string jmx.locale=fr and establishes it in the thread that will do
getAttribute("java.lang:Runtime", "Name").

The details of how contexts are encoded into ObjectNames are explained in the encode method.

The namespace jmx.context// just mentioned is only needed by remote clients, since local clients can set the context directly using doWithContext. Accordingly, this namespace is not present by default in the MBeanServer. Instead, it is simulated by the standard RMI connector using a special MBeanServerForwarder. If you are using this connector, you do not need to do anything special. Other connectors may or may not simulate this namespace in the same way. If the connector server returns true from the method supportsSystemMBeanServerForwarder then it does simulate the namespace. If you are using another connector, or if you want to be able to use the with* methods locally, then you can install the MBeanServerForwarder yourself as described in the method newContextForwarder.


Field Summary
Modifier and Type Field and Description
static String LOCALE_KEY
          The context key for the client locale.
static String NAMESPACE
          The namespace that implements contexts, "jmx.context".
 
Method Summary
Modifier and Type Method and Description
static
<T> T
doWithContext(Map<String,String> context, Callable<T> task)
          Execute the given task with the client context set to the given Map.
static String encode(Map<String,String> context)
          Returns an encoded context prefix for ObjectNames.
static Map<String,String> getContext()
          Get the client context associated with the current thread.
static Locale getLocale()
          Get the client locale associated with the current thread.
static MBeanServerForwarder newContextForwarder(MBeanServer nextMBS, MBeanServer loopMBS)
          Create a new MBeanServerForwarder that applies the context received from a client to the current thread.
static MBeanServerForwarder newLocalizeMBeanInfoForwarder(MBeanServer mbs)
          Create a new MBeanServerForwarder that localizes descriptions in MBeanInfo instances returned by getMBeanInfo.
static MBeanServerConnection withContext(MBeanServerConnection mbsc, String key, String value)
          Return an MBeanServerConnection object that is equivalent to the given MBeanServerConnection object except that operations on MBeans run with the given key bound to the given value in their thread context.
static MBeanServer withContext(MBeanServer mbs, String key, String value)
          Return an MBeanServer object that is equivalent to the given MBeanServer object except that operations on MBeans run with the given key bound to the given value in their thread context.
static MBeanServerConnection withDynamicContext(MBeanServerConnection mbsc)
          Returns an MBeanServerConnection object that is equivalent to the given MBeanServerConnection object except that remote operations on MBeans run with the context that has been established by the client using doWithContext.
static MBeanServerConnection withLocale(MBeanServerConnection mbsc, Locale locale)
          Return an MBeanServerConnection object that is equivalent to the given MBeanServerConnection object except that operations on MBeans run with the given Locale in their thread context.
static MBeanServer withLocale(MBeanServer mbs, Locale locale)
          Return an MBeanServer object that is equivalent to the given MBeanServer object except that operations on MBeans run with the given Locale in their thread context.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

LOCALE_KEY

public static final String LOCALE_KEY

The context key for the client locale. The string associated with this key is an encoded locale such as en_US which could be returned by Locale.toString().

See Also:
Constant Field Values

NAMESPACE

public static final String NAMESPACE

The namespace that implements contexts, "jmx.context".

See Also:
Constant Field Values
Method Detail

getContext

public static Map<String,String> getContext()

Get the client context associated with the current thread.

Returns:
the client context associated with the current thread. This may be an empty Map, but it cannot be null. The returned Map cannot be modified.

getLocale

public static Locale getLocale()

Get the client locale associated with the current thread. If the client context includes the "jmx.locale" key then the returned value is the Locale encoded in that key. Otherwise the returned value is the default locale.

Returns:
the client locale.

doWithContext

public static <T> T doWithContext(Map<String,String> context,
                                  Callable<T> task)
                       throws Exception

Execute the given task with the client context set to the given Map. This Map will be the result of getContext() within the task.

The task may include nested calls to doWithContext. The value returned by getContext() at any point is the Map provided to the most recent doWithContext (in the current thread) that has not yet returned.

The getContext() method returns the same value immediately after a call to this method as immediately before. In other words, doWithContext only affects the context during the execution of the task.

As an example, suppose you want to get an attribute with whatever context has already been set, plus the locale set to "fr". You could write this:

 Map<String, String> context =
     new HashMap<String, String>(ClientContext.getContext());
 context.put(ClientContext.LOCALE_KEY, "fr");
 String lastProblemDescription =
     ClientContext.doWithContext(context, new Callable<String>() {
         public String call() {
             return (String) mbeanServer.getAttribute(mbean, "LastProblemDescription");
         }
     });
 

Type Parameters:
T - the type of value that the task will return. This type parameter is usually inferred from the type of the task parameter. For example, if task is a Callable<String> then T is String. If the task does not return a value, use a Callable<Void> and return null from its call method.
Parameters:
context - the context to use while executing task.
task - the task to run with the key=value binding.
Returns:
the result of task.call().
Throws:
IllegalArgumentException - if either parameter is null, or if any key in context is null or empty, or if any value in context is null.
Exception - If task.call() throws an exception, doWithContext throws the same exception.

withLocale

public static MBeanServer withLocale(MBeanServer mbs,
                                     Locale locale)

Return an MBeanServer object that is equivalent to the given MBeanServer object except that operations on MBeans run with the given Locale in their thread context. Note that this will only work if the given MBeanServer supports contexts, as described above.

This method is equivalent to withContext(mbs, "jmx.locale", locale.toString()).

Throws:
IllegalArgumentException - if either parameter is null, or if mbs does not support contexts. In the second case only, the cause of the IllegalArgumentException will be an InstanceNotFoundException.

withLocale

public static MBeanServerConnection withLocale(MBeanServerConnection mbsc,
                                               Locale locale)

Return an MBeanServerConnection object that is equivalent to the given MBeanServerConnection object except that operations on MBeans run with the given Locale in their thread context. Note that this will only work if the given MBeanServerConnection supports contexts, as described above.

This method is equivalent to withContext(mbs, "jmx.locale", locale.toString()).

Throws:
IllegalArgumentException - if either parameter is null, or if the communication with mbsc fails, or if mbsc does not support contexts. If the communication with mbsc fails, the cause of this exception will be an IOException. If mbsc does not support contexts, the cause will be an InstanceNotFoundException.

withContext

public static MBeanServer withContext(MBeanServer mbs,
                                      String key,
                                      String value)

Return an MBeanServer object that is equivalent to the given MBeanServer object except that operations on MBeans run with the given key bound to the given value in their thread context. Note that this will only work if the given MBeanServer supports contexts, as described above.

Parameters:
mbs - the original MBeanServer.
key - the key to bind in the context of MBean operations in the returned MBeanServer object.
value - the value to bind to the key in the context of MBean operations in the returned MBeanServer object.
Throws:
IllegalArgumentException - if any parameter is null, or if key is the empty string, or if mbs does not support contexts. In the last case only, the cause of the IllegalArgumentException will be an InstanceNotFoundException.

withContext

public static MBeanServerConnection withContext(MBeanServerConnection mbsc,
                                                String key,
                                                String value)

Return an MBeanServerConnection object that is equivalent to the given MBeanServerConnection object except that operations on MBeans run with the given key bound to the given value in their thread context. Note that this will only work if the given MBeanServerConnection supports contexts, as described above.

Parameters:
mbsc - the original MBeanServerConnection.
key - the key to bind in the context of MBean operations in the returned MBeanServerConnection object.
value - the value to bind to the key in the context of MBean operations in the returned MBeanServerConnection object.
Throws:
IllegalArgumentException - if any parameter is null, or if key is the empty string, or if the communication with mbsc fails, or if mbsc does not support contexts. If the communication with mbsc fails, the cause of this exception will be an IOException. If mbsc does not support contexts, the cause will be an InstanceNotFoundException.

withDynamicContext

public static MBeanServerConnection withDynamicContext(MBeanServerConnection mbsc)

Returns an MBeanServerConnection object that is equivalent to the given MBeanServerConnection object except that remote operations on MBeans run with the context that has been established by the client using doWithContext. Note that this will only work if the remote system supports contexts, as described above.

For example, suppose the remote system does support contexts, and you have created a JMXConnector like this:

 JMXServiceURL url = ...;
 JMXConnector client = JMXConnectorFactory.connect(url);
 MBeanServerConnection mbsc = client.getMBeanServerConnection();
 mbsc = ClientContext.withDynamicContext(mbsc);
 

Then if you do this...

 MBeanInfo mbi = ClientContext.doWithContext(
     Collections.singletonMap(ClientContext.LOCALE_KEY, "fr"),
     new Callable<MBeanInfo>() {
         public MBeanInfo call() {
             return mbsc.getMBeanInfo(objectName);
         }
     });
 

...then the context with the locale set to "fr" will be in place when the getMBeanInfo is executed on the remote MBean Server.

Parameters:
mbsc - the original MBeanServerConnection.
Throws:
IllegalArgumentException - if the mbsc parameter is null, or if the communication with mbsc fails, or if mbsc does not support contexts. If the communication with mbsc fails, the cause of this exception will be an IOException. If mbsc does not support contexts, the cause will be an InstanceNotFoundException.

encode

public static String encode(Map<String,String> context)

Returns an encoded context prefix for ObjectNames. If the given context is empty, "" is returned. Otherwise, this method returns a string of the form "jmx.context//key=value;key=value;...". For example, if the context has keys "jmx.locale" and "xid" with respective values "fr" and "1234", this method will return "jmx.context//jmx.locale=fr;xid=1234" or "jmx.context//xid=1234;jmx.locale=fr".

Each key and each value in the encoded string is subject to encoding as if by the method URLEncoder.encode(String, String) with a character encoding of "UTF-8", but with the additional encoding of any * character as "%2A". This ensures that keys and values can contain any character. Without encoding, characters such as = and : would pose problems.

Parameters:
context - the context to encode.
Returns:
the context in encoded form.
Throws:
IllegalArgumentException - if the context parameter is null or if it contains a null key or value.

newContextForwarder

public static MBeanServerForwarder newContextForwarder(MBeanServer nextMBS,
                                                       MBeanServer loopMBS)

Create a new MBeanServerForwarder that applies the context received from a client to the current thread. A client using one of the various with* methods (for example withContext) will encode that context into the ObjectName of each MBeanServer request. The object returned by this method decodes the context from that ObjectName and applies it as described for doWithContext while performing the MBeanServer request using the ObjectName without the encoded context.

This forwarder can be used in a number of ways:

Parameters:
nextMBS - the next MBeanServer in the chain of forwarders, which might be another MBeanServerForwarder or a plain MBeanServer. This is the object to which MBeanServer requests that do not include a context are sent. It will be the value of getMBeanServer() on the returned object, and can be changed with setMBeanServer. It can be null but must be set to a non-null value before any MBeanServer requests arrive.
loopMBS - the MBeanServer to which requests that contain an encoded context should be sent once the context has been decoded. For example, if the request is getAttribute("jmx.context//jmx.locale=fr//java.lang:type=Runtime", "Name"), then the context of the thread executing that request will have "jmx.locale" set to "fr" while executing loopMBS.getAttribute("java.lang:type=Runtime", "Name"). If this parameter is null, then these requests will be sent to the newly-created MBeanServerForwarder. Usually the parameter will either be null or will be the result of getSystemMBeanServerForwarder() for the connector server in which this forwarder will be installed.
Returns:
a new MBeanServerForwarder that decodes client context from ObjectNames.

newLocalizeMBeanInfoForwarder

public static MBeanServerForwarder newLocalizeMBeanInfoForwarder(MBeanServer mbs)

Create a new MBeanServerForwarder that localizes descriptions in MBeanInfo instances returned by getMBeanInfo. The MBeanServerForwarder returned by this method passes all MBeanServer methods through unchanged to the supplied object, mbs, with the exception of getMBeanInfo. To handle getMBeanInfo(objectName), it calls mbs.getMBeanInfo(objectName) to get an MBeanInfo, mbi; it calls mbs.getClassLoaderFor(objectName) to get a ClassLoader, cl; and it calls getLocale() to get a Locale, locale. The order of these three calls is not specified. Then the result is mbi.localizeDescriptions(locale, loader).

This forwarder can be used in a number of ways:

Parameters:
mbs - the next MBeanServer in the chain of forwarders, which might be another MBeanServerForwarder or a plain MBeanServer. It will be the value of getMBeanServer() on the returned object, and can be changed with setMBeanServer. It can be null but must be set to a non-null value before any MBeanServer requests arrive.
Returns:
a new MBeanServerForwarder that localizes descriptions in the result of getMBeanInfo.

Java™ Platform
Standard Ed. 7

DRAFT ea-b76

Submit a bug or feature

Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. Use is subject to license terms.