users@glassfish.java.net

ejbcontext.isCallerInRole causes "No mapping available for role reference"

From: janne postilista <jannepostilistat_at_gmail.com>
Date: Mon, 11 Oct 2010 13:13:57 +0300

I have an EJB which has security role-checking code:

@Stateless
public class SomeBean {
   @RolesAllowed(value="FOO_ROLE")
   public Object bla(String foo) {
       Principal p = context.getCallerPrincipal();
       log.debug("caller is principal: " + p);
       log.debug("has role 'FOO_ROLE': " + context.isCallerInRole("FOO_ROLE"));

Running this results in

Caused by: java.lang.IllegalStateException: No mapping available for
role reference FOO_ROLE
       at com.sun.ejb.containers.EJBContextImpl.isCallerInRole(EJBContextImpl.java:458)
       at com.gofore.valtimo.soaservice.DynamicEjbCaller.debugPrincipal(DynamicEjbCaller.java:119)
       at com.gofore.valtimo.soaservice.DynamicEjbCaller.call(DynamicEjbCaller.java:82)
       ... 73 more

The @RolesAllowed annotation works fine though and lets only correct
users call the method. Why does the isCallerInRole() throw exception
when @RolesAllowed works? I have also tried adding
@DeclareRoles({"FOO_ROLE"}) to the bean but this does not help.

I have META-INF/ejb-jar.xml:

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar version="3.1" xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd">
   <assembly-descriptor>
       <security-role>
           <role-name>FOO_ROLE</role-name>
       </security-role>
   </assembly-descriptor>
</ejb-jar>

and META-INF/sun-ejb-jar.xml:

<!DOCTYPE sun-ejb-jar PUBLIC "-//Sun Microsystems, Inc.//
DTD GlassFish Application Server 3.0 EJB 3.1//EN"
"http://www.sun.com/software/appserver/dtds/sun-ejb-jar_3_1-0.dtd">
<sun-ejb-jar>
   <security-role-mapping>
       <role-name>FOO_ROLE</role-name>
       <group-name>foorole_group_name_in_database</group-name>
   </security-role-mapping>
</sun-ejb-jar>

I am not sure if this relevant to the problem, but I am using
JDBCRealm which I do a programmatic login at EJB a before calling the
EJB "SomeBean":

@Stateless
public class SomeOtherBean {
  public void duudaa() {
       ProgrammaticLogin login = new ProgrammaticLogin();
       boolean success;
       try {
           success = login.login(username, password, REALM_NAME, true);
       } catch (Exception ex) {
           throw new RuntimeException("login failed", ex);
       }
       someBean.bla(zzz);