JAC provides an IDE that supports UML-like editors so that it greatly simplifies the programmer's task. This IDE is called UMLAF for UML Aspectual Factory
UMLAF is entirely programmed with JAC itself. It is a good
example of what can be done using JAC. Sources of UMLAF are
located in src/org/objectweb/jac/ide of the sources tarball.
Using UMLAF to program with JAC is not mandatory. Since JAC is
a framework, JAC programs are written in pure Java (excepting the
*.acc files). Thus, your favorite IDE can be used
instead of UMLAF.
UMLAF is still in a beta version. The core model is quite stable and you should be able to read your projects with upcomming JAC releases, however, class diagrams could be lost.
The supported modeling language is a subset of UML (it only supports class diagram), plus a set of new concepts to model aspects (aspect classes, pointcut relations, and groups). These concepts should not be used for actual softwares since they are experimental (for the moment).
We claim that when using aspect-oriented technology, the whole UML language is not actually needed since the program is expressed with its simpliest core-business form. All the complexity related to implementation and design is handled in the provided aspects. As a consequence, you might be disapointed if you try to use this IDE whithin a regular development process on regular OO or CB technologies. In the future, other useful UML concepts (such as collaboration diagrams) will be implemented.
Refer to the installation guide to launch UMLAF.
When launched for the first time, the IDE appears as a window separated in 4 sub-panels. In the upper-left pannel, one can see a treeview that contains one single node called "projects". This sub-panel is the most important since it allows you to navigate in your projects and all the projects entities such as packages, diagrams, classes, or applications. The following list shows the hierachy of all the different entities manipulated by the IDE:
): An entity that represents a given project
(packages and applications).
): A package is a container for classes or
aspect classes. It can also contains subpackages if
needed.
): A child package (can have other
children).
): A class as defined in UML. In JAC, a
class should represent a purely fonctional component
dedicated to one precise task. It contains methods and
attributes and can be related to other classes through
relation links or inheritence links.
): An attribute is a data in a
class.
): A method defines a treatment that
can be perfomed on the instances of the owning
class.
): A relation link relates a
class to another class. In a method body, the ending
class can be reached by using the end role name.
): An aspect represents an aspect
component in JAC. An aspect should be used to model
crosscutting behaviors on a set of classes or
instances. It can be defined in the same way as a
class (attributes, methods, and relation links) but
can also use pointcut links.
): A pointcut link relates an
aspect to a class, an instance, or a set of
instances (a group). The end role of a pointcut
link defines a set of methods using a method pointcut definition. The start
role must be equal to a method name in the aspect
so that this method can wrap all the methods
denoted by the end role.
): This entity represent an instance
of a class (as defined in UML). An instance can be
defined by its name regarding the JAC naming
conventions (i.e. the lowercased class name followed
by the index of the instance regarding its creation
order).
): This entity represents a set of
instances denoted by two expressions: an object pointcut definition and a class pointcut definition. Groups allows
the user to define heterogenous sets of objects that
can be extended by an aspect if a pointcut link ends
to the group.
): A diagram is the graphical representation of
a set of package entities such as classes or aspects. It
roughly correspond to an UML class diagram but with some
features added and some other removed. The diagram is
consistent with the entities of packages.
): An application represents a launchable
piece of software. It defines a lauching code that should
instanciate one of the classe defined in one of the project's
packages. It also defines and configures the aspects that are
woven to the application when it is run.
): This entity represent the
configuration of a given aspect for a given application.Using the treeview is simple. You can double-click on a given node to open it. You can use the right-click to show the available treatments on the entity. For instance, to create a new project, just right-click on the "projects" node and choose the "Add project" item.
The upper-right panel is used to edit diagrams. Once you have created a package in your project (using right-click on the treeview), create a diagram in this package. The upper-right panel will show a diagram editor that allows you to create and edit the entities of the owning package.
The two lower panels are used to provide a Widget-based representation of the currently selected entity in a diagram. The left one shows classes, aspects, instances, or groups. The right one shows relation and pointcut links, attributes, or methods. These two panels can be used to edit the model elements without using a graphical diagram editor (which is sometimes useful to avoid using the mouse to much).
First create a new project using the right click on the "projects" node of the treeview. Call it "myProject" and choose a generation path (the directory where the Java code will be generated).
You then need to create a new package in your project to define the business classes. Right-click on "myProject" node and add a package that you can call "invoices".
Since it is nicer to model graphically, right-click on "invoices" in the treeview and add a new diagram. Call it "business" since it will represent the core-busines model of the application. A diagram editor component should then appear in the upper-right sub-panel.
Click on the "New class" button (
) of the diagram editor toolbar and then
click on the desktop where you want to locate the new class. A
popup should appear to enter the class' name. Note that you can
modify names later on by using the "Text tool" (
) button or by using
the other sub-panels. Just call the new class "Invoice". This
class represents an invoice. You can add an attribute by using
the "Add attribute" button (
) of the
toolbar or by right-clicking on the class in the tree view or in
the diagram. Set the name of the field to "amount" and its type
to "double".
Attributes can be read-only, which means that no method to set its value will be generated, or calculated which means to no real java field will be generated to store it value. A calulated field should usually be read-only.
With the same process, create an attribute named "date" of type "Date".
You can now create another class named "Customer" with an attribute named "name" of type "String".
We can now relate the two classes together. Use the "New
relation" button (
). Press the left button down on the "Invoice"
class and, without releasing, move to the "Customer" class and
then release the button. A new relation link is created
with its default roles, names, and cardinalities. You can edit
them on the diagram using the text tool, or in the lower-right
sub-panel after you have selected one in the diagram. Set the
start cardinality to "1" and the end cardinality to "0-*".
Set the role names as shown in the following screenshot.
We are now going to create a "repository" class to represent a set of invoices. Right-click on the invoices package in the treeview, select the "add repository" entry in the menu, and choose "invoices.Invoice" as the "Contained item class":
You can then use the "Add an existing class" button (
) in the
diagram toolbar to import the repository class into the
diagram: click on the button, then click in the diagram at the
place you want to import the class. A dialog box pops up. Select
the "invoices.Invoices" class, check the import "relation option"
and press "OK". Your diagram will look like that:
Repository classes are just like normal classes, except that
UMLAF will automatically generate some appropriate aspect
configuration for them. And an init() method is
generated to initialise a singleton static
field with a new instance.
As for any Java application, we need a main method
that will be executed we the application is started. So let's
right-click on the Invoices class and select "Add
main method". Click on the method in the diagram. A view of the
method will appear in the lower-right panel. Select the "body" tab
in this panel and type the following code:
Invoices.init();
With JAC, the main method usually creates the root
objects of the application that can be used to reach or create
other objects via collections (relation links with "0-*" end
cardinality) or references (relation links with "0-1" end
cardinality).
In this case, we only need to create an Invoices
instance since all the other objects are reachable from it
(regarding the model).
We are now ready to introduce the aspects!
Once the core business is modeled, you should create a new application to make a running JAC program.
Right-click on the "myProject" node and choose "Add application". Call it "myFirstApplication" and set its main class to "invoices.Invoices".
Note that the full name of the class is as expected the parent package path concated with the class name (this follows the Java conventions).
At this step, the application is ready to run. Validate and use the "Generate and Compile" commands by right-clicking on the "myProject" node. If something goes wrong, some error message(s) should appear in an errors dialog. If you do not figure out how to solve the problem, do not hesitate to contact us.
Since the application does not perform any treatment, it is not very interesting to launch it as is. Thus, we should add at least configure a GUI aspect so that the user of the application can create and manipulate the business objets.
The GUI aspect is one of the most useful aspect provided by JAC since it allows the programmer to configure how the business objects should be rendered and how the final user can interact with the application.
As any aspect in JAC, the GUI aspect provides a configuration interface GUIConf (extends ClassAppearenceGuiConf, FieldAppearenceGuiConf, MethodAppearenceGuiConf, and BehaviorGuiConf) that defines all the configuration methods that can be used during the configuration process. The programmer can refer these interfaces to know the available commands that can be used.
To add an aspect configuration to an application, right-click on the application node of the treeview and add a new aspect configuration.
An RTTI aspect configuration is automatically added when you create a new application. No configuration is required for the moment since the RTTI aspect automatically import a default configuration and UMLAF automatically generate some configuration based on the application's model that is sufficent for this application. To know more about RTTI and what can be configured in it, see RttiConf.
So let's, create and configure the GUI aspect as shown in the following screenshots.
For more details on aspect configurations and syntaxes.
setTableView invoices.Invoices invoices;
window myGUI {
registerCustomized;
setTitle "Invoices";
setSubPanesGeometry 2 HORIZONTAL {false,false};
setPaneContent 0 Object {"default","invoices#0"};
addReferenceToPane invoices.Invoices invoices 1;
setPosition 0 0 60 60;
setSplitterLocation 0 0.6;
}
setEmbeddedEditors; setAutoCreateAll;
Code in the "default configuration" tab will apply to all classes.
Before starting the application, you must ensure that the code generation for aspect configurations is ok by right-click on the application's node and "Generate code". And of course, if you changed something in the model or code, you must recompile as we explained earlier.
The application code and classes is then available in the generation directory (GEN_DIR) that you have choosen when you have created the project (you can change it by asking a view on the project).
We are now almost ready to start the application. We just need to configure a few options before we can do so. Right-click on the application and "View", then in the "Run options" tab, configure as below:
You can now right-click on the application and "start"! You will see a window as shown below:
Alternatively, you can start your application by hand with the application's desciptor that was automatically generated:
cd <jac_dir>
java -jar jac.jar -R .
-C GEN_DIR:GEN_DIR/classes
-G myGUI
GEN_DIR/myFirstApplication/myFirstApplication.jac
java -jar jac.jar -R .
-C "GEN_DIR;GEN_DIR\classes"
-G myGUI
"GEN_DIR\myFirstApplication\myFirstApplication.jac"
And set its start directory to <jac_dir>.
To stop the application, use the "stop" action in the application popup menu. Closing the window will not kill the process by default.
Since it would be nice to also have a list of all our
customers, lets create a relation from Invoices to
Customer. Make it navigable from
Invoices to Customer only, and make it
an aggregation:
Do not forget do generate the code of the project and compile it after you modified your model. You need only generate the code of the application if you change the configuration of an aspect.
We are now showing all the aspect configurations that are needed for the full application (exept the RTTI that is also needed at first place).
For details on configuration commands, see the entire configuration interface at GUIConf (extends ClassAppearenceGuiConf, FieldAppearenceGuiConf, MethodAppearenceGuiConf, and BehaviorGuiConf).
class invoices.Invoices {
setCategories {"Invoices","Customers"};
attribute invoices {
setTableView;
setCategory "Invoices";
setDisplayLabel false;
}
attribute customers {
setCategory "Customers";
setDisplayLabel false;
}
}
class invoices.Invoice {
setTableMembersOrder {amount,date};
setAttributesOrder {amount,date,customer};
}
class invoices.Customer {
setToString "%name%";
setAttributesOrder {name,invoices};
setTableView invoices;
}
window myGUI {
registerCustomized;
setTitle "Invoices";
setSubPanesGeometry 2 HORIZONTAL {false,false};
setPaneContent 0 Object {"default","invoices#0"};
addReferenceToPane invoices.Invoices invoices 1;
addReferenceToPane invoices.Invoices customers 1;
setPosition 0 0 60 60;
setSplitterLocation 0 0.6;
}
With this configuration, you can declare some data dependencies and some conditions on their values.
For details on configuration commands, see the entire configuration interface at IntegrityConf.
Associations need to be declared. This is done automatically when the code is generated for each relation, depending on its direction.
Add an aspect configuration named "integrity" to your application, and write the following code in the "Configuration" tab:
// Opposite roles of associations must be automatically updated updateAssociations; // Customers are automatically added to the repository collection declareRepository "invoices#0" invoices.Invoices.customers invoices.Invoice.customer; // Invoices are automatically added to the repository collection declareRepository "invoices#0" invoices.Invoices.invoices invoices.Customer.invoices; // add a condition addPostCondition invoices.Invoice amount org.objectweb.jac.aspects.integrity.GenericConditions.isGreaterThan {0} "The amount must be positive";
With this aspect, your datas are automatically made persistent.
For details on configuration commands, see the entire configuration interface at PersistenceConf.
Add a "persistence" aspect configuration to your application with the following configuration code:
// We use a file-system storage (path is from the root JAC dir) configureStorage org.objectweb.jac.aspects.persistence.FSStorage {"~/invoices"}; // All classes of package invoices must be persistent makePersistent invoices.* ALL;
"~/invoice" is the directory where the data will be
stored. The ~ refers to the user's home directory.
Regenerate the code for the application by right-clicking on the application in the tree view. You need not regenerate the java code for the classes nor recompile it: this is the power of aspect oriented programming.
The resulting application should look as following.
It works also on the WEB: you just need to use the "start web
GUI" and "Web GUIs" options in the "Run options" tab or replace the
-G option with -W in the command line
or windows shortcut.
You can then access your application at http://localhost:8088/jac/myGUI
UMLAF helps the programmer to design JAC applications and allows him to easily configure existing aspects (the ones that are provided by the JAC distribution). However, for the moment, the knowlege of the aspect configuration interfaces is still needed. In a short future, the IDE will provide some graphical customization means that will make the programmer task easier.
With UMLAF, the programmer can also create entirely new aspects despite it is not documented yet.