June 11th, 2010
12:44 pm
Further notes on EJB Lookups

Posted under Glassfish
Tags , ,

Much of this has already been covered here, but I am posting these somewhat raw notes from an earlier investigative email as they include one or two links and points not covered elsewhere. I don’t have the time or inclination at present to rework everything into an existing post :-

 

1/ For local beans, you can just use defaults in @Stateless (in the bean) and in @EJB (in the referring code)
Note that when you do not use all the defaults, you must declare both the beaninterface and the name attributes

@EJB(name=”ejb/JPAGlassFishIce/SimpleBean”, beanInterface=SimpleBeanLocal.class)
private SimpleBean simpleBean;
2/ For remote beans, you can use e.g.

@Stateless(mappedName=”ejb/JPAGlassFishIceEJB/SimpleBean”)

Then

@EJB(beanInterface=SimpleBeanRemote.class, mappedName=”ejb/JPAGlassFishIceEJB/SimpleBean”)
private SimpleBean simpleBean;

Note – you must pass the class of the remote interface as above or it will not work, and you just get name not found exception.

3/ The above methods work for both access from one bean to another, and from a JSF managed bean to a remote (or local) bean
It also works from any POJO called from e.g. a JSF manged bean.
Note that this ability is container specific – Glassfish does it, other containers may vary in what/if/how they support.

4/ If doing JNDI lookups yourself to a local bean (via context.lookup), you need to add <ejb-local-ref> to web.xml as follows :-

 <ejb-local-ref>
    <ejb-ref-name>ejb/JPAGlassFishIce/SimpleBean</ejb-ref-name>
    <ejb-ref-type>Session</ejb-ref-type>
    <local-home></local-home>
    <local>uk.co.salientsoft.jpaglassfishice.domain.SimpleBeanLocal</local>
</ejb-local-ref>

This would be used if using e.g. Spring or a custom EL resolver  to inject references into JSF managed beans (via JSF DI)

Note that the JNDI name for the above local reference would be
“java:comp/env/ejb/JPAGlassFishIce/SimpleBean”
i.e. this is picking up from the <ejb-ref-name> above, and is prefixed java:comp/env
java:comp/env is a reference to the JNDI “Environment” service provider for Java EE
you can also use this  to look up environment variables etc.
see here http://java.sun.com/developer/technicalArticles/xml/WebAppDev4/

The <ejb-local-ref> stuff is done for you automatically if you use @EJB

5/ Note that JNDI names are container specific at present (fixed in java ee6)
See here for a good SUN post on all the EJB reference stuff :-
https://glassfish.dev.java.net/javaee5/ejb/EJB_FAQ.html

No Comments »

December 1st, 2009
4:33 pm
Java EE Enterprise Naming Context

Posted under EJB
Tags , ,

This article on CodeIdol is a good detailed FAQ on the Enterprise Naming Context or ENC, also known as the Java EE Application Component Environment, accessed via the JNDI name “java:comp/env”.  The article details the use of the java ee annotations in @javax.annotation.EJB and the equivalent XML, including injection of bean references via XML using <injection-target> rather than annotations. 

Another article on redhat.com gives a good overview of this with some other helpful links.

No Comments »

December 1st, 2009
11:38 am
EJB referencing/JNDI mapping examples in JSF/Glassfish

Posted under Glassfish
Tags , , ,

Update

I have posted some further notes on this here. The notes are in raw form from an earlier investigative email – much of it is covered here, but some points and links are not, and I do not have the time or inclination at present to rework everything into a single post!

The following examples show typical scenarios which have been tested as working :-

1/ Local EJB Interface injected into JSF managed bean via @EJB

Note that when implementing a dual interface as here, you can extend a single underlying interface. In this case, SimpleBeanLocal and SimpleBeanRemote both extend SimpleBean. However, when you do this, the implementation code must explicitly implemement both SimpleBeanLocal and SimpleBeanRemote as in this example. Implementing the superinterface SimpleBean on its own will not work. This is also explained in this post.

JSF managed bean code

@EJB()
private SimpleBean simpleBean;

 

EJB Implementation Code

@Stateless()
public class SimpleBeanImpl implements SimpleBeanLocal, SimpleBeanRemote {

...class code here...

}

 

 

2/ Local EJB Interface looked up in JSF managed bean directly via JNDI 

JSF managed bean code

try {
  InitialContext ctx = new InitialContext();

  /* Note that the JNDI name consists of the Java EE Environment Naming Context (ENC) -
    "java:comp/env", followed by "/", followed by the <ejb-ref-name> used in web.xml.
    The extra /Local is just to make the name different to the remote example.
    Any name can be used providing web.xml matches, and multiple slashes can be present.
  */

  simpleBean = (SimpleBean) ctx.lookup("java:comp/env/ejb/JPAGlassFishIce/Local/SimpleBean");     
  userList = simpleBean.fetchUsers();
} catch (NamingException e1) {
  e1.printStackTrace();
}

 

web.xml

<!-- We define a reference for the bean here.
     If we were using @EJB this would do it for us,
     but in this case we are using an explicit JNDI lookup.
-->
<ejb-local-ref>
    <ejb-ref-name>ejb/JPAGlassFishIce/Local/SimpleBean</ejb-ref-name>
    <ejb-ref-type>Session</ejb-ref-type>
    <local-home></local-home>
    <local>uk.co.salientsoft.jpaglassfishice.domain.SimpleBeanLocal</local>
</ejb-local-ref>

 

EJB Implementation Code

@Stateless()
public class SimpleBeanImpl implements SimpleBeanLocal, SimpleBeanRemote {

...class code here...

}

 

 

3/ Remote EJB Interface injected into JSF managed bean via @EJB

JSF managed bean code

@EJB(name="ejb/JPAGlassFishIce/SimpleBean", beanInterface=SimpleBeanRemote.class)
private SimpleBean simpleBean;

 

EJB Implementation Code

@Stateless(mappedName="ejb/JPAGlassFishIceEJB/SimpleBean")
public class SimpleBeanImpl implements SimpleBeanLocal, SimpleBeanRemote {

...class code here...

}

 

 

4/ Remote EJB Interface looked up in JSF managed bean directly via JNDI 

JSF managed bean code

try {
  InitialContext ctx = new InitialContext();

  /* Note that the JNDI name here matches the mappedName given in the
     @Stateless annotation in the EJB implementation code.
     mappedName is only relevant for remote interfaces.
     It is not used for a local interface.
  */

  simpleBean = (SimpleBean) ctx.lookup=("ejb/JPAGlassFishIceEJB/SimpleBean");     
  userList = simpleBean.fetchUsers();
} catch (NamingException e1) {
  e1.printStackTrace();
}

 

EJB Implementation Code

@Stateless(mappedName="ejb/JPAGlassFishIceEJB/SimpleBean")
public class SimpleBeanImpl implements SimpleBeanLocal, SimpleBeanRemote {

...class code here...

}

No Comments »

November 30th, 2009
5:28 pm
Accessing Local and Remote EJBs in Glassfish

Posted under Glassfish
Tags , , ,

This Glassfish article  is a must read reference on the naming and JNDI minefield when looking up local and remote EJBs.
There is also a very  informative Refcardz card on this topic. Refcardz can be downloaded as PDFs if  you register.
In my experience, there is a lot of misinformation around the internet on this which can be time consuming to weed out.

I’ve posted some examples of local and remote EJB access via both injection and JNDI here.

Here are some key points I worked through and learned :-

  1. Despite a number of blog posts to the contrary, EJBs can be injected via @EJB into JSF managed beans, POJOs called from managed beans, and servlets provided the JSF/servlets are running in the EJB container, e.g. if Glassfish is used both as servlet and EJB container.
  2. When injecting local EJBs, using the defaults on @EJB and matching defaults e.g. on @Stateless will work and the bean will inject.
  3. When injecting remote EJBs via @EJB, use the mappedName argument to specify the JNDI name of the remote bean. It is also essential to specify the class of the remote EJB interface in the beanInterface argument to @EJB. Failure to do this will result in NamingExceptions, which can give the misleading impression that it is the JNDI name that is wrong.
  4. If @EJB is not used, then <ejb-local-ref> may be used in web.xml to define a reference to the bean. If @EJB is used then this is handled automatically. The above Glassfish article details how the various fields in @EJB and <ejb-local-ref> are related.
  5. In addition to @EJB and direct JNDI lookups, EJBs can be injected via JSF using a custom EL resolver which performs the JNDI lookups and injections performed in faces-config.xml.  An interesting example of a custom EL resolver to do this is here. However, for injecting EJBs,  @EJB requires no extra code. It is also possible to inject EJBs via Spring, into beans managed by a Spring container. However these have not been pursued as @EJB is the easiest way. It would be overkill to use a Spring container purely for EJB injection/service location.

No Comments »