The preliminary implementation of declarative programming in EJB 3.0+aspect

Source: Internet
Author: User
Tags define execution implement resource return string
Programming Summary This article will explore with you how to combine annotations with the power of aspects to provide declarative services to enterprise implementations in a way that is compatible with EJB 3.0, while still providing the independence of the container.

   first, the introduction

As we collectively seek ways to further improve the production performance of software development, we-as members of the Java community-are generally turning to EE to provide solutions for more challenging technical issues such as distributed transaction management, concurrency, and object distribution for enterprise development. The philosophy behind it-these complex enterprise services can be implemented by Application server vendors and balanced for business developers-is really a good idea. Java EE, specifically EJB, has successfully provided a platform for building enterprise Java applications on it.

Part of this success is due to the ability to do declarative programming-a way to develop programs-in this way, you can declare infrastructure services rather than explicitly encode them with business logic so that the code is scattered everywhere. EJB has proven the value of this programming approach by allowing enterprise issues such as transactions and security to be declared and handled by a container with a release descriptor.

However, in the past years, more and more developers have realized that EJB has brought new challenges to the team in terms of productivity-each EJB must be accompanied by multiple interfaces, described in a release descriptor, accessed via Jndi, and so on. In addition, there are other difficulties in unit testing on the EJB outside the container, and today EJB has no longer focused on the simple object-oriented development.

Please note that you need to have the following tools for reading this article:

· Java 2 SDK 1.5

· Maven 2.0 Beta 2

The goal of EJB 3.0 is to make enterprise development easier in the following ways:

• Implementation of declarative requests for enterprise services by introducing meta data annotations

• Implementation of dependency/resource injection via annotations

• Realization of decoupling of enterprise beans and EJB-specific interfaces

• Continuous storage simplification via lightweight object-relational mapping

This is especially the spring breeze for EJB developers who have struggled to develop, test, and maintain EJBS. Using EJB 3.0 to write an enterprise bean is now easy, as a Pojo (traditional Java object) is created with specific annotations to mark it as an EJB and request Enterprise Services. The following is an example of an EJB from the EJB 3.0 public draft:

@Stateful
public class Cartbean implements ShoppingCart
{
private float total;
Private Vector productcodes;
public int Someshoppingmethod () {...};
...
}


The EJB 3.0 declaration essentially indicates that the developer needs a solution that is not a heavyweight, "Publish all, meet all", but a lightweight, easy-to-use solution that provides a range of enterprise services to developers. For this reason, one of the most important methods provided by EJB 3.0 is to implement the decoupling of enterprise beans and EJB APIs. Also, this solution brings interesting derivative-EJB now not only to run on different EJB containers, but also to run within any application framework-these frameworks must be able to recognize the EJB 3.0 (JSR 220) and the common annotations for declaring Enterprise Services (JSR 250).

This article does not provide in-depth exploration of declarative programming, EJBs, aspects, or annotations. Instead, just analyze the interrelationships between these technologies and discuss how they can be combined in a new way to simplify application development.

In this article, you will learn how to write an EJB 3.0-compliant bean and create a few simple aspects that enable it to have declarative transaction management, security, and resource injection capabilities. I hope you get the following benefits from this exercise:

• Three practical applications for learning (dependency injection, security, and transactions).

• Familiar with EJB 3.0 and the ideas behind it.

• Realize how EJB is decoupled from a specific API to allow EJB 3.0-compliant services to be delivered in lightweight implementations rather than just EJBS.

   second, instance application-flight order

Throughout the discussion, you will learn about the implementation of a flight ordering system-which uses aspects and 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 orders a trip (Figure 2). Both operations will be handled securely to allow only those users who can be identified to execute them. In addition, since the order travel operation includes ordering two flights (outgoing and return flights), you need to create the operation as transactional-for example, two subscriptions will either succeed or fail as a unit of work.


Figure 1. Flight enquiries: First, users look for flights that meet their specified criteria.

Figure 2. Flight order: Next, the user orders an outgoing flight and a return flight. Two orders are either successful or fail.
This simple Web application consists of several servlet, a service look, and a DAO layer (see Figure 3).

Crosscutting concerns such as resource configuration, security, and transaction management are provided by aspects (implemented with ASPECTJ 1.5 M3) to implement the injection behavior declared in the Java 5 annotations.


Figure 3. Flight Order System architecture: This flight ordering system consists of three main components-they unite to complete user requests. iii. Resource Injection

The EJB 3.0 Draft declaration allows resources to be declared via @resource annotations (this decision is defined in the draft general Comment statement) and is injected into your EJB by the container. Dependency injection is a technique in which an entity outside of an object is not explicitly able to provide (inject) a dependency on an object by an entity created by that object. It is sometimes described as the Hollywood principle-this jokingly means "don't give us a call, we'll call you".

Take the Travelagencyserviceimpl class as an example-this class needs to find an implementation of a Iflightdao interface to store some data for persistence. Traditionally, this is accomplished through a factory, singleton, service locator, or some other custom solution. One of the possible solutions looks like this:

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 includes creating a particular factory class-it is very likely to read configuration information stored somewhere to understand how to create Iflightdao. Configuration details and object creation will be represented on the container if the service is not explicitly creating its dependencies injected by the container. This allows components in one application to be easily connected together-using different configurations and eliminating large amounts of old-fashioned singleton and factory code.

An implementation of the class-it relies on an implementation of the Iflightdao declared with a JSR 250 resource annotation-may look like this:

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 a service class with the correct implementation of a resource named "Flightdao". But what if you want to use resource injection now instead of waiting for the EJB 3.0 release? Well, you can use a lightweight container-it can provide dependency injection, such as spring or Pico container. However, I am not aware of the existence of a lightweight container-it can use the JSR 250 resource annotations to specify the injection requirements (although I am very much looking forward to some in this regard).

One solution is to use aspects to implement dependency injection. If you use @resource annotations for this purpose, your implementation will be consistent with EJB 3.0 and forward compatible with EJB 3.0 implementations-and this is not a very difficult thing to achieve. The following list shows an aspect created with ASPECTJ-it injects the fields 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);
}
}


This simple aspect is all done by querying the implementation class from a property file (which is encapsulated in the Dependencymanager object) and injecting it into the fields annotated with the @resource annotation before accessing the field. Obviously, this implementation is not complete, but it does illustrate how you can provide resource injection in a JSR 250 compliant way without using EJBS.

  Four, security

In addition to resource injection, JSR 250 and EJB 3.0 also provide metadata security representations through annotations. The Javax.annotation.security package defines five annotations-runas,rolesallowed,permitall,denyall and rolesreferenced-all of which can be applied to methods to define security requirements. For example, if you want to declare that the Bookflight method listed above can only be performed for callers who have a "user" role, you can annotate this method with the following security constraints:

public class Travelagencyserviceimpl implements Itravelagencyservice
{
@Resource (name = "Flightdao")
Public Iflightdao Flightdao;
@RolesAllowed ("User")
public void Booktrip (long outboundflightid, long returnflightid, int seats)
Throws Insufficientseatsexception
{
Reserveseats (Outboundflightid, seats);
Reserveseats (Returnflightid, seats);
}
}


This annotation will indicate that the container is responsible for ensuring that only callers of the specified role can execute this method. So now I'm going to show you another simple aspect-it will further strengthen the security constraints on the application:

@Aspect
public class Securityaspect
{
@Around ("Execution (@javax. annotation.security.RolesAllowed * *.* (..))")
Public Object aroundsecuredmethods (Proceedingjoinpoint thisjoinpoint)
Throws Throwable
{
Boolean callerauthorized = false;
rolesallowed rolesallowed = Rolesallowedforjoinpoint (thisjoinpoint);
For (String Role:rolesAllowed.value ())
{
if (callerinrole (role))
{callerauthorized = true;}
}
if (callerauthorized)
{return thisjoinpoint.proceed ();}
Else
{
throw new RuntimeException ("Caller not authorized to perform specified function");
}
}
Private rolesallowed Rolesallowedforjoinpoint (Proceedingjoinpoint thisjoinpoint)
{
Methodsignature methodsignature = (methodsignature) thisjoinpoint.getsignature ();
Method Targetmethod = Methodsignature.getmethod ();
Return targetmethod.getannotation (Rolesallowed.class);
}
Private Boolean Callerinrole (String role)
{ ... }
}


This aspect includes the execution of all methods-by verifying that the caller is one of the roles specified in the annotation, annotating with a @rolesallowed annotation and ensuring that the caller is authorized to invoke the method. Of course, you can also substitute any algorithm you like to authorize the user and retrieve his/her role, such as Jaas or a custom solution. For convenience, I chose to delegate to the servlet container for the purposes of this sample program.

Five, transaction

transactions become an important part of enterprise development-because they facilitate data integration in a concurrent environment. At a high level, transactions can be guaranteed through a variety of, or complete, or incomplete operations.

is not a comment on resource injection and security, and annotations for transactions are specific to EJB 3.0 and are not defined in the JSR 250 common note. EJB 3.0 defines two annotations associated with a transaction: Transactionmanagement and TransactionAttribute. The TransactionManager note Specifies whether the transaction is managed by the container or by the bean. In EJB 3, if this annotation is not specified, then the transaction managed by the container will be used. The TransactionAttribute annotation is used to specify the transaction propagation level of the method. Valid values-include mandatory, required, new, supported, unsupported, and never supported-used to define whether an existing transaction is required or to start a new transaction, and so on.

Because the bookflight operation contains two steps-order an outgoing flight and a return flight, so by wrapping it into a transaction, you can guarantee the consistency of the operation. By using the EJB 3.0 transaction annotation, this will look like this:

public class Travelagencyserviceimpl implements Itravelagencyservice
{
@Resource (name = "Flightdao")
Public Iflightdao Flightdao;
@RolesAllowed ("User")
@TransactionAttribute (transactionattributetype.required)
public void Booktrip (long outboundflightid, long returnflightid, int seats)
Throws Insufficientseatsexception
{
Reserveseats (Outboundflightid, seats);
Reserveseats (Returnflightid, seats);
}
}


And you can apply a simple aspect to automatically define the transaction boundary:

@Aspect
public class Transactionaspect
{
@Pointcut ("Execution (@javax. Ejb.transactionattribute * *.* (..))")
public void Transactionalmethods () {}
@Before ("Transactionalmethods ()")
public void Beforetransactionalmethods ()
{hibernateutil.begintransaction ();}
@AfterReturning ("Transactionalmethods ()")
public void Afterreturningtransactionalmethods ()
{hibernateutil.committransaction ();}
@AfterThrowing ("Transactionalmethods ()")
public void Afterthrowingtransactionalmethods ()
{hibernateutil.rollbacktransaction ();}
}


This implementation is based on the assumption that-hibernate and ubiquitous thread-local patterns are used to manage Hibernate session and transaction objects, but any other appropriate implementation, such as JTA based implementations, can be used instead.

   Vi. Summary

By using the EJB 3.0 and JSR 250 annotation sets, this article has demonstrated how cross-cutting concerns such as resource management, security, and transactions are implemented. Of course, there are a lot of things we need to learn further. The first thing to learn is to provide the blueprint for modular crosscutting concerns by using ASPECTJ implementations of these examples. Second, we have seen some new ideas and new concepts behind the EJB 3.0 statement that is now surfacing. Finally, we see in a dramatic way the freedom that must be provided to decouple our business objects from the EJB API. At this point, all you want to make Travelagencyserviceimpl a stateless session is simply to add a final note:

@Stateful
public class Travelagencyserviceimpl implements Itravelagencyservice
{ ... }


Finally, I very much hope that this way of providing business services freely will bring about competition and innovation in the framework/container industry.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.