Customizing the JRMPContainerInvoker Socket Factories

Author:Scott Stark <Scott_Stark@displayscape.com>

Introduction

The RMI/JRMP based implementation of the org.jboss.ejb.ContainerInvoker interface supports customization of the socket factory implementation using the standard RMI java.rmi.server.RMIClientSocketFactory and java.rmi.server.RMIServerSocketFactory interfaces. This HowTo describes the customization usage and demonstrates an example custom factory from the 1.3 RMIThe Custom Socket Factory Tutorial

Configuring the ContainerInvoker

One of the many items that can be customized about the JBoss container configurations is the container invoker and its configuration. Figure 11.26 illustrates the jboss.xml elements that are available for customizing the container-invoker element when it is set to org.jboss.ejb.plugins.jrmp.server.JRMPContainerInvoker

Figure 11.26. jboss.xml container-invoker-config elements

1

The Optimized element tells if the container invoker to bypass RMI layer when the client is local (same VM as the server). This optimizes RMI calls. Its value must be true or false.

2

The RMIObjectPort element indicates what port the RMI objects created by this container should listen on. Any number of objects in the same VM can use the same port. However, objects in different VMs cannot use the same port. You may set this value to 0 to use anyonmous ports (that is, each object just picks a free port to use). If you want to run jBoss more than once on the same machine, you must either create separate configurations with separate ports, or set all the configurations to use anonymous port. The standard jBoss setting is "4444". Its value must an integer (0, or a valid port number). Note that normal user on a UNIX system cannot access privileged ports (less than 1024)

3

The RMIClientSocketFactory element indicates the use of a custom socket factory that should be used by RMI objects created by this container. The combination of socket factory type and port must be unique but more than one container can use the same socket factory, port combination. Its value must be the fully qualified name of the class that implements the java.rmi.server.RMIClientSocketFactory interface, and the class must be available to the JBoss class loader. If this element is not specified the default VM client socket factory will be used.

4

The RMIServerSocketFactory element indicates the use of a custom socket factory that should be used by RMI objects created by this container. The combination of socket factory type and port must be unique but more than one container can use the same socket factory, port combination. Its value must be the fully qualified name of the class that implements the java.rmi.server.RMIServerSocketFactory interface, and the class must be available to the JBoss class loader. If this element is not specified the default VM server socket factory will be used.

Custominzation of the ContainerInvoker sockets entails sepecifying the classes that implement the java.rmi.server.RMIClientSocketFactory and java.rmi.server.RMIServerSocketFactory interfaces. Figure 11.27gives a sample container-invoker-conf element.

Figure 11.27. Sample container-invoker-conf Element


<container-invoker-conf>
  <Optimized>true</Optimized>
  <RMIObjectPort>4445</RMIObjectPort>
  <RMIClientSocketFactory>org.jboss.test.jrmp.ejb.CompressionClientSocketFactory</RMIClientSocketFactory>
  <RMIServerSocketFactory>org.jboss.test.jrmp.ejb.CompressionServerSocketFactory</RMIServerSocketFactory>
</container-invoker-conf>

CompressionSocket Example

The jbosstest cvs module contains a org.jboss.test.jrmp package in the src/main directory which contains tests of custom socket configuration. One example is the CompressionSocket example from the RMI custom socket tutorial. The org.jboss.test.jrmp.test.TestCustomSockets class access a stateless session bean using the compression custom sockets as well as a stateful session bean using the default JRMP socket factories. The ejb-jar.xml and jboss.xml deployment descriptors for the ejb jar are given in Figure 11.28and Figure 11.29 See the jbosstest module code for the complete details.

Figure 11.28. TestCustomSockets Example ejb-jar.xml Descriptor


<?xml version="1.0"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN"
    "http://java.sun.com/j2ee/dtds/ejb-jar_1_1.dtd">

<ejb-jar>
  <display-name>JRMP Custom Socket Tests</display-name>
  <enterprise-beans>

    <session>
      <description>A trival echo stateless session bean</description>
      <ejb-name>StatelessSession</ejb-name>
      <home>org.jboss.test.jrmp.interfaces.StatelessSessionHome</home>
      <remote>org.jboss.test.jrmp.interfaces.StatelessSession</remote>
      <ejb-class>org.jboss.test.jrmp.ejb.StatelessSessionBean</ejb-class>
      <session-type>Stateless</session-type>
      <transaction-type>Container</transaction-type>
    </session>

    <session>
      <description>A trival echo stateful session bean</description>
      <ejb-name>StatefulSession</ejb-name>
      <home>org.jboss.test.jrmp.interfaces.StatelessSessionHome</home>
      <remote>org.jboss.test.jrmp.interfaces.StatelessSession</remote>
      <ejb-class>org.jboss.test.jrmp.ejb.StatelessSessionBean</ejb-class>
      <session-type>Stateful</session-type>
      <transaction-type>Container</transaction-type>
    </session>

  </enterprise-beans>

</ejb-jar>

Figure 11.29. TestCustomSockets Example jboss.xml Descriptor


<?xml version="1.0"?>

<!-- The jboss.xml descriptor for the jrmp-gzip.jar ejb unit -->
<jboss>
    <container-configurations>
        <container-configuration>
            <container-name>Standard Stateless SessionBean</container-name>
            <!-- Override the container socket factories -->
            <container-invoker-conf>
                <Optimized>true</Optimized>
                <RMIObjectPort>4445</RMIObjectPort>
                <RMIClientSocketFactory>org.jboss.test.jrmp.ejb.CompressionClientSocketFactory</RMIClientSocketFactory>
                <RMIServerSocketFactory>org.jboss.test.jrmp.ejb.CompressionServerSocketFactory</RMIServerSocketFactory>
            </container-invoker-conf>
        </container-configuration>
    </container-configurations>

    <enterprise-beans>
        <!-- This section is not really necessary since we are using the default container-name.
It is here to indicate that only the StatelessSession bean is using custom
socket factories.
-->
        <session>
            <ejb-name>StatelessSession</ejb-name>
            <configuration-name>Standard Stateless SessionBean</configuration-name>
        </session>
    </enterprise-beans>
</jboss>

Note that we specified an RMIObjectPort of 4445 rather than the default value of 4444 used by the default container configurations in the standardjboss.xml descriptor. This is necessary because JRMP RMI implementation keeps track of the exported object endpoints based on (port, host, ClientSocketFactory, ServerSocketFactory) rather than just (port, host). If we had used a port value of 4444 we would see an exception at deployment time indicating that port 4444 could not be bound because it was already in use. The reason is that the RMI layer would try to create two ServerSocket instances with the same port,host combination for the two different (ClientSocketFactory, ServerSocketFactory) combinations. If you don't have a reason to choose a fixed port the safest RMIObjectPort configuration to use it 0 which allows the system to bind any available port.