This Article presents two important new features of EJB 3.0 which is bundled with Java EE 5.0 specification, which are Annotations and Dependency Injection. The solid reason for this article is , it will give us an idea how these features are used, so on their encounter in other articles of EJB3.0, we can understand their functionality. So we can say learning this article will give us a smooth drive in later other EJB 3.0 core concepts. So now we are going to start to see how Annotations and Dependency Injection has made the life of a developer easier and code more simple and manageable.
also read:
Annotatons in EJB 3.0
Annotations came into existence with Java 5.0. Annotations essentially allow us to attach some additional information to a Java class, interface,methods and variables. The additional information that we supply can be used by development environments like Eclipse, Java compiler, a deployment tool, a persistence provider like Hibernate or a runtime environment like the Java EE container. So, annotations can be called custom java modifiers (in addition to public final, static etc.) that can be used by anything handling java source code (like java compiler) or byte code(like java runtime environment, j2ee container ).
In fact, annotations are used to affect the way programs are treated mostly by tools. These tools use these annotations applied in program to produce derived files.
- Tools are- compiler, IDE (Integrated Development Environment), Runtime tools like(J2ee container etc.).
- Derived files are :- New Java code, deployment descriptor, class files.
In EJB 3.0 annotations are used to give our components “configuration metadata” that “configuration metadata” in earlier version EJB 2.0 we used to give by way of Deployment Descriptor. So, use of annotations eliminates the need of XML based Deployment Descriptor (exceptions are there like Default Listener as we will see can be configured only through Deployment Descriptor not by using annotation). Annotations provide us or benifit us by
- Declarative Programming
- Less coding since tool will generate the boiler plate code from annotations in the source code
Simple Example
///Annotation Example on Java 5.0 to understand what is it and how it can be utilized... //annotation interface import java.lang.annotation.*; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface ObjColor { String minecolor() default "Red"; } ....... // plain interface public interface Bounceable { public void bounce(); } ..... // Class using plain interface and annotation @ObjColor(minecolor="Yellow") public class Ball implements Bounceable { public void bounce(){ String ballColor=Ball.class.getAnnotation(ObjColor.class).minecolor();//getting the value of minecolor element of ObjColor annotation System.out.println("Hey, I am a Ball , I implement Bounceable interface "+ "so now I can bounce...Can you see some information has been attached to me"+ " which is neither extended nor implemented , and "+ "for this no new field or mathod has been added"+ "professional calls it Annotation and says i can use it ..."+ "and color of mine is "+ballColor); } public static void main(String[] args) { Ball b=new Ball(); b.bounce(); } }
Explanation of Simple Example
Lets understand this simple code…
- Here @ObjColor is an annotation applied on the class (or we can say attached to the class). It tells the tools , which will make use of it that the color of ball is Red that may be used by anybody. More important this extra information is attached to the class without extending , implementing or adding extra method or variable. this information can be used when required inside…like we have got value of color of ball…( String ballColor=Ball.class.getAnnotation(ObjColor.class).minecolor();//getting the value of minecolor element of ObjColor annotation)
- As annotation is an special kind of interface. It must be imported from where it is defined. As we can see that this interface has @Target(ElementType.TYPE) it means this @ObjColor annotation can be applied to Class, interface (including annotation type), or enum declaration. and it has @Retention(RetentionPolicy.RUNTIME), which means this extra details attached is available upto runtime( Annotations are to be recorded in the class file by the compiler and retained by the VM at run time, so they may be read reflectively).
Replacing Deployment Descriptor with Annotations in EJB 3.0
In container managed environment , components need many services (Like. Transaction, Security, Remotability etc.) which are provided by the container. For this purpose service configuration is required to be given to component which is used by container. Service configuration using Java Metadata annotations is easily the most important change in EJB 3.0. As we will see in other articles that annotations simplify the EJB programming model, eliminate the need for verbose(detailed) Deployment Descriptor. lets have a quick refresh about DD(Deployment Descriptor).
What is Deployment Descriptor?
A Deployment Descriptor is simply an XML based file that contains application configuration information. Every Deployment unit in Java EE can have a Deployment Descriptor that describes its contents and environment. Some example of deployment units are the Enterprise Archive (EAR),Web Application Archieve (WAR), and the EJB module(ejb-jar). Deployment Descriptor file example as web.xml in Web Application Archieve and ejb-jar.xml in EJB module. One who has used EJB 2.0 , knows that how verbose the XML (ejb-jar.xml) descriptor was. EJB 3.0 makes the use of DD optional. We can use metadata annotations instead of descriptor entries.
Notes : Both Annotations and DD can be used togetherand Deployment Descriptor entries overrides configuration values hard coded in EJB components. The most obvious way of mixing and matching annotation and XML -Metadata is to use for deployment specific configurations while using annotations for everything else.
Weakness of Annotations
It isn’t always a good idea to mix and match configuration with source code such as annotations. This means that you would have to change source code each time you made a configuration change to something like a database connection resource or deployment descriptor environment entry.
Common Annotations on EJB 3.0
Here is a list of Metadata annotations introduced on Java EE. Although primarily geared towards EJB 3.0, these annotations apply to Java EE components such as Servlets and JSF managed beans as well as application clients. So we will see this list in relevence like usage of annotation and the Java EEcomponents which can use it. Annotations defined in the javax.annotation.* package are defined by the common Metadata Annotations API (JSR-250).
- javax.annotation.Resource :- Its usage is in Dependency injection of resources such as Data Source, JMS Objects etc. Components that can use this annotation are as : EJB, Web Components, application client.
- javax.annotation.PostConstruct :- Its usage is in declaring a method, a life cycle method. Components that can use this annotation are as : EJB, Web Components.
- javax.annotation.PreDestroy :- Its usage is in declaring a method , a life cycle method. Components that can use this annotation are as : EJB, Web Components.
- javax.annotation.security.RunAs :- Its usage is in security related coding. Components that can use this annotation are as : EJB, Web Components.
- javax.annotation.security.RolesAllowed :- Its usage is in security related coding. Components that can use this annotation are as : EJB.
- javax.annotation.security.PermitAll :- Its usage is in security related coding. Components that can use this annotation are as : EJB.
- javax.annotation.security.DenyAll :- Its usage is in security related coding. Components that can use this annotation are as : EJB.
- javax.annotation.security.DeclareRoles :- Its usage is in security related coding. Components that can use this annotation are as : EJB, Web Components.
- javax.ejb.EJB :- Its usage is in Dependency injection of Session Bean. Components that can use this annotation are as : EJB, Web Components, application client.
- javax.jws.WebServiceRef :- Its usage is in Dependency injection of Web Services. Components thact can use this annotation are as : EJB, Web Components, application client.
- javax.persistence.PersistenceContext :- Its usage is in Dependency injection of Container managed EntityManager. Components that can use this annotation are as : EJB, Web Components.
- javax.persistence.PersistenceUnit :- Its usage is in Dependency injection of EntityManagerFactory. Components that can use this annotation are as : EJB, Web Components.
Here we have listed a few annotations. There are many other annotations on the J2ee plateform which we will be using it in all the future articles of EJB 3.0. Here the sole reason of listing some annotations and giving an example of annotation on
Java 5.0 plateform is to explain the functionality of annotations.
Dependency Injection (DI) in EJB 3.0
Dependency Injection (DI) is another new feature of EJB 3.0. One who has worked in earlier version of EJB like EJB 2.0 knows that same repetition of code to lookup a resource or EJB using manual JNDI lookup.
To Solve the complxities surrounding manual JNDI lookups to inject a managed resource from container managed environment(like EJBs, DataSource,JMS Objects , EntityManager, EntityManagerFactory etc.). Almost every component uses another component or resource to implement functionality. The Primary goal of Dependency Injection is to make component interdependencies as loosely coupled as possible.
Resource can be accessed in your environment by two ways
- In Earlier versions of EJB resource ould be accessed by only JNDI lookup.
- But now in EJB 3.0 resource can be injected by JNDI lookup (as it was earlier) and by Dependency Injection as well.
Dependency Injection is reversed of JNDI lookup. As you see in Manual JNDI lookup model, the bean explicitely retrieves the resource and components it needs. As a result, components and resource names are hard-coded in the bean. With DI , the container reads target bean configuration and then figures out what beans and resources the target bean needs and inject them into the bean at runtime. In the end with DI you write no lookup code and can easily change configuration to swap out beans and resources as needed.
Note:- In essence , Dependency Injection(DI) allows you to declare component dependencies and lets the container deal with the complexities of service or resource instantiation, initialization, sequencing and supplies the service or resource references to the clients as required.
Here we will see one example and will notice the difference in manual JNDI look-up and Dependency Injection for an EJB compontent.
Example 1
//file1:- HelloStateless.java package deepakPackage; import javax.ejb.Remote; @Remote public interface HelloStateless { public void printMe(String msg); } ......... //file2:- HelloStatelessBean.java package deepakPackage; import javax.ejb.Stateless; @Stateless public class HelloStatelessBean implements HelloStateless { public void printMe(String msg) { System.out.println("Hello Your message is : "+msg); } } ...... //file3: - MyServlet1.java Servlet Class MineServlet to use bean written //above using Dependency Injection..... import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.ejb.*; import deepakPackage.*; public class MyServlet1 extends HttpServlet { @EJB private HelloStateless hss; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); try { out.println("Output of printMe() method is : "+hss.printMe()); } } finally { out.close(); } } } ............................ //file4: -MyServlet2.java Servlet Class MineServlet to use bean written above using JNDI lookup import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.ejb.*; import javax.naming.InitialContext;//extra import import javax.naming.NamingException;//extra import import deepakPackage.*; public class MyServlet2 extends HttpServlet { private HelloStateless hss; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); try { InitialContext ic=new InitialContext(); Object obj= (HelloStateless)ic.lookup("mineHelloStatelessBeanJNDIname"); hss=(HelloStateless)Obj; out.println("Output of printMe() method is : "+hss.printMe()); } catch(NamingException e) { System.out.println("Naming exception: "+e.printStackTrace()); } } finally { out.close(); } } }
Code Explanation
Here we can see that a stateless session bean has been written by using a POJO(Plain Old Java Object) HelloStateless annotated with @Remote from javax.ejb.Remote.class, which tells that this interface can be used as a remote interface for a bean to be accessed by remote clients remotely to access the methods which have been exposed in this interface as here printMe() so this printMe() method can be accessed by remote clients.
A POJO class HelloStatelessBean.java annotated with @Stateless from Javax.ejb.Stateless.class, which gives this POJO a status of an Enterprise Stateless bean. It says that this bean is stateless (in next article we will know what is stateless). This POJO class implements that business interface(HelloStateless.java) and implements methods exposed in that interface which is Remote. means this bean class can be used only by remote clients as it implements only remote interface. And methods can be accessed by only remote clients only.
Here we have given two servlets one is accessing the same bean using Dependency Injection and another using the same bean using JNDI lookup. So see the Difference in both the servlet.
- In First Servlet MyServlet1.java we have used Dependency Injection to inject a reference to the business interface of the bean whose method we want to access.One import :- import javax.ejb.EJB; and one statement :- @EJB HelloStateless hss; is required to get reference to the Business Interface of the bean.
- In Second Servlet MyServlet2.java we have used manual JNDI lookup to get a reference to the business interface of the bean whose method we want to access. Here we need two imports :- import javax.naming.InitialContext; , import javax.naming.NamingException;and three statements :-
InitialContext ic=new InitialContext(); ,
Object obj= (HelloStateless)ic.lookup(“mineHelloStatelessBeanJNDIname”); , hss=(HelloStateless)Obj; ,
is required to get reference to the Business Interface of the bean.
Difference can be seen as how simple it is to inject a bean using Dependency Injection rather than using manual JNDI lookup.
Conclusion
Annotations which came in existence with JavaSE5, now have become default choice for configuaration of Metadata for resources.It support declarative programming and less code is required to fullfill the task and it eliminate the need for verbose and difficult to maintain Deployment Descriptor(exception is their as Default Listener we will see can be configured only with DD).
Dependency Injection as we have seen are dependent on annotations, provide an easy access to th resources binded in the JNDI. It provide an ease and a support for swap-out of resource as name of resources are not hard coded as in manual JNDI lookup. It lets the developer be happy and container resolve the complexities of resources to be injected in target component.
As both are the new features of EJB3.0 and provide ease in development and support declarative programming that improve the production.