And here we are at the climax of the series of posts about Guice and EJB3. Now starting to discover the wonders Guice JNDI. We will see how to inject through the EJB3 Dependency Iniection in non-managed (as POJOs) using Guice in JBoss AS 5. Basically the goal is to recreate the standard annotation "@ EJB3, pero 'around the limitations that require the EJB3 OF the only other components managed as EJB or Servlet.
We take 3 steps:
- Create an EJB3 Stateless Session Bean to deploy our JBOSS AS
- Write a Java application that invokes the remote in our EjbBean
- use Guice to inject through the inside EjbBean DI ' application.
Come on Eclipse and select menu: File -> New -> EJB Project and create a new project this way:
In this project part of a stateless session bean with a remote interface and its implementation. That 'the remote interface: package
org.bizlogic;
import javax.ejb.Remote;
@ Remote public interface
EJB3TestRemote {
statelessMethod public String (String s);}
and write any implementation like this: package
org.bizlogic;
import javax.annotation.PostConstruct;
javax.ejb.Remote import, import
javax.ejb.Stateless;
import org.apache.log4j.Logger;
/ ** * Session Bean Implementation class
EJB3Test
* /
@ Stateless @ Remote (EJB3TestRemote.class)
public class implements EJB3Test EJB3TestRemote
{private static Logger log = Logger.getLogger (EJB3Test.class.getName ());
/
** * Default constructor.
* / public
EJB3Test () {}
@ PostConstruct
public void useless () {
log.info (String.format ("postconstuct"));}
statelessMethod public String (String s) {
log.info (String.format ("Received: "+ s));
return String.format (" What a nice String! -% s ", new StringBuilder (s). reverse (). reverse ());}
}
Done! It 'was very simple. Now we can deploy this module in JBoss using the utility from making twiddle.sh (found in the distribution of jboss) or Eclipse: Right-click, on the project, select Export and select "EJB JAR file "to export it correctly. We give a name to the form and select the folder deploy our app server that is in $ JBOSS_HOME / server / default / deploy (though of course we use the configuration deployment). Once deployed at the end we will respond JBoss
16:11:35,118 INFO [SessionSpecContainer] Starting jboss.j2ee: jar = Test-Guice.jar-EJB3, name = EJB3Test, service = EJB3 16:11:35,118 INFO
[EJBContainer] STARTED EJB: org.bizlogic. EJB3Test ejbName: EJB3Test
16:11:35,126 INFO [JndiSessionRegistrarBase] Binding The following Entries in Global JNDI:
EJB3Test/remote - EJB3.x Default Remote Business Interface
EJB3Test/remote-org.bizlogic.EJB3TestRemote - Remote Business Interface EJB3.x
We jboss our active and deployed EJB3Test with its remote interface.
We arrived at the second point, and here comes into play immediately Guice. Let's create a simple Java project that uses this remote EJB3 and start having fun on the jndiContext Inject. Create a project "Java Project", press Alt + Enter to go on properties and go to "Build Path" and add the libraries that we have found in the distribution of Guice2 we downloaded from googlecode (here: http://google-guice .googlecode.com/files/guice-2.0.zip ) that are aopalliance.jar, Guice-2.0.jar, Guice-jndi.jar (and if we also want log4j-1.2.15.jar).
not we have inserted the code but now configure the jndi context that we will create: a source-level properties file that we insert a call jndi.properties with this content:
java.naming.factory.initial = org.jnp.interfaces.NamingContextFactory
java.naming . factory.url.pkgs = org.jboss.naming: org.jnp.interfaces
java.naming.provider.url = localhost
Usually Bean would have to call this to initialize a new instance of java.naming.InitialContext and do lookup on the object as in the following code: public class
NiceClass
{public void tryJndi () throws NamingException {InitialContext cxt
= new InitialContext ();
EJB3TestRemote test = (EJB3TestRemote) cxt.lookup (EJB3Test/remote ");
System.out.println (test.statelessMethod (" Hello JBOSS "));}
}
start with and configure Guice inject the JNDI context. We write a class that extends the class GuiceModule AbstractModule Guice and tell that every time he meets with a record selector Iniect @ @ Named ("JNDI") on a reference of type Context should inject a new instance of type as we saw in the InitialContext post 2 above.
AbstractModule {public class extends GuiceModule
@ Override protected void configure () {
bind (Context.class). AnnotatedWith (Names.named ("JNDI")). To (InitialContext.class);
}}
Ok now we can rewrite the class NiceClass like this: public class
NiceClass
{@ Inject @ Named ("JNDI")
private Context cxt;
public void tryJndi () throws
EJB3TestRemote NamingException {test = (EJB3TestRemote) cxt.lookup (EJB3Test/remote ");
System.out.println (test.statelessMethod (" Hello JBOSS "));}
}
So it works fine. But there 's a little problem. We told Guice to inject a new instance of InitialContext but this is not particularly useful. The real added value comes at a time that The Manage the context let Guice JNDI internally and we inject the EJB3 instead! Guice is already prepared to do this through a particular type of object called JndiIntegration. Going to see the code for this class we find that integrates with Guice JNDI but inside it has a reference @ Inject Context context; that at the time it is instantiated, it requires a binding to javax.naming.Context we have set ourselves. Obviously we have to be to indicate how to inject Guice JNDI context because of the jndi properties. So remove the configuration annotatedWith (Names.named ("JNDI"))
bind (Context.class). To (InitialContext.class). In (Singleton.class)
sources and also discover the operation of the static function "fromJndi" that creates an object of type
bind (DataSource . class). toProvider (fromJndi (DataSource.class, "java :..."));
Perfect! We can then jack the remote interface of our ejb3 specifying the object name to evoke directly GuiceModule class. So let's add
import static com.google.inject.jndi.JndiIntegration.fromJndi;
and finally configure our EJB3:
bind (EJB3TestRemote.class) . AnnotatedWith (Names.named (EJB3TestRemote ")). ToProvider (fromJndi (EJB3TestRemote.class," EJB3Test/remote "));
NOTE: One important note is that the suffix" / remote "part of the method of Invocation of default under JBOSS EJB3. OpenEJB on WebSphere or there may be some differences.
Now we make our bean: public class
NiceClass
{@ Inject @ Named ("EJB3TestRemote)
private EJB3TestRemote test;
public void tryJndi () throws NamingException {System.out.println
( test.statelessMethod ("Hello JBOSS"));}
}
Actually @ Named annotation selector there would be a real need that we saw only a remote interface. It would also be helpful if we had a local interface to choose which type of interface to use.
and we send ... et voila! how wonderful! Let's Try
[com.google.inject.Guice] please
--- What a nice string! - JBOSS HELLO
Now scenarios increases. We can inject through the EJB3 POJO inside, this way we can use objects that are not in EjbBean servlet and being able to extend our RPC calls using patterns other than standard, like the command pattern, where a good implementation and 'GWT-Dispatcher. Remains If in doubt want to use more 'java.naming.Context contexts within the same application (an environment configured for local objects, the other for remote objects). The only solution to this is to extend the class and add two static methods JndiIntegration fromJndiLocal fromJndiRemote and working on two different instances of InitialContext, instantiate, this time using a selector @ Named (). But it is a very specific case. For any comments please do not hesitate to contact me even davassi email [at] yahoo [dot] com. At the next post :-)