为什么我不能通过 JNDI 使用远程接口访问我的 EJB?
Why can't I access my EJB using the remote interface through JNDI?
我在使用 JNDI 检索 bean 时遇到问题。
我有两只耳朵:客户耳和工人耳。
Clientear 包含 clientejb 和 libejb
Workerear 包含 workerejb 和 libejb
该库包含 MyInterface
workerejb 包含 bean 和抽象 class
clientejb 包含执行查找的客户端代码。
我实现远程接口的 bean
public class MyBean implements MyInterface
它的 JNDI 绑定是
java:global/jndinaming/MyBean!learning.jndinaming.MyInterface
没关系。
现在我想让它扩展一个摘要 class:
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 转换异常:
ClassCastException: Cannot cast MyBean$$$view68 (id=938) to
MyInterface
接口文件位于客户端和工作项目都可以访问的项目中。
客户端项目包含调用查找方法的代码。
worker 项目有 bean 实现和抽象 class。
这些项目在不同的 ear 文件中,但在同一个 wildfly 容器中。
为什么添加带有抽象 class 的新 "layer" 会导致此 class 转换异常?我能做些什么来解决它?
顺便说一句:
尝试使用
访问
(MyInterface) ctx.lookup("java:global/jndinaming/MyBean!learning.jndinaming.MyInterface");
导致抛出 nameNotFound 异常
编辑:
这是 bean 的当前状态,抽象 class 和接口:
接口:
import javax.ejb.Remote;
@Remote
public interface MyInterface {
public void print();
}
摘要Class:
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();
}
}
从接口中删除@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
演员表也很成功。
注释处理器检查 implements 子句中的接口以确定 remote/local 接口。因为这种情况下的接口是继承的并且没有在 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/
我在使用 JNDI 检索 bean 时遇到问题。
我有两只耳朵:客户耳和工人耳。 Clientear 包含 clientejb 和 libejb Workerear 包含 workerejb 和 libejb
该库包含 MyInterface workerejb 包含 bean 和抽象 class clientejb 包含执行查找的客户端代码。
我实现远程接口的 bean
public class MyBean implements MyInterface
它的 JNDI 绑定是
java:global/jndinaming/MyBean!learning.jndinaming.MyInterface
没关系。
现在我想让它扩展一个摘要 class:
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 转换异常:
ClassCastException: Cannot cast MyBean$$$view68 (id=938) to MyInterface
接口文件位于客户端和工作项目都可以访问的项目中。
客户端项目包含调用查找方法的代码。
worker 项目有 bean 实现和抽象 class。
这些项目在不同的 ear 文件中,但在同一个 wildfly 容器中。
为什么添加带有抽象 class 的新 "layer" 会导致此 class 转换异常?我能做些什么来解决它?
顺便说一句: 尝试使用
访问 (MyInterface) ctx.lookup("java:global/jndinaming/MyBean!learning.jndinaming.MyInterface");
导致抛出 nameNotFound 异常
编辑: 这是 bean 的当前状态,抽象 class 和接口:
接口:
import javax.ejb.Remote;
@Remote
public interface MyInterface {
public void print();
}
摘要Class:
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();
}
}
从接口中删除@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
演员表也很成功。
注释处理器检查 implements 子句中的接口以确定 remote/local 接口。因为这种情况下的接口是继承的并且没有在 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/