Erates
Erates

Reputation: 666

Decorator Operation not allowed

I have a decorator on an EJB (so this decorator is CDI if I understand it correct). I need do some business logic depending on the role the logged in user is. So in the EJB I have the SessionContext, but since this is an EJB object, I need to look it up via JNDI.

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

This works, but creates another error. When I try to call ctx.isCallerInRole("MyRole"); I get this error:

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)

What I expect is happening is that a CDI is not allowed to ask the SessionContext if the logged in user is in the specified role. Is there a way how I can solve this? I've been roaming Google for a few days now, without success.

Erates

Edit:

This is what I have at the moment:

Interface:

@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:

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

This gives me a NullPointerException at StatelessSessionBean.isCallerInRole pointing to the fact that the SessionContext is not injected. (I think because of the difference between SessionContext (EJB) and Inject (CDI)) Note, the EJB and Decorator are in different packages in different JARs in the EAR.

Upvotes: 0

Views: 218

Answers (2)

Erates
Erates

Reputation: 666

Problem was a Classloader issue.

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

I used a producer class that creates the EntityManager and SessionContext using the @Produces annotations on them. This producer class was in the "ejb" jar. On the decorators I used a provided dependency to the "ejb" so at that point, it knew where the @Inject would come from.

But once in runtime, the custom EJB would find the decorator because it is in the libs folder, but the decorator could not find the Produced SessionContext or EntityManager.

Now I've moved the decorators inside the "custom ejb" and all works just fine and dandy.

Upvotes: 1

fantarama
fantarama

Reputation: 880

The SessionContext is created for each bean instance, with the lookup approach you didn't obtain the ctx bind to your bean instance so the method is not allowed. Try using @Resource injection to obtain the bean context.

Upvotes: 0

Related Questions