Showing posts with label jboss. Show all posts
Showing posts with label jboss. Show all posts

Wednesday, August 21, 2013

JBoss Remote EJB Invocation: An Unexpected Journey

Complexity sign6

The amount of complexity I'm willing to tolerate is proportional to the size of the problem being solved. There will come a point where the accumulated complexity of our existing systems is greater than the complexity of creating a new one.

- Ryan Dahl on Software

Es könnte alles so einfach sein, ist es aber nicht.

- Die Fantastischen Vier

 

Getting EJB Remoting to work in JBoss 7 was probably the most pitfall-ridden path I have travelled so far on my journeys through the swamp of frameworks…

Note: The example and discussion in this post is based on JBoss EAP 6.1.

It all started out well with a simple quick-start: ejb-remote.

But the pitfalls lured …

TL;DR: Finally I got an illustrative example running, which will be the base for the following discussion. The example can be found on my Github repo.

The EJB is simple: [Gist]

It's in the client where we find the pitfalls: [Gist]

 

Let's discuss the pitfalls:

Pitfall 1: Determining the JNDI-name for the EJB lookup

When you deploy the EJB into JBoss you get a nice output in the server-log:

[0m23:18:42,226 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-12) JNDI bindings for session bean named HelloWorldBean in deployment unit subdeployment "ejbremote-ejb.jar" of deployment "ejbremote-ear.ear" are as follows:
 
	java:global/ejbremote-ear/ejbremote-ejb/HelloWorldBean!net.jonasbandi.ejbremote.server.HelloWorld
	java:app/ejbremote-ejb/HelloWorldBean!net.jonasbandi.ejbremote.server.HelloWorld
	java:module/HelloWorldBean!net.jonasbandi.ejbremote.server.HelloWorld
	java:jboss/exported/ejbremote-ear/ejbremote-ejb/HelloWorldBean!net.jonasbandi.ejbremote.server.HelloWorld
	java:global/ejbremote-ear/ejbremote-ejb/HelloWorldBean
	java:app/ejbremote-ejb/HelloWorldBean
	java:module/HelloWorldBean

It looks easy … but actually none of those JNDI bindings work for remote lookup!

 

Pitfall 2: There are two approaches for accessing a remote EJB

You can use the "standard" JNDI lookup (which uses the "remote-naming project") or the the (proprietary) EJB Client API. Both approaches differ in the initialisation properties (key-value pairs) that have to be configured and in the JNDI lookup name that must be used for a given bean.

The EJB Client API is recommended. Loadbalancing, clustering and client interceptors are only available with the EJB Client API. Also it is performance optimised. [see here]

Pitfall 3: The initialisation properties are cryptic

I do not understand the following properties (except that they all have something to do with client, context and naming):

jndiProperties.put("jboss.naming.client.ejb.context", true);
ejbProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
ejbProperties.put("org.jboss.ejb.client.scoped.context", "true");

Yet you have to use the correct ones for the correct lookup approach, else it won't work…
There are also a lot of other properties floating around in different documentations, wikis, forums and JIRA issues … I did not find a authoritative documentation about them.

Pitfall 4: Use the correct runtime dependencies

Runtime dependencies are tricky. You can get you code compiling, but it will not work unless you have the correct runtime dependencies configure. Getting the EJB client API running, you need:

      <dependency>
           <groupId>org.jboss</groupId>
           <artifactId>jboss-ejb-client</artifactId>
           <scope>runtime</scope>
       </dependency>

Getting the "standard" JNDI lookup running (including JNDI tree traversal) you need:

       <dependency>
            <groupId>org.jboss</groupId>
            <artifactId>jboss-remote-naming</artifactId>
            <scope>runtime</scope>
        </dependency>

In both cases you need some more runtime dependencies which are listed in the client pom.xml of the example.

 

Pitfall 5: Error messages are mostly not helpful or even misleading

Example 1: If you configure the wrong version of the ejb-client dependency like:

       <dependency>
           <groupId>org.jboss</groupId>
           <artifactId>jboss-ejb-client</artifactId>
           <scope>runtime</scope>
           <version>1.0.5.Final</version>
       </dependency>

Then you get an exception that makes you beleave you have made a mistake somewhere in the security-configuration:

javax.ejb.EJBAccessException: JBAS014502: Invocation on method: [] is not allowed


Example 2: If you pass a number instead of a string for the port configuration like this:

ejbProperties.put("remote.connection.1.port", 4447);

Then you get the same exception as when you use a wrong JNDI lookup name:

java.lang.IllegalStateException: EJBCLIENT000025: No EJB receiver available for handling [appName:ejbremote-ear, moduleName:ejbremote-ejb, distinctName:]

 

Pitfall 6: Client interceptor registration does not work with scoped context

Since JBoss 7.2 you can use scoped contexts and then you would not need do programmatic initialisation of the EJBClientContext.
So if you do this:

ejbProperties.put("org.jboss.ejb.client.scoped.context", "true");

… then you do not need to do the following:

final EJBClientConfiguration ejbClientConfiguration = new PropertiesBasedEJBClientConfiguration(ejbProperties);
final ConfigBasedEJBClientContextSelector selector = new ConfigBasedEJBClientContextSelector(ejbClientConfiguration);
EJBClientContext.setSelector(selector);

However if you do the above, then the programmatic registration of a client interceptor does not work any more. I suspect this is a bug?

In a later post I plan to elaborate on how to get the above example running with a custom login module and with a cluster setup… be prepared for more complexity and more magic strings!

Monday, September 10, 2012

QuickTip: Programmatic MBean access under JBoss

I have been struggeling a bit with the programmatic access of MBeans under JBoss. This is my current conclusion.
With JBoss 5 there are two methods for accessing MBeans:
  • By JNDI-lookup of the RMIAdaptor. With this method you need the JBoss client libraries (the jars in your $JBOSS_HOME/client) on the classpath since the RMIAdaptor is a type that is provided by JBoss.
  • By pure JMX. You don't need the JBoss client libraries your class path here. 

The following snipped shows both methods:

With JBoss 7 the way to access MBeans changed quite a bit: The tricky thing here is, that you need the JBoss client libraries (the jars in $JBOSS_HOME/bin/client) on your classpath even though you don't explicitly import types provided by JBoss.

If the client libraries are missing, you get the following exception: java.net.MalformedURLException: Unsupported protocol: remoting-jmx

As far as I could figure, this is the only way to access MBeans under JBoss 7.
Related Posts Plugin for WordPress, Blogger...