0

I have migrated my app from Glassfish 2.2.1 to JBoss AS 6.

Previously i have a generic class for lookup the ejbs, Below is the code:

public class BeanUtil {
    private static InitialContext ctx; 
    public static <T> T create(Class<T> type){
        try {
            ctx = new InitialContext();
            return (T)ctx.lookup(type.getName());
        } catch (NamingException e) {
            e.printStackTrace();
        }
        return null;
    }

}

The above class works fine for lookup in glassfish. But after migrating the code to JBoss AS 6. I always get javax.naming.NameNotFoundException

Below is one of my ejb class.

 @Remote
    public interface OperationPerformed {

        public void addRandomNo(String randomNos);

    }

    @Stateless
    @Remote(OperationPerformed.class)
    public class OperationPerformedImpl implements OperationPerformed {

        public void addRandomNo(String randomNos) {
        }

    }

If i give the complete jndi name which jboss made during deployment of my app, then i can easily lookup the same. But i want generic code for lookup.

Below is the code which i invoke for lookup a bean:

OperationPerformed operationPerformed = BeanUtil.create(OperationPerformed.class);

Please suggest if i am doing something wrong.

sorabh solanki
  • 480
  • 1
  • 7
  • 18
  • I see you use `@Remote`, is the code doing the look up on the server or the client? – Philippe Marschall Mar 05 '13 at 08:01
  • code is doing look up on the server only. – sorabh solanki Mar 05 '13 at 08:08
  • In that case why do you use `@Remote`? Have you tried to simply use `@EJB` for injection instead of JNDI? – Philippe Marschall Mar 05 '13 at 08:16
  • I got your point. But by using @Local also i am getting the same issue. By using simply {@EJB} like: {@EJB OperationPerformed operationPerformed;} i am getting null. It seems it is unable to resolve this. – sorabh solanki Mar 05 '13 at 08:27
  • The JNDI names for Glassfish and JBoss are likely different that's likely why the JNDI code doesn't work. However that `@EJB` should abstract all this away. The place where you use `@EJB` is an EJB itself? The place where you use `@EJB` is in the same EAR/WAR as `OperationPerformedImpl `? – Philippe Marschall Mar 05 '13 at 08:37
  • The place where i am putting {@ejb} is not an ejb class. It's a class in a war file reside under my ear. – sorabh solanki Mar 05 '13 at 09:13
  • `@EJB` only works in EJBs. JBoss AS 6 / EJB 3.1 uses standardized JNDI names. Check out the [documentation](https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI) (also applies to AS 6) on how they are constructed. – Philippe Marschall Mar 05 '13 at 10:29

2 Answers2

0

I think you can convert class name to jndi name and look it up normally

hyo1411
  • 81
  • 2
  • Class name to jndi name i.e in server log i am getting the jndi name as java:global/gameplayfun/gameplayfun-ejb-1.0-SNAPSHOT/OperationPerformedImpl!com‌​.gameplay.logic.OperationPerformed if i lookup by this name, i can easily lookup. But i want some generic code. – sorabh solanki Mar 05 '13 at 08:19
0

Some suggestions:

  1. It's quite unusual to use @Remote annotation on interface and implementation at the same time. Remove this annotation from your stateless bean, it's redundant.
  2. I agree with other posters:
    • don't use remote interface for local lookups and injections, create another interface and mark it with @Local.
    • when it comes to JVM-local operations @EJB injection is vastly supperior comparing to manual JNDI lookup (see responses to http://stackoverflow.com/questions/12681436/ejb-annotation-vs-jndi-lookup and similar questions on SO).

To sum it all:

create OperationPerformedLocal.java :

@Local
public interface OperationPerformedLocal {
    public void addRandomNo(String randomNos);
}

modify your SLSB:

@Stateless
public class OperationPerformedImpl implements OperationPerformedLocal, OperationPerformed {

    public void addRandomNo(String randomNos) {
    }
}

and use injection rather than jndi lookup whenever possible:

@EJB
private OperationPerformedLocal operationPerformed;

In case of WAR modules some CDI @Injection magic should work, but I haven't got any real experience with it yet.


Now, if you insist on using plain JNDI lookups and want them to be as generic as possible, I came up with this solution:

public class BeanUtil {
    private static InitialContext ctx;
    public static <T, C> T create(Class<C> implType, Class<T> interfaceType) {
        try {
            ctx = new InitialContext();

            return (T)ctx.lookup(implType.getSimpleName()+"/local");
        } catch (NamingException e) {
            e.printStackTrace();
        }
        return null;
    }
}

you can use it this way:

try {
    OperationPerformedLocal operationPerformed =
        BeanUtil.create(OperationPerformedImpl.class, OperationPerformedLocal.class);
    operationPerformed.addRandomNo("123");
} catch (Exception e) {
    e.printStackTrace();
}

It's ugly I know, I'm kind of embarassed posting it.

It's not portable, forces you to know interface and implementation classes and "/local" part is hardcoded making it even more ugly ::sigh::.

Placing EJB-JAR(s) into EAR can complicate things a little bit further, jndi-name will be prefixed with EAR name:

return (T)ctx.lookup("earName/" + implType.getSimpleName() + "/local");

Moreover, it'll probably break if SLSB has changed name i.e. @Stateless(name="someNewName").

Paweł Wyrwiński
  • 1,393
  • 9
  • 13