Browse DevX
Sign up for e-mail newsletters from DevX


Try Declarative Programming with Annotations and Aspects : Page 2

Learn how to combine the power of annotations with aspects to provision enterprise services declaratively, in an EJB 3.0-compatible manner, while still providing container independence.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Example Application—Flight Booking
Through the rest of this discussion you will examine an implementation of a flight booking system that uses aspects with annotations to implement dependency injection, security, and transaction management. The application performs only two functions: It allows users to search for flights (Figure 1) and then to book a trip (Figure 2). Both of these operations will be secured to allow only recognized users to perform them. Also, since the 'book trip' operation involves booking two flights (the outbound and return flights), this operation will need to be transactional; i.e., both bookings will either succeed or fail as a unit of work.

Figure 1. Flight Search: First, users search for flights that meet their specified criteria.
Figure 2. Flight Booking: Next, users book both an outbound and a return flight. Both bookings must succeed or both must fail.

This simple Web application consists of a couple of servlets, a service façade, and a DAO layer (see Figure 3).
Figure 3. Flight Booking System Architecture: The flight booking system includes three main types of components which collaborate to fulfill the user's request.
The cross-cutting concerns of resource configuration, security, and transaction management will be provisioned by aspects (implemented with AspectJ 1.5 M3) which inject behavior declared in Java 5 annotations. The sample code can be downloaded from the sidebar of the article (see left column) and built using Maven 2.0.

Resource Injection
This EJB 3.0 draft specification allows resources to be declared via the @Resource annotation, which is defined in the draft common annotations specification, and injected into your EJB by the container. Dependency injection is a technique by which an object's dependencies are provided (injected) by an entity external to an object rather than explicitly created by the object. It is sometimes described as the Hollywood Principle, which jokingly means "don't call us, we'll call you."

Take the example of the TravelAgencyServiceImpl class which needs to find an implementation of the IFlightDAO interface in order to persist some data. Traditionally this is accomplished via a factory, singleton, service locator, or some other custom solution. One solution might look like the following:

public class TravelAgencyServiceImpl implements ITravelAgencyService { public IFlightDAO flightDAO; public TravelAgencyServiceImpl() { flightDAO = FlightDAOFactory.getInstance().getFlightDAO(); } public void bookTrip(long outboundFlightID, long returnFlightID, int seats) throws InsufficientSeatsException { reserveSeats(outboundFlightID, seats); reserveSeats(returnFlightID, seats); } }

As you can see, this implementation involves the creation of a special factory class which most likely reads configuration information stored somewhere to know what implementation of IFlightDAO to create. If instead of having the service explicitly create its dependencies they are injected by the container, then the details of configuration and object creation are delegated to the container. This allows the components of an application to be easily "wired" together in different configurations and eliminates a lot of rote singleton and factory code.

An implementation of this class that has its dependency on an implementation of IFlightDAO declared with a JSR 250 resource annotation might look as follows:

public class TravelAgencyServiceImpl implements ITravelAgencyService { @Resource(name = "flightDAO") public IFlightDAO flightDAO; public void bookTrip(long outboundFlightID, long returnFlightID, int seats) throws InsufficientSeatsException { reserveSeats(outboundFlightID, seats); reserveSeats(returnFlightID, seats); } }

In this case the container will provide the service class with the correct implementation of a resource named "flightDAO." But what if you want to take advantage of resource injection now without waiting for the EJB 3.0 release? Well, you can adopt a light-weight container that provides dependency injection such as Spring or Pico Container. However, I am not currently aware of a lightweight container that uses JSR 250 resource annotations to specify injection requirements (although I would expect to see some emerge in this space).

One solution is to use aspects to implement dependency injection. If you use the @Resource annotation for this purpose then your implementation will be consistent with the EJB 3.0 approach and forward-compatible with EJB 3.0 implementations—and this is not very difficult to do. The listing below shows an aspect created with AspectJ that injects field annotated with the @Resource annotation:

@Aspect public class InjectionAspect { private DependencyManager manager = new DependencyManager(); @Before("get(@Resource * *.*)") public void beforeFieldAccesses(JoinPoint thisJoinPoint) throws IllegalArgumentException, IllegalAccessException { FieldSignature signature = (FieldSignature) thisJoinPoint.getSignature(); Resource injectAnnotation = signature.getField().getAnnotation(Resource.class); Object dependency = manager.resolveDependency(signature.getFieldType(), injectAnnotation.name()); signature.getField().set(thisJoinPoint.getThis(), dependency); } }

All this simple aspect does is look up the implementation class from a property file (this logic is encapsulated in the DependencyManager object) and inject it into fields annotated with the @Resource annotation before field accesses. Voila: dependency injection a la JSR 250 and EJB 3.0! Obviously this implementation is not complete, but it does illustrate how one could go about providing resource injection in a JSR 250-compatible manner without necessarily adopting EJB.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date