2 Replies Latest reply on Sep 3, 2009 9:14 AM by eminil

    SSL EJB 3.0 invocation

    paul_da_programmer

      Environment: JBoss 4.0.5.GA, Sun JDK jdk1.5.0_11

      C:\Paul\Projects\SSL-EJB\bin>run.bat -c ejb-server
      ===============================================================================
      
       JBoss Bootstrap Environment
      
       JBOSS_HOME: C:\Paul\Projects\SSL-EJB\bin\\..
      
       JAVA: C:\Program Files\Java\jdk1.5.0_11\bin\java
      
       JAVA_OPTS: -Dprogram.name=run.bat -server -Xms128m -Xmx512m -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.ser
      ver.gcInterval=3600000 -Djavax.net.ssl.keyStore=C:/Paul/Projects/SSL-EJB/server/chap8.keystore -Djavax.net.ssl.keyStore
      Password=rmi+ssl -Djava.security.debug=access,failure
      
       CLASSPATH: C:\Program Files\Java\jdk1.5.0_11\lib\tools.jar;C:\Paul\Projects\SSL-EJB\bin\\run.jar
      
      ===============================================================================
      



      I've tried in vain to get SSL invocation of EJB 3.0 session beans working.
      I've successfully followed the guide located here:
      http://docs.jboss.org/jbossas/jboss4guide/r3/html/ch8.chapter.html#d0e20905
      and gotten their EJB 2.x example working both from an J2SE example and another JBoss server as clients.

      I cannot get the exact same example working when updating the SLSB to EJB3.0
      Here are my changes:
      The EJB interface
      package org.jboss.chap8.ex4;
      
      /**
       *
       * @author Scott.Stark@jboss.org
       * @version $Revision: 1.1 $
       */
      public interface Echo
      {
       public String echo(String arg);
      }
      


      The EJB impl
      package org.jboss.chap8.ex4;
      
      import static javax.ejb.TransactionAttributeType.REQUIRED;
      import static javax.ejb.TransactionAttributeType.SUPPORTS;
      import static javax.ejb.TransactionManagementType.CONTAINER;
      
      import java.util.List;
      
      import javax.annotation.security.PermitAll;
      import javax.ejb.Local;
      import javax.ejb.Remote;
      import javax.ejb.TransactionManagement;
      import javax.persistence.EntityManager;
      import javax.persistence.NoResultException;
      import javax.persistence.PersistenceContext;
      
      import org.apache.log4j.Logger;
      import org.jboss.annotation.ejb.LocalBinding;
      import org.jboss.annotation.ejb.RemoteBinding;
      
      @javax.ejb.Stateless
      @Local( {Echo.class})
      @LocalBinding(jndiBinding = "local/EchoBean4")
      @Remote( {Echo.class})
      @RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:3873", jndiBinding="EchoBean4")
      @TransactionManagement(CONTAINER)
      @PermitAll
      public class EchoBean implements Echo
      {
       private static final Logger LOG = Logger.getLogger(EchoBean.class);
      
       public String echo(String arg)
       {
       LOG.debug("echo, arg="+arg);
       return arg;
       }
      }
      

      The Client
      package org.jboss.chap8.ex4;
      
      import java.rmi.RemoteException;
      import java.security.Security;
      import javax.naming.InitialContext;
      
      import org.apache.log4j.BasicConfigurator;
      import org.apache.log4j.Category;
      import org.apache.log4j.Priority;
      
      import org.jboss.logging.XLevel;
      import java.util.Properties;
      import javax.naming.Context;
      
      
      /**
       *
       * @author Scott.Stark@jboss.org
       * @version $Revision: 1.1 $
       */
      public class ExClient
      {
       public static void main(String args[]) throws Exception
       {
       // Install the Sun JSSE provider since we may not have JSSE installed
       Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
       // Configure log4j
       BasicConfigurator.configure();
       Category root = Category.getRoot();
       root.setLevel(XLevel.TRACE);
       Context iniCtx = new InitialContext();
       Object ref = iniCtx.lookup("EchoBean4");
       Echo echo = (Echo) ref;
       System.out.println("Created Echo");
       System.out.println("Created Echo");
       System.out.println("Echo.echo()#1 = "+echo.echo("This is call 1"));
       }
      }
      

      I also removed EchoHome.java and ejb-jar.xml which are superfluous for EJB 3.0.



      I get the following log on the server:
      2007-09-06 15:02:09,949 DEBUG [org.jboss.ejb3.Ejb3Module] Started jboss.j2ee:service=EJB3,module=chap8-ex4.jar
      2007-09-06 15:02:09,949 DEBUG [org.jboss.system.ServiceController] Starting dependent components for: jboss.j2ee:service=EJB3,module=chap8-ex4.jar dependent components: []
      2007-09-06 15:02:09,949 INFO [org.jboss.ejb3.EJB3Deployer] Deployed: file:/C:/Paul/Projects/SSL-EJB/server/ejb-server/deploy/chap8-ex4.jar
      2007-09-06 15:02:09,949 DEBUG [org.jboss.deployment.MainDeployer] End deployment start on package: chap8-ex4.jar
      2007-09-06 15:02:09,949 DEBUG [org.jboss.deployment.MainDeployer] Deployed package: file:/C:/Paul/Projects/SSL-EJB/server/ejb-server/deploy/chap8-ex4.jar
      2007-09-06 15:02:12,100 ERROR [org.jboss.remoting.transport.socket.SocketServerInvoker] Failed to accept socket connection
      java.lang.reflect.InvocationTargetException
       at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
       at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
       at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
       at java.lang.reflect.Constructor.newInstance(Constructor.java:494)
       at org.jboss.remoting.transport.socket.ServerThread.createServerSocket(ServerThread.java:184)
       at org.jboss.remoting.transport.socket.ServerThread.<init>(ServerThread.java:86)
       at org.jboss.remoting.transport.socket.SocketServerInvoker.processInvocation(SocketServerInvoker.java:426)
       at org.jboss.remoting.transport.socket.SocketServerInvoker.run(SocketServerInvoker.java:388)
       at java.lang.Thread.run(Thread.java:595)
      Caused by: java.io.StreamCorruptedException: invalid stream header
       at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:764)
       at java.io.ObjectInputStream.<init>(ObjectInputStream.java:277)
       at org.jboss.remoting.loading.ObjectInputStreamWithClassLoader.<init>(ObjectInputStreamWithClassLoader.java:73)
       at org.jboss.remoting.serialization.impl.java.JavaSerializationManager.createInput(JavaSerializationManager.java:52)
       at org.jboss.remoting.transport.socket.ServerSocketWrapper.createInputStream(ServerSocketWrapper.java:56)
       at org.jboss.remoting.transport.socket.ClientSocketWrapper.createStreams(ClientSocketWrapper.java:76)
       at org.jboss.remoting.transport.socket.ClientSocketWrapper.<init>(ClientSocketWrapper.java:54)
       at org.jboss.remoting.transport.socket.ServerSocketWrapper.<init>(ServerSocketWrapper.java:50)
       ... 9 more
      
      

      and the client hangs with this message
      run-example4:
       [copy] Copying 1 file to C:\Paul\Projects\SSL-EJB\server\ejb-server\deploy
       [echo] Waiting for 5 seconds for deploy...
       [java] created Initial Context
       [java] about to lookup
       [java] after to lookup
       [java] retrieved reference to EchoBean4: jboss.j2ee:jar=chap8-ex4.jar,name=EchoBean,service=EJB3
       [java] cast completed
       [java] Created Echo
       [java] Created Echo
       [java] 0 [main] DEBUG org.jboss.security.SecurityAssociation - Using ThreadLocal: false
       [java] 16 [main] TRACE org.jboss.security.SecurityAssociation - getPrincipal, principal=null
       [java] 125 [main] DEBUG org.jboss.remoting.Client - invoke called, but our invoker is disconnected, discarding and
       fetching another fresh invoker for: InvokerLocator [sslsocket://162.86.118.144:3873/]
       [java] 125 [main] DEBUG org.jboss.remoting.transport.socket.ssl.SSLSocketClientInvoker - connect called for: org.j
      boss.remoting.transport.socket.ssl.SSLSocketClientInvoker@18fd984
       [java] 125 [main] TRACE org.jboss.remoting.transport.socket.ssl.SSLSocketClientInvoker - 1) invoking =>org.jboss.r
      emoting.InvocationRequest@91cee with parameter: [advisedMethod=public abstract java.lang.String org.jboss.chap8.ex4.Echo
      .echo(java.lang.String), unadvisedMethod=public abstract java.lang.String org.jboss.chap8.ex4.Echo.echo(java.lang.String
      ), metadata=[metaData={REMOTING={INVOKER_LOCATOR=[type=AS_ISvalue=InvokerLocator [sslsocket://162.86.118.144:3873/]], SU
      BSYSTEM=[type=AS_ISvalue=AOP]}, DISPATCHER={OID=[type=AS_ISvalue=jboss.j2ee:jar=chap8-ex4.jar,name=EchoBean,service=EJB3
      ]}}], targetObject=null, arguments=[Ljava.lang.Object;@4a63d8]
       [java] 156 [main] TRACE org.jboss.remoting.transport.socket.ssl.SSLSocketClientInvoker - Creating socket number 0
       [java] 499 [main] TRACE org.jboss.remoting.serialization.impl.java.JavaSerializationManager - Creating ObjectOutpu
      tStream
       [java] 499 [main] TRACE org.jboss.remoting.serialization.impl.java.JavaSerializationManager - Creating ObjectInput
      StreamWithClassLoader
      


      I've also tried
      @RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:14445", jndiBinding="EchoBean4")
      

      for the Bean implementation for which I get no log from the server and the client still hangs.

      Is this issue related to a bug in JBoss remoting as described here:
      http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3972519#3972519

      The solution described there is to 'upgrade to JBoss Remoting 2.0.0'. Can someone point me to a concise guide as to how to do this upgrade? Rebuilding JBoss is not going to be allowed ... I tried upping the lib/jboss-remoting.jar file and was met with failure.

      Any help will be greatly appreciated ... at least confirmation that this is a JBoss remoting problem would help.



        • 1. Re: SSL EJB 3.0 invocation
          paul_da_programmer

          Answering my own post...does that count as talking to yourself ?!?

          Ok, I've made a bit of progress with this.
          This post was of immense help:
          http://www.jboss.org/index.html?module=bb&op=viewtopic&t=74475
          By incorporating the suggested changes into deploy\ejb.deployer\META-INF\jboss-service.xml, SSL with EJB 3.0 now works.
          The only adjustment I needed to make was commenting out this
          <!--jboss.remoting:service=NetworkRegistry-->
          Additionally, I removed most of what is no longer needed from the chap8 example application. The jar that contains the EJB 3.0 app only contains
          META-INF/jboss.xml (more on this in a moment)
          and the Interface and implementation listed in the previous post.
          I start the jboss ssl server (the server hosting the SSL EJB 3.0 SLSB) with

          set JAVA_OPTS=%JAVA_OPTS% -Djavax.net.ssl.keyStore=C:/Paul/Projects/SSL-EJB/server/chap8.keystore -Djavax.net.ssl.keyStorePassword=rmi+ssl
          

          I start the jboss ssl client (the server hosting the SSL EJB 3.0 SLSB) with
          set JAVA_OPTS=%JAVA_OPTS% -Djavax.net.ssl.trustStore=C:/Paul/Projects/SSL-EJB/server/client.truststore -Djavax.net.ssl.trustStorePassword=rmi+ssl
          


          At this point everything's done as in functional.

          However, the issue that remained was externalizing the port configuration from the source code. It would be bad for a prod system to have the following in their EJB's
          @RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:3843", jndiBinding="EchoBean4")
          


          The way I externalized it is probably a kludge, but it works.
          (1) First off, I removed the @RemoteBindings annotation from the SLSB and externalized it into the jboss.xml.
          Here's the post that helped: http://www.jboss.org/index.html?module=bb&op=viewtopic&t=111559
          and here's my jboss.xml
          <?xml version="1.0"?>
          <jboss
           xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
           http://www.jboss.org/j2ee/schema/jboss_5_0.xsd"
           version="3.0">
           <enterprise-beans>
           <session>
           <ejb-name>EchoBean4</ejb-name>
           <remote-binding>
           <jndi-name>EchoBean4</jndi-name>
           <client-bind-url>3843</client-bind-url>
           </remote-binding>
           </session>
           </enterprise-beans>
          </jboss>
          


          (2) Then, since we're using the ServiceBindings plugin to configure our ports, I needed to modify the bindings specification for the standard EJB connector as a result of changes to deploy\ejb.deployer\META-INF\jboss-service.xml
          Here's the change to my bindings file:
           <!-- EJB3 Remoting Connector ejb3.deployer/META-INF/jboss-service.xml -->
          
           <service-config name="jboss.remoting:type=Connector,transport=socket3873,handler=ejb3"
           delegateClass="org.jboss.services.binding.AttributeMappingDelegate">
           <delegate-config>
           <attribute name="InvokerLocator">socket://${jboss.bind.address}:5973</attribute>
           </delegate-config>
           <binding port="5974"/>
           </service-config>
          

          This will allow runtime configuration of the standard EJB (non-ssl) port.
          However, the SSL port was still specified in jboss.xml as well as the deploy\ejb.deployer\META-INF\jboss-service.xml
          Due to my lack of experience with 'customizing' the service binding plugin AND the fact that the port had to be 'hardcoded' in the jboss.xml, I decided on another approach

          (3) We already use the SystemPropertiesService to set customization of our applications. Its explanation is out of the scope of this post, but to use it, add the following at the top of conf/jboss-service.xml
           <mbean code="org.jboss.varia.property.SystemPropertiesService"
           name="jboss:type=Service,name=SystemProperties">
           <!--
           | Load properties from each of the given comma seperated URLs
           -->
           <attribute name="URLList">
           ./conf/tap.properties
           </attribute>
           </mbean>
          

          I created a conf/tap.properties file with the following:
          ejb.ssl.port=5843
          ejb.ssl.url=sslsocket://0.0.0.0:5843
          

          And then I modified jboss.xml to use these system properties
          <?xml version="1.0"?>
          <jboss
           xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
           http://www.jboss.org/j2ee/schema/jboss_5_0.xsd"
           version="3.0">
           <enterprise-beans>
           <session>
           <ejb-name>EchoBean4</ejb-name>
           <remote-binding>
           <jndi-name>EchoBean4</jndi-name>
           <client-bind-url>${ejb.ssl.url}</client-bind-url>
           </remote-binding>
           </session>
           </enterprise-beans>
          </jboss>
          

          and I modified the deploy\ejb.deployer\META-INF\jboss-service.xml to use the url property:
           <mbean code="org.jboss.security.plugins.JaasSecurityDomain"
           name="jboss.security:service=JaasSecurityDomain,domain=SSLAdvanced">
           <!-- This must correlate with the java:/jaas/SSL above -->
           <constructor>
           <arg type="java.lang.String" value="SSLAdvanced"/>
           </constructor>
           <!-- The location of the keystore
           resource: loads from the classloaders conf/ is the first classloader -->
           <attribute name="KeyStoreURL">C:/Paul/Projects/SSL-EJB/server/chap8.keystore</attribute>
           <attribute name="KeyStorePass">rmi+ssl</attribute>
           </mbean>
          
           <!-- The Connector is the core component of the remoting server service. -->
           <!-- It binds the remoting invoker (transport protocol, callback configuration, -->
           <!-- data marshalling, etc.) with the invocation handlers. -->
           <mbean code="org.jboss.remoting.transport.Connector"
           xmbean-dd="org/jboss/remoting/transport/Connector.xml"
           name="jboss.remoting:type=Connector,transport=socket3843,handler=ejb3">
           display-name="Socket transport Connector">
          
           <attribute name="Configuration">
           <config>
           <invoker transport="sslsocket">
           <attribute name="dataType" isParam="true">invocation</attribute>
           <attribute name="marshaller" isParam="true">org.jboss.invocation.unified.marshall.InvocationMarshaller</attribute>
           <attribute name="unmarshaller" isParam="true">org.jboss.invocation.unified.marshall.InvocationUnMarshaller</attribute>
           <!-- The following is for setting the server socket factory. If want ssl support -->
           <!-- use a server socket factory that supports ssl. The only requirement is that -->
           <!-- the server socket factory value must be an ObjectName, meaning the -->
           <!-- server socket factory implementation must be a MBean and also -->
           <!-- MUST implement the org.jboss.remoting.security.ServerSocketFactoryMBean interface. -->
           <attribute name="serverSocketFactory">jboss.remoting:service=ServerSocketFactory,type=SecurityDomainAdvanced</attribute>
           <attribute name="serverBindAddress">${jboss.bind.address}</attribute>
           <attribute name="serverBindPort">${ejb.ssl.port}</attribute>
           </invoker>
           <handlers>
           <handler subsystem="AOP">org.jboss.aspects.remoting.AOPRemotingInvocationHandler</handler>
           </handlers>
           </config>
           </attribute>
           <depends>jboss.remoting:service=ServerSocketFactory,type=SecurityDomainAdvanced</depends>
           <!--<depends>jboss.remoting:service=NetworkRegistry</depends>-->
           <depends>jboss.aop:service=AspectDeployer</depends>
           </mbean>
          

          As I said, a little kludgy, but it works. So in summary:
          1. I got EJB 3.0 SLSB working using SSL
          2. I removed the keystore etc... from the deployed application.
          3. I completely externalized configuration of the port used to host the SSL socked from the deployed application itself. This is a major requirement.

          If anyone could assist with configuring the deploy\ejb.deployer\META-INF\jboss-service.xml using the service bindings manager AND somehow remove the necessity of specifying the port in the application's jboss.xml - that would be an improvement.





          • 2. Re: SSL EJB 3.0 invocation
            eminil

            I seem to get

            "javax.naming.NameNotFoundException: jaas not bound"

            Trying to deploy that...