【问题标题】:Decorator Operation not allowed不允许装饰器操作
【发布时间】:2015-03-05 14:13:20
【问题描述】:

我在 EJB 上有一个装饰器(所以如果我理解正确,这个装饰器就是 CDI)。我需要根据登录用户的角色做一些业务逻辑。所以在 EJB 中我有 SessionContext,但由于这是一个 EJB 对象,我需要通过 JNDI 查找它。

InitialContext ic = new InitialContext();
SessionContext ctx = (SessionContext) ic.lookup("java:comp/EJBContext");

这可行,但会产生另一个错误。当我尝试拨打 ctx.isCallerInRole("MyRole"); 时,我收到此错误:

Caused by: java.lang.IllegalStateException: Operation not allowed
    at com.sun.ejb.containers.SessionContextImpl.checkAccessToCallerSecurity(SessionContextImpl.java:205)
    at com.sun.ejb.containers.EJBContextImpl.isCallerInRole(EJBContextImpl.java:447)
    at com.example.decorators.MyDecorator.findAll(MyDecorator.java:46)

我期望发生的是,如果登录用户处于指定角色中,则不允许 CDI 询问 SessionContext。有没有办法解决这个问题?我已经在 Google 上漫游了几天,但没有成功。

消耗

编辑:

这是我目前拥有的:

界面:

@Local
public interface StatelessSessionBeanLocal extends Serializable {
    <T> Collection<T> findAll(Class<T> clazz);
    boolean isCallerInRole(String role);
}

EJB:

@Stateless
public class StatelessSessionBean implements StatelessSessionBeanLocal {
    @Resource
    private SessionContext ctx;

    @Override
    public <T> Collection<T> findAll(Class<T> clazz){
       ...
    }

    @Override
    public boolean isCallerInRole(String role){
        return ctx.isCallerInRole(role);
    }
}

装饰者:

@Decorator
public abstract class StatelessSessionBeanDecorator implements StatelessSessionBeanLocal {
    @Inject
    @Delegate
    StatelessSessionBeanLocal sb;

    @Override
    public <T> Collection<T> findAll(Class<T> clazz){
        if (sb.isCallerInRole("TestRole")){
            return new ArrayList();
        } else {
            return sb.findAll(clazz);
        }
    }
}

这给了我一个在 StatelessSessionBean.isCallerInRole 的 NullPointerException ,指出 SessionContext 没有被注入。 (我认为是因为 SessionContext (EJB) 和 Inject (CDI) 之间的区别)注意,EJB 和 Decorator 在 EAR 中不同 JAR 中的不同包中。

【问题讨论】:

    标签: java jakarta-ee glassfish ejb cdi


    【解决方案1】:

    SessionContext 是为每个 bean 实例创建的,使用查找方法您没有获得 ctx 绑定到您的 bean 实例,因此该方法是不允许的。 尝试使用@Resource 注入来获取 bean 上下文。

    【讨论】:

    • 嗯.. @Resource 是 EJB(据我所知),并且由于这个 bean 是一个装饰器(CDI),它不会注入它。结果 --> NullPointerException
    • SessionContext 是一个 EJB 规范接口,ejb 是 cdi bean,尝试将你的装饰器定义为 @Stateless bean
    • 如果我这样做,Netbeans 会抱怨不应该使用装饰器或拦截器来注释无状态 bean。因此,当我删除 Decorator 注释时,Netbeans 抱怨 Delegate 注释不应该在无状态 bean 中。所以当我这样做时,装饰器的全部目的就消失了。还是我看错了?
    • 在那里定义@Stateless你的bean impl和injext SessionContext,然后定义一个方法委托给ctx.isCallerInRole。在您的装饰器中,使用 Inject Delegate Any MyBean myBean 注入 bean 相关实例并调用委托方法
    • 好的,所以我现在有一个方法 - boolean isCallerInRole(String role); 在接口中公开,(bean 和装饰器)都实现了。只有 bean 覆盖它,如果调用者在角色中,则请求 SessionContext(具有 @Resource 注释)。现在 NPE 在装饰器中消失了,但出现在 bean 本身的 isCallerInRole(String role) 方法中。
    【解决方案2】:

    问题是类加载器问题。

    ear
    | - lib
    |    | - custom decorators.jar
    | - custom ejb
    | - ejb
    | - war
    

    我使用了一个生产者类,它使用 @Produces 注释创建 EntityManager 和 SessionContext。这个生产者类在“ejb”jar 中。在装饰器上,我使用了 provided 对“ejb”的依赖,因此它知道 @Inject 的来源。

    但是一旦在运行时,自定义 EJB 会找到装饰器,因为它在 libs 文件夹中,但装饰器找不到 Produced SessionContextEntityManager

    现在我已经将装饰器移到了“自定义 ejb”中,并且一切正常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-17
      • 2014-10-06
      • 1970-01-01
      • 2016-09-27
      • 2018-05-26
      • 1970-01-01
      • 1970-01-01
      • 2012-01-03
      相关资源
      最近更新 更多