首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用泛型接口时不调用EJB拦截器

使用泛型接口时不调用EJB拦截器
EN

Stack Overflow用户
提问于 2011-03-17 18:36:40
回答 1查看 2.5K关注 0票数 4

给定以下代码

代码语言:javascript
复制
public interface Foo<T> {
    T get();
}

@Remote
public interface Bar extends Foo<String> {
}

@Stateless
public class BarImpl implements Bar {
    @Interceptors(ExceptionInterceptor.class)
    public String get() {
        throw new RuntimeException("not implemented");
    }
}

public class ExceptionInterceptor {
    @AroundInvoke
    public Object convertExceptionForExternalSystem(InvocationContext ctx) throws RuntimeException, Error {
        try
        {
            return ctx.proceed();
        }
        catch (Throwable e)
        {
            if (e instanceof Error)
                throw new Error("Changed");
            throw new RuntimeException("Changed");
        }
    }
}

当我们在远程调用一个方法时,

代码语言:javascript
复制
Bar bar = context.lookup(Bar.class.getName());
bar.get();

代码语言:javascript
复制
Foo foo = context.lookup(Bar.class.getName());
foo.get();

不调用拦截器(使用Glassfish 3.0.1)。

这个问题似乎是由于接口的编译类文件是

代码语言:javascript
复制
javap Foo
Compiled from "Foo.java"
public interface Foo{
    public abstract java.lang.Object get();
}

而对于BarImpl,它是

代码语言:javascript
复制
javap BarImpl
Compiled from "BarImpl.java"
public class BarImpl extends java.lang.Object implements Bar{
    public BarImpl();
    public java.lang.String get();
    public java.lang.Object get();
}

所以,当我们调用

代码语言:javascript
复制
Bar bar = ...;
bar.get();

在内部,方法

代码语言:javascript
复制
public java.lang.Object get(); 

,它将委托给

代码语言:javascript
复制
public java.lang.String get();

拦截器似乎只有在直接调用后者时才会被调用。当我将界面栏更改为

代码语言:javascript
复制
@Remote
public interface Bar extends Foo<String> {
    @Override
    String get();
}

拦截器在第一个调用(bar.get())中调用,但在第二个调用(foo.get())中没有调用。在类级别上定义拦截器可能会解决这个问题,但在我们的情况下不是一个选项。

我们是否做错了什么,或者这是java-ee-6的一般问题,或者这是glassfish中的错误?有解决办法吗?或者我们应该放弃在我们的服务中使用泛型吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-12-20 02:10:26

因为我们处理的是Java,所以类型擦除会在运行时接管,而您的业务接口将只包含:

代码语言:javascript
复制
public Object get();

您正在将接口强制转换为Bar,这没有问题(没有运行时类强制转换异常),但是被调用的业务方法是业务接口中存在的方法(因为这是客户端知道的唯一方法):Object get()版本。

此外,由于设计上只拦截业务方法调用,所以在String get()上委托的Object get()不会被拦截(它只是一个方法调用另一个方法)。这意味着,在最初的场景中,您试图拦截一个不属于业务接口的方法,因此永远不会被拦截。

由于EJB3规范对泛型的定义并不明确(基本上什么也没说),所以实现实际上将这一部分委托给了JVM虚拟机。在这种情况下,没有办法获得真正的通用支持,我要说的是,你不得不使用类拦截器或更改业务接口。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5337879

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档