为什么我不能通过JNDI使用远程接口访问我的EJB?

时间:2015-07-20 14:57:15

标签: java java-ee jndi wildfly-8

我遇到使用JNDI检索bean的问题。

我有两只耳朵:clientear和workerear。 Clientear包含clientejb和libejb Workerear包含workerejb和libejb

lib包含MyInterface workerejb包含bean和抽象类 clientejb包含执行查找的客户端代码。

我实现远程接口的bean

public class MyBean implements MyInterface

它的JNDI绑定是

java:global/jndinaming/MyBean!learning.jndinaming.MyInterface

没关系。

现在我希望它扩展一个Abstract类:

public abstract  class MyAbstractClass implements MyInterface
public class MyBean extends MyAbstractClass

因此JNDI绑定变为

java:global/jndinaming/MyBean!learning.jndinaming.MyBean

没关系,我调整了字符串和我的代码:

(MyInterface) ctx.lookup("java:global/jndinaming/MyBean!learning.jndinaming.MyInterface");

成为这个:

(MyInterface) ctx.lookup("java:global/jndinaming/MyBean!learning.jndinaming.MyBean");

我得到了一个Class Cast异常:

  

ClassCastException:无法将MyBean $$$ view68(id = 938)强制转换为   MyInterface的

接口文件位于客户和工作项目均可访问的项目中。

客户端项目包含调用查找方法的代码。

worker项目具有bean实现和抽象类。

项目位于单独的ear文件中,但位于同一个wildfly容器中。

为什么在抽象类中添加新的“图层”会导致此类强制转换异常?我该怎么做才能解决它?

顺便说一句: 尝试使用

进行访问
 (MyInterface) ctx.lookup("java:global/jndinaming/MyBean!learning.jndinaming.MyInterface");

导致抛出nameNotFound异常的结果

编辑: 这是bean的当前状态,Abstract类和接口:

接口:

import javax.ejb.Remote;

@Remote
public interface MyInterface {
    public void print();

}

抽象类:

public abstract  class MyAbstractClass implements MyInterface{

}

为myBean

@Stateless
public class MyBean extends MyAbstractClass{

    @Override
    public void print() {
        System.out.println("MyAbstractClassExtender.PRINT");

    }

}

客户代码:

@Stateless
public class TimedBean {
    @Resource
    private SessionContext              ctx;

    @Schedule(second="*/10", minute="*", hour="*")
    public void run() throws NamingException{
            MyInterface c2 = (MyInterface) ctx.lookup("java:global/workerear/workerejb-0.0.1-SNAPSHOT/MyAbstractClassExtender!learning.lib.MyInterface");
        c2.print();
    }

}

2 个答案:

答案 0 :(得分:1)

从界面中删除@Remote并将其添加到bean可以解决问题:

public interface MyInterface {
    public void print();

}

@Stateless
@Remote(MyInterface.class)
public class MyBean extends MyAbstractClass{

    @Override
    public void print() {
        System.out.println("MyAbstractClassExtender.PRINT");

    }

}

然后JNDI绑定就是这个:

java:global/workerear/workerejb-0.0.1-SNAPSHOT/MyBean!learning.lib.MyInterface

演员表演。

答案 1 :(得分:0)

注释处理器检查implements子句中的接口以确定远程/本地接口。由于这种情况下的接口是继承的,而未在implements子句中显式定义,因此注释处理器将采用容器的默认行为。

一种解决方案是向Bean添加一个工具:

@Stateless
public class MyBean extends MyAbstractClass implements MyInterface{
    @Override
    public void print() {
        System.out.println("MyAbstractClassExtender.PRINT");

    }
}

你的答案中陈述的另一个是在你的bean中声明远程接口而不是:

@Stateless
@Remote(MyInterface.class)
public class MyBean extends MyAbstractClass{

    @Override
    public void print() {
        System.out.println("MyAbstractClassExtender.PRINT");

    }
}

一种方法优于另一种方法将有利有弊。我发现这个博客非常有趣http://piotrnowicki.com/2013/03/defining-ejb-3-1-views-local-remote-no-interface/