More Books
JBoss 4.0 The Official Guide
JBoss® 4.0 The Official Guide
Table of Contents
Copyright
About the Authors
We Want to Hear from You!
Introduction
What This Book Covers
About JBoss
About Open Source
About Professional Open Source
What's New in JBoss 4.0
Chapter 1.  Installing and Building the JBoss Server
Getting the Binary Files
Installing the Binary Package
Basic Installation Testing
Booting from a Network Server
Building the Server from Source Code
Chapter 2.  The JBoss JMX Microkernel
JMX
The JBoss JMX Implementation Architecture
Connecting to the JMX Server
Using JMX as a Microkernel
The JBoss Deployer Architecture
Exposing MBean Events via SNMP
Remote Access to Services, Detached Invokers
Chapter 3.  Naming on JBoss
An Overview of JNDI
The JBossNS Architecture
Chapter 4.  Transactions on JBoss
Transaction and JTA Overview
JBoss Transaction Internals
Chapter 5.  EJBs on JBoss
The EJB Client-Side View
The EJB Server-Side View
The EJB Container
Entity Bean Locking and Deadlock Detection
Chapter 6.  Messaging on JBoss
JMS Examples
JBossMQ Overview
JBossMQ Configuration and MBeans
Specifying the MDB JMS Provider
Chapter 7.  Connectors on JBoss
JCA Overview
An Overview of the JBossCX Architecture
Configuring JDBC Datasources
Configuring Generic JCA Adaptors
Chapter 8.  Security on JBoss
J2EE Declarative Security Overview
An Introduction to JAAS
The JBoss Security Model
The JBossSX Architecture
The Secure Remote Password (SRP) Protocol
Running JBoss with a Java 2 Security Manager
Using SSL with JBoss and JSSE
Configuring JBoss for Use Behind a Firewall
Securing the JBoss Server
Chapter 9.  Web Applications
The Tomcat Service
The Tomcat server.xml File
The Engine Element
The Host Element
Using SSL with the JBoss/Tomcat Bundle
Setting the Context Root of a Web Application
Setting Up Virtual Hosts
Serving Static Content
Using Apache with Tomcat
Using Clustering
Integrating Third-Party Servlet Containers
Chapter 10.  MBean Services Miscellany
System Properties Management
Property Editor Management
Services Binding Management
Scheduling Tasks
The Log4j Service MBean
RMI Dynamic Class Loading
Chapter 11.  The CMP Engine
Example Code
The jbosscmp-jdbc Structure
Entity Beans
CMP Fields
Container-Managed Relationships
Declaring Queries
Optimized Loading
The Loading Process
Transactions
Optimistic Locking
Entity Commands and Primary Key Generation
JBoss Global Defaults
Datasource Customization
Chapter 12.  Web Services
JAX-RPC Service Endpoints
Enterprise JavaBean Endpoints
Web Services ClientsA JAX-RPC Client
Service References
Chapter 13.  Hibernate
The Hibernate MBean
Hibernate Archives
Using Hibernate Objects
Using a HAR File Inside an EAR File
The HAR Deployer
Chapter 14.  Aspect-Oriented Programming (AOP) Support
JBoss AOP: EJB-Style Services for Plain Java Objects
Why AOP?
Basic Concepts of AOP
Building JBoss AOP Applications
The JBoss AOP Deployer
Packaging and Deploying AOP Applications to JBoss
Appendix A.  The GNU Lesser General Public License (LGPL)
GNU General Public License
Appendix B.  Example Installation
Index
SYMBOL
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X

Connecting to the JMX Server

JBoss includes adaptors that allow access to the JMX MBeanServer from outside the JBoss server VM. The current adaptors include HTML, an RMI interface, and an EJB.

Inspecting the Server: The JMX Console Web Application

JBoss comes with its own implementation of a JMX HTML adaptor that allows you to view the server's MBeans, using a standard web browser. The default URL for the console web application is http://localhost:8080/jmx-console/. If you browse to this location, you will see something similar to what is presented in Figure 2.12.

Figure 2.12. The JBoss JMX Console web application agent view.


The top view is called the agent view, and it provides a listing of all MBeans registered with the MBeanServer, sorted by the domain portion of the MBean's ObjectName. Under each domain you can see the MBeans that are in that domain. When you select one of the MBeans, you are taken to the MBean view, where you can view and edit an MBean's attributes as well as invoke operations. As an example, Figure 2.13 shows the MBean view for the jboss.system:type=Server MBean.

Figure 2.13. The MBean view for the jboss.system:type=Server MBean.


The source code for the JMX Console web application is located in the varia module, under the src/ main/org/jboss/jmx directory. Its web pages are located under varia/src/resources/jmx. The application is a simple MVC servlet with JSP views that utilize the MBeanServer.

Securing the JMX Console

Because the JMX Console web application is just a standard servlet, it can be secured using standard J2EE role-based security. The jmx-console.war is deployed as an unpacked WAR that includes template settings for quickly enabling simple username- and password-based access restrictions. If you look at the jmx-console.war in the server/default/deploy directory, you will find the web.xml and jboss-web.xml descriptors in the WEB-INF directory and jmx-console-roles.properties and jmx-console-users.properties files under WEB-INF/classes.

By uncommenting the security sections of the web.xml and jboss-web.xml descriptors, as shown in Listing 2.10 and Listing 2.11, you enable HTTP basic authentication that restricts access to the JMX Console application to the user admin with password admin. The username and password are determined by the admin=admin line in the jmx-console-users.properties file.

Listing 2.10. The jmx-console.war web.xml Descriptors, with the Security Elements Uncommented
<?xml version="1.0"?>
<!DOCTYPE web-app PUBLIC
          "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
          "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
    <!-- ... -->

    <!-- A security constraint that restricts access to the HTML JMX console
         to users with the role JBossAdmin. Edit the roles to what you want and
         uncomment the WEB-INF/jboss-web.xml/security-domain element to enable
         secured access to the HTML JMX console.
    -->
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>HtmlAdaptor</web-resource-name>
            <description> An example security config that only allows users with
                the role JBossAdmin to access the HTML JMX console web
                application </description>
            <url-pattern>/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>JBossAdmin</role-name>
        </auth-constraint>
    </security-constraint>
    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>JBoss JMX Console</realm-name>
    </login-config>
    <security-role>
        <role-name>JBossAdmin</role-name>
    </security-role>
</web-app>

Listing 2.11. The jmx-console.war jboss-web.xml Descriptors, with the Security Elements Uncommented
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss-web
    PUBLIC "-//JBoss//DTD Web Application 2.3//EN"
    "http://www.jboss.org/j2ee/dtd/jboss-web_3_0.dtd">
<jboss-web>
    <!--

        Uncomment the security-domain to enable security. You will
        need to edit the htmladaptor login configuration to set up the
        login modules used to authenticate users.
    -->
    <security-domain>java:/jaas/jmx-console</security-domain>
</jboss-web>

Make these changes to uncomment the security code, and then when you try to access the JMX Console URL, you will see a dialog similar to the one shown in Figure 2.14.

Figure 2.14. The JMX Console basic HTTP login dialog.


By default JBoss uses properties files for securing access to the JMX Console application. To see how to better configure the security settings of web applications, see Chapter 8, "Security on JBoss."

Connecting to JMX Using RMI

JBoss supplies an RMI interface for connecting to the JMX MBeanServer. This interface is org.jboss.jmx.adaptor.rmi.RMIAdaptor. The RMIAdaptor interface is bound into JNDI in the default location jmx/invoker/RMIAdaptor, as well as jmx/rmi/RMIAdaptor for backward compatibility with older clients.

Listing 2.12 shows a client that makes use of the RMIAdaptor interface to query the MBeanInfo for the JNDIView MBean. It also invokes the MBean's list(boolean) method and displays the result.

Listing 2.12. A JMX Client That Uses the RMIAdaptor Interface
public class JMXBrowser
{
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws Exception
    {
        InitialContext ic = new InitialContext();
        RMIAdaptor server = (RMIAdaptor) ic.lookup("jmx/invoker/RMIAdaptor");

        // Get the MBeanInfo for the JNDIView MBean
        ObjectName name = new ObjectName("jboss:service=JNDIView");
        MBeanInfo  info = server.getMBeanInfo(name);
        System.out.println("JNDIView Class: " + info.getClassName());

        MBeanOperationInfo[] opInfo = info.getOperations();
        System.out.println("JNDIView Operations: ");
        for(int o = 0; o < opInfo.length; o ++) {
            MBeanOperationInfo op = opInfo[o];

            String returnType = op.getReturnType();
            String opName     = op.getName();
            System.out.print(" + " + returnType + " " + opName + "(");

            MBeanParameterInfo[] params = op.getSignature();
            for(int p = 0; p < params.length; p++) {
                MBeanParameterInfo paramInfo = params[p];

                String pname = paramInfo.getName();
                String type  = paramInfo.getType();

                if (pname.equals(type)) {
                    System.out.print(type);
                } else {
                    System.out.print(type + " " + name);
                }

                if (p < params.length-1) {
                    System.out.print(',');
                }
            }
            System.out.println(")");
        }

        // Invoke the list(boolean) op
        String[] sig    = {"boolean"};
        Object[] opArgs = {Boolean.TRUE};
        Object   result = server.invoke(name, "list", opArgs, sig);

        System.out.println("JNDIView.list(true) output:\n"+result);
    }
}

To test the client access using the RMIAdaptor, you should run the following:


[examples]$ ant -Dchap=chap2 -Dex=4 run-example
...

run-example4:
     [java] JNDIView Class: org.jboss.mx.modelmbean.XMBean
     [java] JNDIView Operations:
     [java]  + java.lang.String list(boolean jboss:service=JNDIView)
     [java]  + java.lang.String listXML()
     [java]  + void create()
     [java]  + void start()
     [java]  + void stop()
     [java]  + void destroy()
     [java]  + void jbossInternalLifecycle(java.lang.String jboss:service=JNDIView)
     [java]  + java.lang.String getName()
     [java]  + int getState()
     [java]  + java.lang.String getStateString()
     [java] JNDIView.list(true) output:
     [java] <h1>java: Namespace</h1>
     [java] <pre>
     [java]   +- XAConnectionFactory (class: org.jboss.mq.SpyXAConnectionFactory)
     [java]   +- DefaultDS (class: javax.sql.DataSource)
     [java]   +- SecurityProxyFactory (class: org.jboss.security.SubjectSecurityProxyFactory)
     [java]   +- DefaultJMSProvider (class: org.jboss.jms.jndi.JNDIProviderAdapter)
     [java]   +- comp (class: javax.naming.Context)
     [java]   +- JmsXA (class: org.jboss.resource.adapter.jms.JmsConnectionFactoryImpl)
     [java]   +- ConnectionFactory (class: org.jboss.mq.SpyConnectionFactory)
     [java]   +- jaas (class: javax.naming.Context)
     [java]   |   +- JmsXARealm (class: org.jboss.security.plugins.SecurityDomainContext)
     [java]   |   +- jbossmq (class: org.jboss.security.plugins.SecurityDomainContext)
     [java]   |   +- HsqlDbRealm (class: org.jboss.security.plugins.SecurityDomainContext)
     [java]   +- timedCacheFactory (class: javax.naming.Context)
     [java] Failed to lookup: timedCacheFactory, errmsg=null
     [java]   +- TransactionPropagationContextExporter (class: org.jboss.tm
.TransactionPropagationContextFactory)
     [java]   +- StdJMSPool (class: org.jboss.jms.asf.StdServerSessionPoolFactory)
     [java]   +- Mail (class: javax.mail.Session)
     [java]   +- TransactionPropagationContextImporter (class: org.jboss.tm
.TransactionPropagationContextImporter)
     [java]   +- TransactionManager (class: org.jboss.tm.TxManager)
     [java] </pre>
     [java] <h1>Global JNDI Namespace</h1>
     [java] <pre>
     [java]   +- XAConnectionFactory (class: org.jboss.mq.SpyXAConnectionFactory)
     [java]   +- UIL2ConnectionFactory[link -> ConnectionFactory] (class: javax.naming
.LinkRef)
     [java]   +- UserTransactionSessionFactory (proxy: $Proxy11 implements interface org
.jboss.tm.usertx.interfaces.UserTransactionSessionFactory)
     [java]   +- HTTPConnectionFactory (class: org.jboss.mq.SpyConnectionFactory)
     [java]   +- console (class: org.jnp.interfaces.NamingContext)
     [java]   |   +- PluginManager (proxy: $Proxy36 implements interface org.jboss.console
.manager.PluginManagerMBean)
     [java]   +- UIL2XAConnectionFactory[link -> XAConnectionFactory] (class: javax.naming
.LinkRef)
     [java]   +- UUIDKeyGeneratorFactory (class: org.jboss.ejb.plugins.keygenerator.uuid
.UUIDKeyGeneratorFactory)
     [java]   +- HTTPXAConnectionFactory (class: org.j boss.mq.SpyXAConnectionFactory)
     [java]   +- topic (class: org.jnp.interfaces.NamingContext)
     [java]   |   +- testDurableTopic (class: org.jboss.mq.SpyTopic)
     [java]   |   +- testTopic (class: org.jboss.mq.SpyTopic)
     [java]   |   +- securedTopic (class: org.jboss.mq.SpyTopic)
     [java]   +- queue (class: org.jnp.interfaces.NamingContext)
     [java]   |   +- A (class: org.jboss.mq.SpyQueue)
     [java]   |   +- testQueue (class: org.jboss.mq.SpyQueue)
     [java]   |   +- ex (class: org.jboss.mq.SpyQueue)
     [java]   |   +- DLQ (class: org.jboss.mq.SpyQueue)
     [java]   |   +- D (class: org.jboss.mq.SpyQueue)
     [java]   |   +- C (class: org.jboss.mq.SpyQueue)
     [java]   |   +- B (class: org.jboss.mq.SpyQueue)
     [java]   +- ConnectionFactory (class: org.jboss.mq.SpyConnectionFactory)
     [java]   +- UserTransaction (class: org.jboss.tm.usertx.client.ClientUserTransaction)
     [java]   +- jmx (class: org.jnp.interfaces.NamingContext)
     [java]   |   +- invoker (class: org.jnp.interfaces.NamingContext)
     [java]   |   |   +- RMIAdaptor (proxy: $Proxy35 implements interface org.jboss.jmx
.adaptor.rmi.RMIAdaptor, interface org.jboss.jmx.adaptor.rmi.RMIAdaptorExt)
     [java]   |   +- rmi (class: org.jnp.interfaces.NamingContext)
     [java]   |   |   +- RMIAdaptor[link -> jmx/invoker/RMIAdaptor] (class: javax.naming
.LinkRef)
     [java]   +- HiLoKeyGeneratorFactory (class: org.jboss.ejb.plugins.keygenerator.hilo
.HiLoKeyGeneratorFactory)
     [java]   +- UILXAConnectionFactory[link -> XAConnectionFactory] (class: javax.naming
.LinkRef)
     [java]   +- UILConnectionFactory[link -> ConnectionFactory] (class: javax.naming.LinkRef)
     [java] </pre>

Command-Line Access to JMX

JBoss provides a simple command-line tool that allows for interaction with a remote JMX server instance. This tool is called Twiddle (for twiddling bits via JMX) and is located in the bin directory of the distribution. Twiddle is a command execution tool, not a general command shell. It is run using either the twiddle.sh script or the twiddle.bat script; and passing in a -h(--help) argument provides the basic syntax, and --help-commands shows what you can do with the tool:

[bin]$ ./twiddle.sh -h
A JMX client to 'twiddle' with a remote JBoss server.

usage: twiddle.sh [options] <command> [command_arguments]

options:
    -h, --help                       Show this help message
        --help-commands              Show a list of commands
    -H=<command>               Show command specific help
    -c=command.properties            Specify the command.properties file to use
    -D<name>[=<value>]   Set a system property
    --                               Stop processing options
    -s, --server=<url>         The JNDI URL of the remote server
    -a, --adapter=<name>       The JNDI name of the RMI adapter to use
    -q, --quiet                      Be somewhat more quiet

Connecting Twiddle to a Remote Server

By default the twiddle command connects to the local host at port 1099 to look up the default jmx/rmi/RMIAdaptor binding of the RMIAdaptor service as the connector for communicating with the JMX server. To connect to a different server/port combination, you can use the -s (--server) option:

[bin]$ ./twiddle.sh -s toki serverinfo -d jboss
[bin]$ ./twiddle.sh -s toki:1099 serverinfo -d jboss

To connect using a different RMIAdaptor binding, you use the -a (--adapter) option:

[bin]$ ./twiddle.sh -s toki -a jmx/rmi/RMIAdaptor serverinfo -d jboss

Sample Twiddle Command Usage

To access basic information about a server, you use the serverinfo command:

[bin]$ ./twiddle.sh -H serverinfo
Get information about the MBean server

usage: serverinfo [options]

options:
    -d, --domain    Get the default domain
    -c, --count     Get the MBean count
    -l, --list      List the MBeans
    --              Stop processing options
[bin]$ ./twiddle.sh --server=toki serverinfo --count
460
[bin]$ ./twiddle.sh --server=toki serverinfo --domain
jboss

To query the server for the name of MBeans matching a pattern, you use the query command:

[bin]$ ./twiddle.sh -H query
Query the server for a list of matching MBeans

usage: query [options] <query>
options:
    -c, --count    Display the matching MBean count
    --             Stop processing options
Examples:
 query all mbeans: query '*:*'
 query all mbeans in the jboss.j2ee domain: query 'jboss.j2ee:*'
[bin]$ ./twiddle.sh -s toki query 'jboss:service=invoker,*'
jboss:readonly=true,service=invoker,target=Naming,type=http
jboss:service=invoker,type=jrmp
jboss:service=invoker,type=local
jboss:service=invoker,type=pooled
jboss:service=invoker,type=http
jboss:service=invoker,target=Naming,type=http

To get the attributes of an MBean, you use the get command:

[bin]$ ./twiddle.sh -H get
Get the values of one or more MBean attributes

usage: get [options] <name> [<attr>+]
  If no attribute names are given all readable attributes are retrieved
options:
    --noprefix    Do not display attribute name prefixes
    -- Stop       processing options
[bin]$ ./twiddle.sh get jboss:service=invoker,type=jrmp RMIObjectPort StateString
RMIObjectPort=4444
StateString=Started
[bin]$ ./twiddle.sh get jboss:service=invoker,type=jrmp
ServerAddress=0.0.0.0
RMIClientSocketFactoryBean=null
StateString=Started
State=3
RMIServerSocketFactoryBean=org.jboss.net.sockets.DefaultSocketFactory@ad093076
EnableClassCaching=false
SecurityDomain=null
RMIServerSocketFactory=null
Backlog=200
RMIObjectPort=4444
Name=JRMPInvoker
RMIClientSocketFactory=null

To query the MBeanInfo for an MBean, you use the info command:

[bin]$ ./twiddle.sh -H info
Get the metadata for an MBean

usage: info <mbean-name>
  Use '*' to query for all attributes
[bin]$ Description: Management Bean.
+++ Attributes:
 Name: ServerAddress
 Type: java.lang.String
 Access: rw
 Name: RMIClientSocketFactoryBean
 Type: java.rmi.server.RMIClientSocketFactory
 Access: rw
 Name: StateString
 Type: java.lang.String
 Access: r-
 Name: State
 Type: int
 Access: r-
 Name: RMIServerSocketFactoryBean
 Type: java.rmi.server.RMIServerSocketFactory
 Access: rw
 Name: EnableClassCaching
 Type: boolean
 Access: rw
 Name: SecurityDomain
 Type: java.lang.String
 Access: rw
 Name: RMIServerSocketFactory
 Type: java.lang.String
 Access: rw
 Name: Backlog
 Type: int
 Access: rw
 Name: RMIObjectPort
 Type: int
 Access: rw
 Name: Name
 Type: java.lang.String
 Access: r-
 Name: RMIClientSocketFactory
 Type: java.lang.String
 Access: rw
+++ Operations:
 void start()
 void jbossInternalLifecycle(java.lang.String java.lang.String)
 void create()
 void stop()
 void destroy()

To invoke an operation on an MBean, you use the invoker command:


[bin]$ ./twiddle.sh -H invoke
Invoke an operation on an MBean

usage: invoke [options] <query> <operation> (<arg>)*

options:
    -q, --query-type[=<type>]     Treat object name as a query
    --                            Stop processing options

query type:
    f[irst]    Only invoke on the first matching name [default]
    a[ll]      Invoke on all matching names
[bin]$ ./twiddle.sh invoke jboss:service=JNDIView list true
<h1>java: Namespace</h1>
<pre>
  +- XAConnectionFactory (class: org.jboss.mq.SpyXAConnectionFactory)
  +- DefaultDS (class: javax.sql.DataSource)
  +- SecurityProxyFactory (class: org.jboss.security.SubjectSecurityProxyFactory)
  +- DefaultJMSProvider (class: org.jboss.jms.jndi.JNDIProviderAdapter)
  +- comp (class: javax.naming.Context)
  +- JmsXA (class: org.jboss.resource.adapter.jms.JmsConnectionFactoryImpl)
  +- ConnectionFactory (class: org.jboss.mq.SpyConnectionFactory)
  +- jaas (class: javax.naming.Context)
  |   +- JmsXARealm (class: org.jboss.security.plugins.SecurityDomainContext)
  |   +- jbossmq (class: org.jboss.security.plugins.SecurityDomainContext)
  |   +- HsqlDbRealm (class: org.jboss.security.plugins.SecurityDomainContext)
  +- timedCacheFactory (class: javax.naming.Context)
Failed to lookup: timedCacheFactory, errmsg=null
  +- TransactionPropagationContextExporter (class: org.jboss.tm
.TransactionPropagationContextFactory)
  +- StdJMSPool (class: org.jboss.jms.asf.StdServerSessionPoolFactory)
  +- Mail (class: javax.mail.Session)
  +- TransactionPropagationContextImporter (class: org.jboss.tm
.TransactionPropagationContextImporter)
  +- TransactionManager (class: org.jboss.tm.TxManager)
</pre>
<h1>Global JNDI Namespace</h1>
<pre>
  +- XAConnectionFactory (class: org.jboss.mq.SpyXAConnectionFactory)
  +- UIL2ConnectionFactory[link -> ConnectionFactory] (class: javax.naming.LinkRef)
  +- UserTransactionSessionFactory (proxy: $Proxy11 implements interface org.jboss.tm
.usertx.interfaces.UserTransactionSessionFactory)
  +- HTTPConnectionFactory (class: org.jboss.mq.SpyConnectionFactory)
  +- console (class: org.jnp.interfaces.NamingContext)
  |   +- PluginManager (proxy: $Proxy36 implements interface org.jboss.console.manager
.PluginManagerMBean)
  +- UIL2XAConnectionFactory[link -> XAConnectionFactory] (class: javax.naming.LinkRef)
  +- UUIDKeyGeneratorFactory (class: org.jboss.ejb.plugins.keygenerator.uuid
.UUIDKeyGeneratorFactory)
  +- HTTPXAConnectionFactory (class: org.jboss.mq.SpyXAConnectionFactory)
  +- topic (class: org.jnp.interfaces.NamingContext)
  |   +- testDurableTopic (class: org.jboss.mq.SpyTopic)
  |   +- testTopic (class: org.jboss.mq.SpyTopic)
  |   +- securedTopic (class: org.jboss.mq.SpyTopic)
  +- queue (class: org.jnp.interfaces.NamingContext)
  |   +- A (class: org.jboss.mq.SpyQueue)
  |   +- testQueue (class: org.jboss.mq.SpyQueue)
  |   +- ex (class: org.jboss.mq.SpyQueue)
  |   +- DLQ (class: org.jboss.mq.SpyQueue)
  |   +- D (class: org.jboss.mq.SpyQueue)
  |   +- C (class: org.jboss.mq.SpyQueue)
  |   +- B (class: org.jboss.mq.SpyQueue)
  +- ConnectionFactory (class: org.jboss.mq.SpyConnectionFactory)
  +- UserTransaction (class: org.jboss.tm.usertx.client.ClientUserTransaction)
  +- jmx (class: org.jnp.interfaces.NamingContext)
  |   +- invoker (class: org.jnp.interfaces.NamingContext)
  |   |   +- RMIAdaptor (proxy: $Proxy35 implements interface org.jboss.jmx.adaptor.rmi
.RMIAdaptor, interface org.jboss.jmx.adaptor.rmi.RMIAdaptorExt)
  |   +- rmi (class: org.jnp.interfaces.NamingContext)
  |   |   +- RMIAdaptor[link -> jmx/invoker/RMIAdaptor] (class: javax.naming.LinkRef)
  +- HiLoKeyGeneratorFactory (class: org.jboss.ejb.plugins.keygenerator.hilo
.HiLoKeyGeneratorFactory)
  +- UILXAConnectionFactory[link -> XAConnectionFactory] (class: javax.naming.LinkRef)
  +- UILConnectionFactory[link -> ConnectionFactory] (class: javax.naming.LinkRef)
</pre>

Connecting to JMX Using Any Protocol

With the detached invokers and a somewhat generalized proxy factory capability, you can really talk to the JMX server by using the InvokerAdaptorService and a proxy factory service to expose an RMIAdaptor or similar interface over your protocol of choice. You'll learn about the detached invoker notion, along with proxy factories, later in this chapter, in the section "Remote Access to Services, Detached Invokers." See the section "A Detached Invoker Example, the MBeanServer Invoker Adaptor Service," later in this chapter, for an example of an invoker service that allows you to access the MBean server by using to the RMIAdaptor interface over any protocol for which a proxy factory service exists.