Continued from http://blog.kevinlee.io/2009/05/17/roo-so-cool-02/
Now, let's look at more interesting one that is the ROO generated source code!
As you can see, there are many AspectJ aspects in the com.springsource.vote.domain
package. So I'll firstly try to look at the Choice
class which is not an aspect.
Wow! Is that it? Without the annotations, it consists of only two lines of code in the class. Just two variable declarations.
So where are the others?
Check out the Choice_Roo_Entity
aspect.
It appears to be a persistent object class with a persistence manager which means it includes data access logic. This sounds like normal Active Record yet if you closer look at the code, it uses AspectJ's inter-type declaration to add more attributes and behaviours to the domain object Choice
.
@javax.persistence.Id
@javax.persistence.GeneratedValue(strategy = javax.persistence.GenerationType.AUTO)
@javax.persistence.Column(name = "id")
private java.lang.Long Choice.id;
This code above is declaring long type id variable to the type Choice to use as an identifier for OR mapping. Because it is declared as a private variable, it is impossible to access it inside the code of Choice but possible only inside this Choice_Roo_Entity
aspect.
What about the Choice_Roo_JavaBean
.
JavaBean (Aspect)
It has all the getters and setters for the Choice
class and again inter-type declaration is used for adding these accessor methods. So an instance of Choice type cannot only behave as a persistent object but also as a JavaBean object. If you look into the jsp file, you can see it is used just like the methods belong to Choice
class. In order to access the variables inside Choice
object, the Choice_Roo_JavaBean
is defined as privileged
aspect.
privileged aspect Choice_Roo_JavaBean {
public java.lang.String Choice.getNamingChoice() {
return this.namingChoice;
}
public void Choice.setNamingChoice(java.lang.String namingChoice) {
this.namingChoice = namingChoice;
}
public java.lang.String Choice.getDescription() {
return this.description;
}
public void Choice.setDescription(java.lang.String description) {
this.description = description;
}
}
So as shown above, Choice_Roo_JavaBean
is a privileged aspect and therefore it can access namingChoice
and description
variables which are declared in Choice
.
So what is it? It is a mixin. Mixin is a class which provides a functionality to a subclass yet mixin itself is not supposed to stand alone. So a class can collect its functionality by inheriting from one or more mixins through multiple inheritance. However, as we all know, Java does not support multiple inheritance. So to use mixins in Java world, inter-type declarations in AspectJ can be used.
privileged aspect Choice_Roo_Entity {
(...)
@javax.persistence.Id
@javax.persistence.GeneratedValue(strategy = javax.persistence.GenerationType.AUTO)
@javax.persistence.Column(name = "id")
private java.lang.Long Choice.id;
(...)
public java.lang.Long Choice.getId() {
return this.id;
}
}
As seen in the aspect code above, a long type variable is added to the type Choice and a getId() method which returns a long type value that is the value in the variable, id, just added by the aspect. So an instance of Choice type can have getId() method even though it does not exist in the Choice class. Therefore, as mentioned, Choice type can have characteristics of both persistent object and JavaBean.
AspectJ is also used to declare Choice type as a configurable type.
Make Choice @Configurable
This code reveals that Choice
type has @org.springframework.beans.factory.annotation.Configurable
annotation.
privileged aspect Choice_Roo_Configurable {
declare @type: Choice: @org.springframework.beans.factory.annotation.Configurable;
}