【问题标题】:Ejb 3 lookup not working in Jboss AS 6Ejb 3 查找在 Jboss AS 6 中不起作用
【发布时间】:2013-03-05 07:52:30
【问题描述】:

我已将我的应用程序从 Glassfish 2.2.1 迁移到 JBoss AS 6。

以前我有一个用于查找 ejb 的通用类,下面是代码:

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;
    }

}

上述类适用于 glassfish 中的查找。 但是在将代码迁移到 JBoss AS 6 之后。我总是得到 javax.naming.NameNotFoundException

下面是我的 ejb 类之一。

 @Remote
    public interface OperationPerformed {

        public void addRandomNo(String randomNos);

    }

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

        public void addRandomNo(String randomNos) {
        }

    }

如果我给出 jboss 在部署我的应用程序期间创建的完整 jndi 名称,那么我可以轻松查找相同的名称。但我想要通用代码进行查找。

以下是我为查找 bean 调用的代码:

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

如果我做错了什么,请提出建议。

【问题讨论】:

  • 我看到你使用@Remote,代码是在服务器还是客户端进行查找?
  • 代码仅在服务器上进行查找。
  • 那你为什么要使用@Remote?您是否尝试过简单地使用 @EJB 进行注入而不是 JNDI?
  • 我明白你的意思。但是通过使用@Local,我也遇到了同样的问题。通过简单地使用 {@EJB} 像:{@EJB OperationPerformed operationPerformed;} 我得到空值。似乎无法解决这个问题。
  • Glassfish 和 JBoss 的 JNDI 名称可能不同,这可能是 JNDI 代码不起作用的原因。然而,@EJB 应该将这一切抽象出来。您使用@EJB 的地方是EJB 本身吗?你使用@EJB的地方和OperationPerformedImpl 在同一个EAR/WAR中?

标签: jboss glassfish ejb-3.0 jboss6.x


【解决方案1】:

我认为你可以将类名转换为jndi名并正常查找

【讨论】:

  • 类名到 jndi 名称,即在服务器日志中,我得到的 jndi 名称为 java:global/gameplayfun/gameplayfun-ejb-1.0-SNAPSHOT/OperationPerformedImpl!com‌​.gameplay.logic.OperationPerformed 如果我按此名称查找,我可以轻松查找。但我想要一些通用代码。
【解决方案2】:

一些建议:

  1. 在接口和实现上同时使用@Remote 注解是很不寻常的。从您的无状态 bean 中删除此注释,它是多余的。
  2. 我同意其他海报:
    • 不要使用远程接口进行本地查找和注入,创建另一个接口并用@Local 标记它。
    • 当涉及到 JVM 本地操作时,@EJB 注入与手动 JNDI 查找相比要优越得多(请参阅对 http://stackoverflow.com/questions/12681436/ejb-annotation-vs-jndi-lookup 的回复以及关于 SO 的类似问题) .

总而言之:

创建OperationPerformedLocal.java

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

修改你的 SLSB:

@Stateless
public class OperationPerformedImpl implements OperationPerformedLocal, OperationPerformed {

    public void addRandomNo(String randomNos) {
    }
}

并尽可能使用注入而不是 jndi 查找:

@EJB
private OperationPerformedLocal operationPerformed;

如果是 WAR 模块,一些 CDI @Injection 魔法应该可以工作,但我还没有任何实际经验。


现在,如果您坚持使用纯 JNDI 查找并希望它们尽可能通用,我想出了这个解决方案:

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;
    }
}

你可以这样使用它:

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

我知道这很难看,我有点不好意思发布它。

它不可移植,迫使您了解接口和实现类,并且“/local”部分是硬编码的,使其更加丑陋::sigh::.

将 EJB-JAR(s) 放入 EAR 会使事情变得更复杂,jndi-name 将以 EAR 名称为前缀:

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

此外,如果 SLSB 更改名称,即@Stateless(name="someNewName"),它可能会中断。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多