users@glassfish.java.net

Local EJB access within an Entity Bean

From: <glassfish_at_javadesktop.org>
Date: Thu, 17 Jan 2008 03:40:38 PST

I have been having a good bit of trouble getting instances of local EJBs in my project. I am new to EJBs and just started learning with the EJB 3.0 spec.

I am trying to build a web application (eventually incorporating JSF) with many to all of the business methods residing in EJBs. At fist I was having a very hard time getting the classes that resided in the web tier (.war) to access the backing EJBs locally, but after much research and learning, was successfully able to instantiate an EJB via its local interface and the javax.naming.Context.

Now I am trying to access this same EJB within an Entity Bean (both reside in the same .ear). Ideally, I would like to include a reference to the EJB within the Entity, having it injected by the container - but I have also tried to acquire it directly via the naming.Context as I did in the .war portion. Nothing I do works.

I declared a local interface as:

@Local
public interface RoleManagerLocal {
    Role getRoleById(String roleId);
    Role getRoleByName(String roleName);
    boolean roleHasMember(Role role, RoleMember roleMember);
}



with its implementation as (the RoleManagerRemote interface is defined but is currently without any methods):

@Stateless
public class RoleManagerBean implements RoleManagerRemote, RoleManagerLocal {
    
    @PersistenceContext EntityManager entityManager;
    
    public Role getRoleById(String roleId) {
        ...
    }
    
    public Role getRoleByName(String roleName) {
        ...
    }
 
    public boolean roleHasMember(Role role, RoleMember roleMember) {
        
        ...
    }
 
}


My entity bean is below:

@Entity
@Table(name = "roles")
@DiscriminatorValue(value="ROLE")
public class Role extends RoleMember {
    private static final long serialVersionUID = 1L;
 
    @Column(name = "role_name", nullable = false)
    private String roleName;
    
    @Lob
    @Column(name = "role_mask", nullable = false)
    private byte[] roleMask;
    
    @JoinTable(name = "memberhierarchy", joinColumns = {_at_JoinColumn(name = "member_id", referencedColumnName = "member_id")}, inverseJoinColumns = {_at_JoinColumn(name = "member_id", referencedColumnName = "member_id")})
    @ManyToMany
    private Collection<RoleMember> childRoleMembers;
    
    @JoinColumn(name = "member_id", referencedColumnName = "member_id", insertable = false, updatable = false)
    @OneToOne
    private RoleMember roleMember;
 
    @Transient
    @EJB
    private RoleManagerLocal roleManager;
    
    public Role() {
        super();
        
        // this line would not be included if the @EJB injection worked
        this.roleManager = this.lookupRoleManagerBean();
    }
 
    public Role(String memberId) {
        super(memberId);
        
        // this line would not be included if the @EJB injection worked
        this.roleManager = this.lookupRoleManagerBean();
    }
 
    public Role(String memberId, String roleName, byte[] roleMask) {
        super(memberId);
        this.roleName = roleName;
        this.roleMask = roleMask;
        
        // this line would not be included if the @EJB injection worked
        this.roleManager = this.lookupRoleManagerBean();
    }
 
    public String getRoleName() {
        return roleName;
    }
 
    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }
 
    public byte[] getRoleMask() {
        return roleMask;
    }
 
    public void setRoleMask(byte[] roleMask) {
        this.roleMask = roleMask;
    }
 
    public Collection<RoleMember> getChildRoleMembers() {
        return childRoleMembers;
    }
 
    public void setChildRoleMembers(Collection<RoleMember> childRoleMembers) {
        this.childRoleMembers = childRoleMembers;
    }
 
    protected RoleMember getRoleMember() {
        return roleMember;
    }
 
    protected void setRoleMember(RoleMember roleMember) {
        this.roleMember = roleMember;
    }
 
    public boolean hasRoleMember(RoleMember member) {
        return this.roleManager.roleHasMember(this, member);
    }
 
    // this method would not be included if the @EJB injection worked
    private RoleManagerLocal lookupRoleManagerBean() {
        try {
            Context c = new InitialContext();
            return (RoleManagerLocal) c.lookup("java:comp/env/RoleManagerLocal"); // I have tried countless items here
        } catch (NamingException ne) {
            java.util.logging.Logger.getLogger(getClass().getName()).log(java.util.logging.Level.SEVERE, "exception caught", ne);
            throw new RuntimeException(ne);
        }
    }
}


As I stated above, I am trying to get a reference (roleManager) to the RoleManagerBean via the local interface (RoleManagerLocal), ideally by container injection, but I have also tried throught the context lookup. In the above Entity Bean, I included both the @EJB annotation as well as the lookup call and method to show what I have attempted. I never have both of these at the same time.

As an added note, I have successfully been able to access this bean remotely within the Entity Bean, most simply by the statement

@Stateless(mappedName="RoleManagerBean")
public class RoleManagerBean implements RoleManagerRemote, RoleManagerLocal {
...


and then pulling it from the context via

...
return (RoleManagerRemote) c.lookup("RoleManagerBean");
...


but alas, no success locally.

Also, I am using Glassfish V2 and Netbeans 6.0 should that make a difference.

Could someone please help me nail down what I am doing wrong here?
[Message sent by forum member 'sed108' (sed108)]

http://forums.java.net/jive/thread.jspa?messageID=254396