3 Replies Latest reply on Jul 7, 2015 9:55 PM by tungtd

    Remote EJB call (JBoss AS7/EAP6 )

    dako_t

      Hi all,

       

      I have deployed an EJB jar on JBoss AS 7/EAP6 and wants to call the EJB from my spring application.

      I use the SimpleRemoteStatelessSessionProxyFactoryBean and it works for EJB's which are deployed an localhost.

       

      Thats my sample config:

       

              <bean id="converterConfigEJB" class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean">
                      <property name="jndiTemplate" ref="remoteEjbJndiTemplate"/>
              <property name="jndiName"
                  value="ejb:/Converter-EJBs/ConverterConfigService!de.mycompany.converter.ejb.interfaces.ConverterConfigServiceRemote" />
              <property name="businessInterface" value="de.mycompany.converter.ejb.interfaces.ConverterConfigServiceRemote" />
          </bean>
      

       

      How can I configure that the remote EJB is deployed on a remote host?

      I think with JNDI properties but if I look into the EJB client samples from Red Hat they are using a "jboss-ejb-client.properties" file with properties like this: "remote.connection.default.host".

       

      I've tried to use this properties with a "org.springframework.jndi.JndiTemplate":

       

           <bean id="remoteEjbJndiTemplate" class="org.springframework.jndi.JndiTemplate">
              <property name="environment">
                  <props>
                      <prop key="remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED">false</prop>
                      <prop key="remote.connection.default.host">localhost</prop>
                      <prop key="remote.connection.default.port">4447</prop>
                      <prop key="remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS">default</prop>
                  </props>
              </property>
          </bean>
      

       

      But it doesnt matter which values I set for host or port properties my example works. I think this jboss properties will be ignored. What are the correct properties for host and port?

        • 1. Re: Remote EJB call (JBoss AS7/EAP6 )
          dlmiles

          I can probably assist on this, as I have front end webservers (using plain Tomcat 7.x and Spring) connecting to a backend JBoss EAP 6.1 (that happens to also use Spring).  This is all using JBoss's enchanced EJB remoting.

           

          I do not fully understand how I got it to work it was a lot of trial and error.

           

          Some things I learned:

           

          * Do not have a file called jndi.properties in your web-app.  This will interfere with Tomcat's own JNDI mechanism, such as for looking up JDBC connections.  That needs to continue to keep working, the problem is that if you change the web-app environments config to use the alternative JNDI registry and services.  Good if you are already running inside AS but not good for me, when I wanted Tomcat's regular and local JNDI to work, but have a few EJB remote beans to access another host on the network.

           

          * Next I ensure I added dependencies for org.jboss.ejb.* into my WAR project (the client access code is an enchanced EJB remoting library that supports JBoss value added additional features, this is my understanding anyway)

            I am a maven user so this means I added (you shall need to resolve to the best versions to use for your particular version of JBoss AS / EAP / Wildfly:

          {code:xml}

                      <dependency>

                          <groupId>org.jboss</groupId>

                          <artifactId>jboss-ejb-client</artifactId>

                      </dependency>

                      <dependency>

                          <groupId>org.jboss</groupId>

                          <artifactId>jboss-remote-naming</artifactId>

                      </dependency>

                      <dependency>

                          <groupId>org.jboss.marshalling</groupId>

                          <artifactId>jboss-marshalling-river</artifactId>

                      </dependency>

                      <dependency>

                          <groupId>org.jboss.sasl</groupId>

                          <artifactId>jboss-sasl</artifactId>

                      </dependency>

                      <dependency>

                          <groupId>org.jboss.xnio</groupId>

                          <artifactId>xnio-nio</artifactId>

                      </dependency>

          {code}

           

          * When setting up the JndiTemplate I chose to stay away from a bean called "jndiTemplate" as I think this maybe a magic name used by default (if it exists) that also affected things badly.  So I configured with:

          {code:xml}

              <bean id="jbossJndiProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">

                  <property name="location" value="classpath:/my-jndi.properties"/>

              </bean>

          {code}

           

          * The file /my-jndi.properties is a WAR toplevel level property file in the classpath, this means it src/main/resources/my-jndi.properties (in the Maven WAR project) or WEB-INF/classes/my-jndi.properties in the packaged WAR.

          * In this file I have a single active line: *java.naming.factory.url.pkgs=org.jboss.ejb.client.naming* (it is my limited understanding, this overrides the default client implementation of the JRE to instead use the JBoss enchanced EJB client not the JRE bundled one,

            it is the JBoss enchancements that understand the configuration variables you are trying to set in the JNDI context environment.)

           

          * I chose to configure in Spring XML each use of a remote EJB with xmlns:jee="http://www.springframework.org/schema/jee" and xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd",

          * This means I used {code:xml}<jee:remote-slsb .../>{code} modify this example to suit.  My EJB was inside an EAR all using Maven to manage the project.  The jndi-name is the fully qualified one you shall find emitted by JBoss AS / EAP / WildFly when it deploys the EJB with server logging enabled.

            The use of ${ejbReference.earVersion} is some matter concerning a difference between testing and production environments in how the item was named/labeled/versioned.

          {code:xml}

              <jee:remote-slsb id="myStateless" jndi-name="ejb:com.domain.ear${ejbReference.earVersion}/com-domain-ejb-0.0.1-SNAPSHOT/MyStatelessImpl!com.domain.ejb.MyStateless"

                  business-interface="com.domain.ejb.MyStateless"

                  cache-home="true" lookup-home-on-startup="true" refresh-home-on-connect-failure="true" environment-ref="jbossJndiProperties">

              </jee:remote-slsb>

          {code}

           

          * Now we configure the JBoss enchanced EJB client part in the WAR property file jboss-ejb-client.properties (this file is magically looked for by the JBoss code).

             Between devel (your local system), test (your testing platform) and live (the production environment) you change the 'remote.connections' and 'remote.clusters' lines,

             you should ideally remove all unused/unrequired credentials from the file that are not relevant to the environment in which you deploy the config, as-is makes for a good example.

            My understanding is that port 4447 is the enchanced JBoss EJB remoting socket (which is not the standard port number for EJB)

            In this file the specialized properties you are trying to configure can be setup (only JBoss enchanced EJB client codes look at this) :

          {code}

          #

          #   Not sure which things in this file are actually used.

          ##

          endpoint.name=client-endpoint

          #endpoint.create.options=

           

          remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false

           

          #remote.connections=devel

          remote.connections=test

          #remote.connections=live

           

          remote.connection.devel.host=127.0.0.1

          remote.connection.devel.port=4447

          remote.connection.devel.username=myusername

          remote.connection.devel.password=myPaSsWoRD123456

           

          remote.connection.test.host=10.123.52.87

          remote.connection.test.port=4447

          remote.connection.test.username=myusername

          remote.connection.test.password=myPaSsWoRD334455

          remote.connection.test.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=true

          remote.connection.test.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS=JBOSS-LOCAL-USER

           

          remote.connection.live.host=10.212.70.125

          remote.connection.live.port=4447

          remote.connection.live.username=myusername

          remote.connection.live.password=myPaSsWoRD567890

          remote.connection.live.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=true

          remote.connection.live.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS=JBOSS-LOCAL-USER

           

          remote.clusters=ejb

           

          remote.cluster.ejb.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=true

          remote.cluster.ejb.username=myusername

          remote.cluster.ejb.password=myPaSsWoRD999999

           

          #remote.connection.default.host=localhost

          #remote.connection.default.port = 4447

          #remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

           

          # Does this section do anything for us ?

          jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=true

          jboss.naming.client.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS=JBOSS-LOCAL-USER

          jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT=false

           

          #jboss.naming.client.connect.options=

          {code}

           

           

          * On the JBoss EJB server (AS/EAP/WildFly) you need to create the account that is used with username/password credentials as above.

            This looks to have resulted in the file standalone/configuration/application-users.properties gaining an entry for the username/password-hashed.

            Maybe the JBoss EJB / server configuration documentation is helpful on this point.  Running the script $JBOSS_HOME/bin/add-user.* in the context of a non-admin application user.

           

          * You need to ensure you have an appropiate profile for EJB and the subsystem enabled in the server configuration such as standalone/configuration/standalone-full.xml

            I did experiment with the <management> and <security-realms> part of the config but it seems this was not needed in the final version that worked for me.

           

          * Ensure there is TCP level network access from the EJB client host to the EJB server host on port 4447.  This maybe blocked due to firewal issues.

            Maybe the JBoss EJB / server configuration documentation is helpful on this point.

           

           

           

          I would appreciate any indepth knowledge correcting any of my above claims.  As I reiterate my configuration works by chance not by engineering, while there is documentation around the process of understanding what happens (the sequence of events) when an EJB client is library

          invokes on the server was better understood with the debugging and stepping into code!  This is not good.

           

          Also documentation on what all the defaults are,

          How to turn on full debugging mode (hint make this easy!) so all configured options are dumped (as both client and server ends) during a remoting diagnostic session, if its possible to simplfy the steps by understanding the defaults better.

           

          If would also be very good if there was a single Maven dependency maybe type=pom that was the collection of JARs needed for various JBoss EJB client profiles starting with 'all features with all the trimmings' down to 'basic remote EJB with SSL'.  So save me having to track down what

          is compatible with that over multiple JARs needed on a foreign (non JBoss product) the client.

           

           

          Please reply to thread if these instruction were exactly enough to get things working for you.  Bear in mind that some steps maybe simplified when the EJB client/server does not leave the same JVM/host, but this is a good example of a realisitic worst case scenario, when you are trying

          to make a foreign (non-JBoss) client application use JBoss AS.

          1 of 1 people found this helpful
          • 2. Re: Remote EJB call (JBoss AS7/EAP6 )
            dako_t

            Hi Darryl,

             

            thank you for your explanation. I will check this out within the next days.

            • 3. Re: Remote EJB call (JBoss AS7/EAP6 )
              tungtd

              Thank you Darryls!!! You save my days...

              I struggled with invoking remote EJB from a Spring client. I looked for a very simple example but nothing came out. Eventually I found your reply and add this line to the properties file:

              java.naming.factory.url.pkgs=org.jboss.ejb.client.naming
              
              


              Without this, the Spring container kept complaining:

               

              Bean creation exception on FactoryBean type check: org.springframework.beans.factory.BeanCreationException: 
              Error creating bean with name 'clientService': Invocation of init method failed; 
              nested exception is javax.naming.NoInitialContextException: Need to specify class name in environment or system property, 
              or as an applet parameter, or in an application resource file:  java.naming.factory.initial

               

               

              Just like you mentioned "it is my limited understanding, this overrides the default client implementation of the JRE to instead use the JBoss enchanced EJB client not the JRE bundled one"

              => This really works.

              Thank Darryl!