Chapter 10. Transports

This chapter explains how remote clients communicate with the EJB 3 container and describes how to set up alternate transports. types. The transport used by JBoss EJB 3 is based on JBoss Remoting, see the JBoss Remoting documentation for more in-depth examples.

10.1. Default transport

By default JBoss EJB 3 uses a socket based invoker layer on port 3878. This is set up in $JBOSS_HOME/server/<your-conf>/deploy/ejb3.deployer/META-INF/jboss-service.xml

This is the out-of-the-box setup:

   <mbean code="org.jboss.remoting.transport.Connector"
          xmbean-dd="org/jboss/remoting/transport/Connector.xml"
          name="jboss.remoting:type=Connector,name=DefaultEjb3Connector,handler=ejb3">
      <depends>jboss.aop:service=AspectDeployer</depends>
      <attribute name="InvokerLocator">socket://0.0.0.0:3873</attribute>
      <attribute name="Configuration">
         <handlers>
            <handler subsystem="AOP">org.jboss.aspects.remoting.AOPRemotingInvocationHandler</handler>
         </handlers>
      </attribute>
   </mbean>
         

The URL given by the InvokerLocator atribute tells JBoss Remoting which protocol to use, and which IP address and port to listen on. In this case we are using 0.0.0.0 as the IP address, meaning we listen on all NIC's. The socket:// protocol means we listen on a plain socket, and the port we use is 3873

The Configuration attribute specifies that requests coming in via this socket should be handed over to the AOP subsystem, implemented by org.jboss.aspects.remoting.AOPRemotingInvocationHandler which is the entry point to the EJB 3 container.

10.2. Securing the transport

In some cases you may wish to use SSL as the protocol. In order to do this you first need to generate a keystore.

10.2.1. Generating the keystore and truststore

For SSL to work we need to create a public/private key pair, which will be stored in a keystore. Generate this using the genkey command that comes with the JDK.

   $cd $JBOSS_HOME/server/default/conf/
   $ keytool -genkey -alias ejb3-ssl -keypass opensource -keystore localhost.keystore
   Enter keystore password:  opensource
   What is your first and last name?
     [Unknown]:
   What is the name of your organizational unit?
     [Unknown]:
   What is the name of your organization?
     [Unknown]:
   What is the name of your City or Locality?
     [Unknown]:
   What is the name of your State or Province?
     [Unknown]:
   What is the two-letter country code for this unit?
     [Unknown]:
   Is CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
     [no]:  yes
         

alias is the name ("ejb2-ssl") of the key pair within the keystore. keypass is the password ("opensource") for the keystore, and keystore specifies the location ("localhost.keystore") of the keystore to create/add to.

Since we have not signed our certificate through any certification authoritiy, we also need to create a truststore for the client, explicitly saying that we trust the certificate we just created. The first step is to export the certificate using the JDK keytool:

   $ keytool -export -alias ejb3-ssl -file mycert.cer -keystore localhost.keystore
   Enter keystore password:  opensource
   Certificate stored in file <mycert.cer>

         

Then we need to create the truststore if it does not exist and import the certificate into the trueststore:

   $ keytool -import -alias ejb3-ssl -file mycert.cer -keystore localhost.truststore
   Enter keystore password:  opensource
   Owner: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
   Issuer: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
   Serial number: 43bff927
   Valid from: Sat Jan 07 18:23:51 CET 2006 until: Fri Apr 07 19:23:51 CEST 2006
   Certificate fingerprints:
            MD5:  CF:DC:71:A8:F4:EA:8F:5A:E9:94:E3:E6:5B:A9:C8:F3
            SHA1: 0E:AD:F3:D6:41:5E:F6:84:9A:D1:54:3D:DE:A9:B2:01:28:F6:7C:26
   Trust this certificate? [no]:  yes
   Certificate was added to keystore 

10.2.2. Setting up the SSL transport

The simplest way to define an SSL transport is to define a new Remoting connector using the sslsocket protocol as follows. This transport will listen on port 3843:

   <mbean code="org.jboss.remoting.transport.Connector"
      xmbean-dd="org/jboss/remoting/transport/Connector.xml"
      name="jboss.remoting:type=Connector,transport=socket3843,handler=ejb3">
      <depends>jboss.aop:service=AspectDeployer</depends>
      <attribute name="InvokerLocator">sslsocket://0.0.0.0:3843</attribute>
      <attribute name="Configuration">
         <handlers>
            <handler subsystem="AOP">org.jboss.aspects.remoting.AOPRemotingInvocationHandler</handler>
         </handlers>
      </attribute>
   </mbean>
         

We need to tell JBoss Remoting where to find the keystore to be used for SSl and its password. This is done using the javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword=opensource system properties when starting JBoss, as the following example shows:

    $cd $JBOSS_HOME/bin
    $ run -Djavax.net.ssl.keyStore=../server/default/conf/localhost.keystore -Djavax.net.ssl.keyStorePassword=opensource
         

10.2.3. Configuring your beans to use the SSL transport

By default all the beans will use the default connector on socket://0.0.0.0:3873. By using the @org.jboss.annotation.ejb.RemoteBinding annotation we can have the bean invokable via SSL.

   @RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:3843", jndiBinding="StatefulSSL"),
   @Remote(BusinessInterface.class)
   public class StatefulBean implements BusinessInterface
   {
      ...
   }

         

This bean will be bound under the JNDI name StatefulSSL and the proxy implementing the remote interface returned to the client will communicate with the server via SSL.

You can also enable different types of communication for your beans

   @RemoteBindings({
      @RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:3843", jndiBinding="StatefulSSL"),
      @RemoteBinding(jndiBinding="StatefulNormal")
   })
   @Remote(BusinessInterface.class)
   public class StatefulBean implements BusinessInterface
   {
      ...
   }
         

Now if you look up StatefulNormal the returned proxy implementing the remote interface will communicate with the server via the normal unencrypted socket protocol, and if we look up StatefulSSL the returned proxy implementing the remote interface will communicate with the server via SSL.

10.2.4. Setting up the client to use the truststore

If not using a certificate signed by a certificate authorization authority, you need to point the client to the truststore using the javax.net.ssl.trustStore system property and specify the password using the javax.net.ssl.trustStorePassword system property:

            java -Djavax.net.ssl.trustStore=${resources}/test/ssl/localhost.truststore -Djavax.net.ssl.trustStorePassword=opensource com.acme.RunClient