AOP (Aspect Oriented Programming)
introduces a new way for reusing code. In fact aspects complement some
shortcomings in traditional Object Oriented Programming.
Which problems does AOP resolve? Sometime you have a functionality that is
common to a group of classes but using inheritance is not practical (in
Java we only have single inheritance) or not ethical (because there isn't
a is-a relationship). Moreover the system may be already written, or maybe
you need to include or not this functionality on demand. AOP is an easy
way to resolve these problems.
What is an aspect? An aspect is a bunch of code that can be scattered as
you wish in your application.
The Java language has a complete AOP support by means of the AspectJ
project.
OpenXava adds some support for the aspects concept since version 1.2.1.The
support for aspects in XML component is small, but if you use POJOs +
annotations (since version 3.0) you can use
AspectJ and enjoy the full strength of aspects.
Aspects
definition
The
aspects.xml file inside the xava folder of your project is
used to define aspects.
The file syntax is:
<aspects>
<aspect ... /> ... <!-- 1 -->
<apply ... /> ... <!-- 2 -->
</aspects>
- aspect (several, optional): To define aspects.
- apply (several, optional): To apply the defined
aspects to the selected models.
With aspect (1) you can define an aspect (that is a group of features)
with a name, and using apply (2) you achieve that a set of models
(entities or aggregates) will have these features automatically.
Let's see the aspect syntax:
<aspect
name="name" <!-- 1 -->
>
<postcreate-calculator .../> ... <!-- 2 -->
<postload-calculator .../> ... <!-- 3 -->
<postmodify-calculator .../> ... <!-- 4 -->
<preremove-calculator .../> ... <!-- 5 -->
</aspect>
- name (required): Name for this aspect. It must be
unique.
- postcreate-calculator (several, optional): All
model with this aspect will have this postcreate-calculator
implicitly.
- postload-calculator (several, optional): All model
with this aspect will have this postload-calculator
implicitly.
- postmodify-calculator (several, optional): All
model with this aspect will have this postmodify-calculator
implicitly.
- preremove-calculator (several, optional): All model
with this aspect will have this preremove-calculator
implicitly.
Furthermore, you need to assign the defined aspects to your models. The
syntax to do that is:
<apply
aspect="aspect" <!-- 1 -->
for-models="models" <!-- 2 -->
except-for-models="models" <!-- 3 -->
/>
- aspect (required): The name of the aspect that you
want to apply.
- for-models (optional): A comma separated list of
models to which the aspect is applied to. It's mutually exclusive with
except-for-models attribute.
- except-for-models (optional): A comma separated
list of models to be excluded when apply this aspect. In this case the
aspect applies to all models excepts the indicated ones. It's mutually
exclusive with for-models attribute.
If you use neither
for-models nor
except-for-models,
then the aspect will apply to all models in the application. Models are
the names of components (for its entities) or aggregates.
A simple example may be:
<aspect name="MyAspect">
<postcreate-calculator
class="com.mycompany.myapplication.calculators.MyCalculator"/>
</aspect>
<apply aspect="MyAspect"/>
Whenever a new object is created (saved in database for the first time),
then the logic of
MyCalculator is executed. And this for all
models.
At the moment only these few calculators are supported. We expect to
extend the power of aspects for OpenXava in the future. Anyway the
existing calculators offer interesting possibilities. Let's see an example
in the next section.
AccessTracking:
A practical application of aspects
The current OpenXava distribution includes the
AccessTracking
project. This project defines an aspect that allows you to track all
access to the data in your application. Actually, this project allows your
application to comply the Spanish Data Protection Law (Ley de Protección
de Datos) including high level security data. Although it's generic enough
to be useful in a broad variety of scenarios.
The
aspect definition
You can find the aspect definition in
AccessTracking/xava/aspects.xml:
<?xml version = "1.0" encoding = "ISO-8859-1"?>
<!DOCTYPE aspects SYSTEM "dtds/aspects.dtd">
<!-- AccessTracking -->
<aspects>
<aspect name="AccessTracking">
<postcreate-calculator
class="org.openxava.tracking.AccessTrackingCalculator">
<set property="accessType" value="Create"/>
</postcreate-calculator>
<postload-calculator
class="org.openxava.tracking.AccessTrackingCalculator">
<set property="accessType" value="Read"/>
</postload-calculator>
<postmodify-calculator
class="org.openxava.tracking.AccessTrackingCalculator">
<set property="accessType" value="Update"/>
</postmodify-calculator>
<preremove-calculator
class="org.openxava.tracking.AccessTrackingCalculator">
<set property="accessType" value="Delete"/>
</preremove-calculator>
</aspect>
</aspects>
When you apply this aspect to your components, then the code of
AccessTrackingCalculator
is executed each time a object is created, loaded, modified or removed.
AccessTrackingCalculator
writes a record into a database table with information about the access.
In order to apply this aspect you need to write your
aspects.xml
like this:
<?xml version = "1.0" encoding = "ISO-8859-1"?>
<!DOCTYPE aspects SYSTEM "dtds/aspects.dtd">
<aspects>
<apply aspect="AccessTracking" for-models="Warehouse, Invoice"/>
</aspects>
In this way this aspect is applied to
Warehouse and Invoice. All
access to these entities will be record in a database table.
Setup
AccessTracking
If you want to use the
AccessTracking aspect in your project you
have to follow the next setup steps:
- Add AccessTracking as referenced project: Inside Eclipse
click right button on your project and go to Properties > Java
Build Path > Projects.
- Create the table in your database to store the tracking of accesses.
You can find the CREATE TABLEs in AccessTracking/data/access-tracking-db.script
file.
- You have to include the hibernate.dialect property in your
configuration files. You can see examples of this in OpenXavaTest/jboss-hypersonic.properties
and other OpenXavaTest/xxx.properties files.
- Inside the AccessTracking project you need to select a configuration
(editing build.xml) and regenerate hibernate code (using the ant
target generateHibernate) for AccessTracking
project.
- Edit the file of your project build/ejb/META-INF/MANIFEST.MF
to add the next jars into the classpath: ./lib/tracking.jar
./lib/ehcache.jar ./lib/antlr.jar ./lib/asm.jar
./lib/cglib.jar ./lib/hibernate3.jar ./lib/dom4j.jar
./lib/slf4j-api.jar ./lib/slf4j-jdk14.jar ./lib/javassist.jar.This
step isn't needed if you use only POJOs, not EJB CMP2, new in v2.0.
The slf4j-api.jar, slf4j-jdk14.jar and javassist.jar
jars are only needed since v3.1.
Also you need to modify the target
createEJBJars (only if you
are using EJB2 CMP) and
deployWar of your
build.xml in
this way:
<target name="createEJBJars"> <!-- 'createEJBJars' only if you use EJB2 CMP -->
...
<ant antfile="../AccessTracking/build.xml" target="createEJBTracker"/>
</target>
<target name="deployWar">
<ant antfile="../AccessTracking/build.xml" target="createTracker"/>
...
</target>
After these steps, you have to apply the aspect in your application.
Create a file in your project
xava/aspects.xml:
<?xml version = "1.0" encoding = "ISO-8859-1"?>
<!DOCTYPE aspects SYSTEM "dtds/aspects.dtd">
<aspects>
<apply aspect="AccessTracking"/>
</aspects>
Now you only have to deploy the war for your project.
(new in v2.0)
In the case that you are using EJB2 CMP you have to regenerate the code,
deploying EJB and deploying war for your project.
All access are recorded in a table with the name TRACKING.ACCESS. If you
want you can deploy the module web or the portlet of
AccessTracking
project in order to have a web application to browse the accesses.
For more details you can have a look at the
OpenXavaTest
project.