One of the key enabling technologies introduced by J2SE 5.0 is the program annotation facility defined by JSR-175. This facility allows developers to annotate program elements in Java programming language source files to control the behavior and deployment of an application.
Metadata annotations are a key element in the simplification of the development of EJB 3.0 applications.
Annotations available for:
Defining Web Services
Defining Enterprise Beans
Calling out EJB Lifecycle callbacks or Interceptors
Dependency Injection
Almost anything that you used to previously have a Deployment Descriptor entry for
Transaction Attributes
Security
Annotations: Pros
Easier to write than .xml
Easier to understand than .xml
Fewer files to maintain
Annotations: Cons
Only visible in source-code
Can't express all Java Platform, EE 5 metadata
Blurs lines between Java EE platform roles (e.g., Component Provider vs. Application Assembler)
Best Uses for Annotations
Metadata that does not change often
Metadata tied to component development time
Examples:
Structural metadata
@Stateless
@WebService
@Entity
Environment dependencies
@EJB
@Resource
@PersistenceContext
Callbacks
@PostConstruct
@Timeout
@Remove
Best Uses for Deployment Descriptors
Overriding annotations and defaults
Application assembler metadata
EJB Security Method Permissions
Typically not known until assembly/deployment time
Likely to change
Independent of business logic
Dependency linking info
e.g. cross-module ejb-link
Metadata that has no corresponding annotation
e.g. EJB Default interceptors, EJB 2.x Entity Beans, Message Destinations
NOTE. Although it is not anticipated as a typical use case, it is possible for the application developer to combine the use of metadata annotations and deployment descriptors in the design of an application. When such a combination is used, the rules for the use of deployment descriptors as an overriding mechanism apply.
Guidelines for .xml Overriding
Use sparingly
Overuse can make app difficult to understand/maintain
Good with linking metadata
e.g., ejb-link, persistence-unit-name
Keep in mind not all annotations are overridable
e.g., Session bean type (Stateful vs. Stateless) can't be overridden
Don't Forget Spec-Defined Defaults
Default values can be easier than annotations and .xml
EJB based transaction demarcation type
Default: Container managed transaction
EJB based transaction attribute
Default: TX_REQUIRED
Environment annotation name()
Default: Derived from class and field/method
Component Dependency Annotations
For declaring environment dependencies
For eliminating JNDI lookups
ejb-ref, resource-ref, service-ref, etc.
Available on container-managed classes
Enterprise beans and interceptors, Servlets, Filters, ServletListeners, JSF Managed Beans, Web service endpoints and Handlers
NOT FOR JSP, JSP beans, or other plain Java classes that are not available at deployment
Declared at Class, Field, or Method level
Field/method level dependencies injected at runtime
Annotation example:
@Resource(name="Foo") private DataSource ds;
Deployment Descriptor example:
<resource-ref> <res-ref-name>Foo</res-ref-name> <res-ref-type>javax.sql.DataSource</res-ref-type> <injection-target> <injection-target-class>com.acme.FooBean</injection-target-class> <injection-target-name>ds</injection-target-name> </injection-target> </resource-ref>
Dependency Injection
Available for Fields as well as Methods
Available anywhere on the inheritence hierarchy
Follows normal language overriding rules
@PostConstruct annotation available to provide initialization after injection
Injected Field/Method Access Modifiers
Spec allows public, package, protected, private
Which should you use?
Private is best
Injected data is typically internal to the .class
Exception: Overriding of environment dependencies within a class hierarchy
Use sparingly
Tightly couples classes
Harder to understand/maintain
Which Is Best: Field, Method, or Class-level?
Field-level: Easiest
e.g., @EJB Converter converter
Takes fewest characters to declare
Supports injection
Method-level
Useful for logic tied to a specific dependency injection
But Field-level + @PostConstruct would work too
Class-level
Useful for dependency declaration WITHOUT injection
Declare environment dependency for use by non container-managed classes
Class-Level Dependency Example:
FooBean.java
@EJB(name="ejb/bar", beanInterface=Bar.class) public class FooBean implements Foo { ... }
Utility.java
Bar bar = (Bar) context.lookup("java:comp/env/ejb/bar");
Another Class-Level Dependency Example:
Scenario: Stateful Session Bean creation
EJB 3.0 SFSBs are created as a side-effect of injection/lookup
Common need : many instances of same SFSB
Using Field-based dependency + injection:
@EJB Cart cart1; @EJB Cart cart2; @EJB Cart cart3;
is too static.
Alternative: Class-level dependency + lookup
@EJB(name="ejb/Cart", beanInterface=Cart.class) public class CartClient { ... Cart[] carts = new Cart[numCarts]; for(int i = 0; i < carts.length; i++) { carts[i] = (Cart) ctx.lookup("java:comp/env/ejb/Cart"); } }
Concurrency and Injection
Injection does not solve concurrency issues
If an object obtained through lookup() is non-sharable, it's non-sharable when injected
Be careful with Servlet instance injection:
public class MyServlet ... { private @EJB StatelessEJB stateless; // OK private @EJB StatefulEJB stateful; // dangerous! }
Most common issues: Stateful Session Beans, PersistenceContexts
Recommended alternative: lookup() and store in HttpSession:
@PersistenceContext(name="pc", type=EntityManager.class) public class MyServlet ... { EntityManager em = ctx.lookup("java:comp/env/pc"); httpSession.setAttribute("entityManager", em); }
Performance and Injection
Use of injection is unlikely to cause performance issues
Injection is essentially a ctx.lookup() + one reflective operation
Injection occurs at instance creation-time
Overhead of injection typically small compared to instance creation itself
Most lookups() resolved locally within server
Instances are typically long-lived/reused
![]() ![]() ![]() ![]() ![]() ![]() |
![]() |
![]() |