JAC is still beta software
released for developers who know what they are doing. It is
developed and tested under Linux and should work out of the box
on any Unix-like system. It should be very easy to make it run on
Windows by using the furnished scripts/jac.bat script
(however, the compilation scripts should be ported).
To use JAC, download a JAC release at the downloads section. JAC uses several libraries that you can find on the Internet.
Simple installation: you can simply download the JAC version with libraries included (since version 4.1). With this choice, the JAC installation is easier and you do not need to install all the following (except JDK1.3).
Complex installation: download the JAC version with no libraries included and install the following libraries separatly from JAC.
and to compile JAC:
Once you have installed all you need, install JAC and initialize the environment:
cd <work_dir> tar zxf jac.xxx.tar.gz
scripts/init_env and then source it in the root
directory of the distribution:
source scripts/init_env [JAC_ROOT directory]
WARNING: under Windows, the
scripts/init_env script will not work. You
should use the scripts/jac.bat script that sets
the class path. This script assumes that you installed JAC
in C:\jac. If you installed it somewhere else,
you should edit jac.bat and change the
definition of JAC_ROOT and
CLASSPATH.
Make.rules if
needed (for instance if you want to use javac instead of jikes),
and run make:
make
You should have performed all the needed steps described in the Installation of JAC section. Here is a quick reminder in case your samples do not work.
Each sample has a makefile in its directory that is automatically generated by the global make. If you compiled JAC, normally the samples are already compiled.
Note: to know if a sample needs the persistence aspect, go
in the sample directory and see if its contains
persistence.acc file (i.e. a configuration file
for persistence). However, if you do not want to use
persistence at a first try, edit the .jac file of the
sample, remove the line that adds the persistence aspect to
the application (or switch the last parameter to false) and
compile again the sample. The sample will then run in a
transient mode (all the modifications you make on the objects
will be forgotten if you restart the program).
Two kinds of storage are available : filesystem and SQL. The filesystem storage allows you to store objects in plain files on your local filesystem. SQL storages allow you to store objects in an SQL database. Only Postgresql is supported for the moment, but adding other databases is very easy.
All you need to do is to specify a directory where object files will stored in the persistence.acc :
configureStorage jac.aspects.persistence.FSStorage {
"<directory>" };
The directory does not need to exist. It will be created if it does not exist.
The src/jac/aspects/persistence/createdb.sql
script creates the tables needed by the aspect (note
that you need to have postgresql and a fully installed account
that allows you to create databases in order to perform this
step):
createdb photo psql photo < createdb.sql
Customize the configureStorage line in persistence.acc. The syntax is:
configureStorage <storage_class> {
"<db_name>", "<db_user>", "<db_password>" };
Since Postgresql is the only supported database for the moment,
<storage_class> is
jac.aspects.persistence.PostgresStorage. Note that
if you change the sample program structure, the database may become
inconsistent with the application.
In any directory, run jac with the *.jac file path as a last argument.
jac -G default src/jac/samples/photos/photos.jac
It will launch JAC and the photos sample class with the Swing
GUI (-G option). The default parameter after the
-G is the name of the window to display. For more
details about starting
options
If the sample can run in a distributed mode (see the
*.jac or if a deployment.acc file
exists to know that), then you will need other JAC containers to
be started elsewhere depending on how the deployment aspect is
configured (see or modify the deployment.acc file
of the sample). To allow the distribution aspect to work:
jac -D serverName(the final server name is
//hostname/serverName where
hostname is the TCP/IP name of the host the
server is launched on and serverName is the given
name). For more details about starting options.go script that launches as
many servers as you need and automatically names them
(go N launches //hostname/s1, //hostname/s2, ... //hostname/sN)topology property is defined in the
application descriptor file (*.jac) of the sample.
Modify it so that it defines all the servers that you have
launched in the previous step.deployment.acc file exists in the
sample's directory and that the deployment rules it defines
correspond to the names of the servers you have launched
(check the available aspects
for distribution). Check also that the *.jac
file declares the deployment aspect.jac -G -D
src/jac/samples/ring/ring.jac. Note that a JAC server
is then created for deployment and is named
//localhost/s0. This deployment server is used by
the other servers as the global aspects configurations
server.Then, just launch the application with the -W
option:
jac -W default calcul.jac
In order to view an object with your browser, you just have to
enter the following URL:
http://localhost:8080/jac/default.
You can then perform any action you could perform with the swing GUI.
Once you are ok with the JAC installation and environment, let us enter into details on how to program a sample application with JAC. We choose the calcul sample since it is a very simple one (available in the latest JAC distributions).
This tutorial allows you to go through JAC programming step by step and in a very progressive way. For more general overview on the JAC's programming philosophy, see the JAC Programmer's Guide.
The base application is the functionnal or core-business
application. In other words, it is the simpliest expression of
your functionnal needs. Here, we would like to have a class that
performs some simple calculi. Wherever you want, create a new
directory calcul and, inside of it, a file called
Calcul.java. The code is the following:
// Calcul.java file
// A simple component definition that can perform
// add and sub operations...
public class Calcul {
protected float value = 0;
public void add(float toadd) {
value+=toadd;
}
public void sub(float tosub) {
value-=tosub;
}
// IMPORTANT: in JAC, each instance-field better have
// a getter of the form getFieldName.
public float getValue() {
return value;
}
// IMPORTANT: in JAC, each instance-field better have
// a setter of the form setFieldName.
public void setValue(float value) {
this.value=value;
}
}
Note that the need of the getters and setters comes from the aspects that will use them later-on.
In JAC, any application must have a program descriptor that we put in a *.jac file. This file declares the new application and the supported aspects to the JAC system.
// calcul.jac file applicationName: calcul launchingClass: Run
The launching class is a regular class that contains a static
main method.
// Run.java file
// The launching-class definition
public class Run {
// Program entry-point
public static void main( String[] args ) {
// Actually launch the calcul program by creating an
// instance of the Calcul class that waits to be used...
Calcul myCalcul = new Calcul();
}
}
Compile these files like you are used to doing in Java
(*.jac and *.acc files do not need to
be compiled).
When compiled, run the JAC server and indicate to launch the calcul
sample. Note that all the classpath issues in Java are also
present in JAC -- thus, you can add the calcul directory to the
classpath (note that *.acc files are also fetched
using the classpath, for this reason, you should beware of
conflicts when modifying the classpath). Into the calcul
directory (where Calcul.class and
Run.class should be found), just run (assuming that
$JAC_ROOT/scripts/jac is in your path):
jac -G default calcul.jac
Because of the -G option, the Swing GUI is launched
and the instance of the class Calcul should appear
in the window. The resulting screen should be:
As you can see on the right-side, the calcul
instance is being introspected by the default GUI aspect of JAC
that offers a default view on it. It shows the fields of the
calcul0 object (here value, and the
methods that can be called on the object (the two buttons
add and sub)). The pencil-like button on
the right of the field means that you can edit the field value by
calling the field's setter. Click on it to change the value of the
value field. The following box pops-up. Fill the new
value:
When you click OK, you can notice that the view is
automatically refreshed. Indeed, thanks to bytecode analysis,
JAC knows that setValue is a setter for the
value field. Thus the MVC (Model-View-Controller)
underlying framework of the GUI aspect refreshes the view.
Let us now try the add button. If you fill the box,
you can notice that nothing happens. However, if you force the
refreshment by clicking right on the calcul0 object
(View menu item), then you can see that the
add action was actually performed.
Moreover, if you look at the input boxes, the used labels are not
very clear such as: arg0 (float). To make this more
user-friendly, the programmer can configure the GUI (Graphical
User Interface) aspect to name the parameters of a given method.
jac.core.rtti is a core aspect that allows the programmer to define extra type information that will be used by other aspects at runtime.
For instance, it can be very useful for other aspects to be
aware that a given method modify the object's state. To declare
this, you just need to write an Aspect-Component Configuration file
(an ACC file) and call the right method on the RTTI aspect. In
your calcul directory, create a file rtti.acc:
// Declares that the "add" method of the "Calcul" class
// modifies the "value" field
addWrittenFields Calcul add {"value"};
// Declares that the "sub" method of the "Calcul" class
// modifies the "value" field
addWrittenFields Calcul sub {"value"};
The GUI aspect allows the programmer to define some presentation information, and to parameterize the interactions between the application objects and the user. For instance, by configuring a personal GUI aspect, a programmer can define the names of the method parameters as they will be displayed by a GUI.
For our example, create a gui.acc file:
// Generates the parameters names for all the setters of
// the "Calcul" class
generateDefaultParameterNames Calcul;
// Sets the actual text for each parameter of the "add"
// method
setParameterNames Calcul add {"Value to add"};
// Sets the actual text for each parameter of the "sub"
// method
setParameterNames Calcul sub {"Value to sub"};
Once you have created you ACC files, you must declare them to the
application by modifying the calcul.jac file as
following:
// calcul.jac file applicationName: calcul launchingClass: Run aspects: \ rtti mydirectory/rtti.acc true \ gui mydirectory/gui.acc true
Note that you can put the directory of the *.acc files in
your class path so that you can launch the application from any
directory (however, you should be very careful that it does not
conflict with other ACC files of other applications).
As shown on this screenshot, the left-lower-part of the JAC window
shows that two aspects are available for the calcul application
(rtti and gui). The checkboxes show
that they are woven (activated). And, the add input
box contains a user-friendly text.
All this configuration works also with the WEB. If you launch JAC
with the WEB-GUI server (RMI must be configured and a servlet
engine running and configured to access JacServlet):
jac -W calcul.jac
Then, from the WEB:
Other aspects are available and can be configured using the same process that the one depicted for the RTTI and GUI aspects.
Some other useful aspects to configure are:
NOTE: This tutorial will be soon completed with other aspect configurations and programming. For the moment, you can follow the same rules to configure other aspects (see the furnished samples) and you can refer to the JAC Programmer's Guide and to the JAC API documentation for further details.
JAC provides full support for distributed AOP. This means two things:
jac.aspects.distribution packageBasically, the deployment aspect provides a set of deployment rules that the programmer can use to deploy its application over a set of containers.
If we take again the calcul example, you may intend to launch JAC
in a distributed mode where a set of clients will access to one
unique instance of calcul (here, calcul0) located
on a server host.
To allow this, first modify the application descriptor to tell that the application knows a set of two other containers, and activate the deployment aspect.
// calcul.jac file
applicationName: calcul
launchingClass: Run
aspects: \
rtti mydirectory/rtti.acc true \
gui mydirectory/gui.acc true \
deployment mydirectory/deployment.acc true
topology: //localhost/s1 //localhost/s2
This means that, including the master host (called
//localhost/s0), your JAC system will contain three
local sites s0, s1, s2. If you want to locate
calcul0 on s1, just write an ACC file,
deployment.acc:
// deploy the calcul0 object from s0 to s1 deploy ".*s0" "calcul0" ".*s1"; // create stubs to access calcul0 on s0 and s2 createStubsFor "calcul0" ".*1" ".*0 || .*2";
Then start 2 JAC servers (if an error occurs, check section Run the sample in distributed mode).
go 2
Then start the application in a distributed mode (this starts the
master server) -- do not forget to move into the
calcul directory if needed:
jac -G -D calcul.jac
If everything goes okay, you should be able to perform remote call
from s0 and s2 to
calcul0 on s1. To check this, you can
launch remote GUIs on s1 and s2 from
the master GUI by using the menu: System -->
Containers and by selecting the remote container you need
to start a GUI on, and by clicking the "Launch remote
GUI" button.
What is revolutionary with JAC is the ability to change the way the
application is distributed without having to change the
application's code or even to restart the servers (this is one
of the benefits of our Dynamic and Distributed Aspect-Oriented
Framework). For instance, if you finally want to say that
calcul0 is replicated on all the sites of the
topology and in strong consistency, then you can change the
deployment file:
// replicate the calcul0 object from s0 to all replicate ".*s0" "calcul0" ".*";
And add a consistency protocol by configuring the consistency aspect (you must declare it in
your .jac file).
addStrongPushConsistency "calcul0" MODIFIERS ".*";
The replicated-strong protocol maintains the replicas in a
consistency called strong, i.e. as soon as a modification
occurs on one site, all the replicas on the other sites are
modified the same way (the last two parameters indicate that the
methods that modify the object state
--MODIFIERS-- are pushed to the other
replicas). To better understand how it works, you can play with
this rule and change the MODIFIER argument into
"setValue(float):void || add(float):void" to not
push the modifications when the sub method is
called (in our case, MODIFIERS equals to
"setValue(float):void || add(float):void ||
sub(float):void") (for more details about pointcut
expressions that are allowed when denoting methods sets, see the
MethodPointcut class.
To apply this rule at runtime, you must declare the consistency
aspect in your .jac class. Then you can (un)weave
aspects at runtime. To (un)weave an aspect, (un)check the checkbox that
corresponds to the aspect in the
Aspects lower-left subwindow of the master host's
GUI. You can replace an aspect configuration by modifying and
saving the ACC file, unckecking the
checkbox, then, when the unweaving is finished, check
the checkbox again to activate the new configuration.
Once you have fully understood how it works, you are ready to play
with more advanced features. For instance, you can use the
load-balancing aspect (see
jac.distribution.aspects.LoadBalancingAC) to increase the
load capability of your applications. For instance you can
program a load-balanced calculator only by slightly changing the
distribution aspects, and by adding a new ACC
(load-balancing.acc):
// deployment.acc replicate ".*s0" "calcul0" ".*";
// consistency.acc addStrongPushConsistency "calcul0" "MODIFIERS" ".*[1-2]";
// load-balancing.acc addRoundTripLoadBalancer "calcul0" ".*s0" ".*[1-2]";
With these three configurations, the calcul instance of
s0 is a load-balancer that performs a rountrip
load-balancing algorithm to dispatch on s1 and
s2.
With the JAC software, we furnish a bunch of useful aspects that can be advantagely used to program distributed applications. However, since JAC is a young project and that we cannot think in advance of all the possible uses you can make out of such a software, most of the aspects we provide may lack useful configuration method or may not work fine for specific usages.
Here is a uncomplete list of the aspects that can be provided to create more specific applications:
Moreover, existing aspects need extensions to be complete. For instance:
As an example, we next show how to add a simple fault-tolerence support to the load-balancing aspect provided in the JAC distribution (see jac.distribution.aspects.LoadBalancingAC).
Let us first recall the structuration of an aspect by showing
the code for an aspect that checks that the add or
sub method invocations on the calcul0
instance so that it raises an error if the added value is
greater than 100 or if the substracted value is greater than
50.
// MyCheckingAspect.java
// the aspect declaration:
class MyCheckingAspect extends AspectComponent {
// at instantiation-time, you should define the pointcuts
public MyCheckingAspect() {
// this pointcut will make the add method of calcul0
// wrapped by an instance of checkingWrapper (an
// inner wrapper of this aspect), and more specifically
// by the wrapping-method "checkAdd"
pointcut("calcul0","Calcul","add(float):void",
CheckingWrapper.class.getName(),"checkAdd",
false);
// same principles for sub...
pointcut("calcul0","Calcul","sub(float):void",
CheckingWrapper.class.getName(),"checkSub",
false);
}
// then define the wrappers (if you think that these
// wrappers can be used by other aspect, you can make
// them public within a standalone class-file)
public Class CheckingWrapper extends Wrapper() {
// see the programmer's guide for details on the
// wrapping methods semantics...
public Object checkAdd() throws Error {
if( ((Integer)args(0)).intVal()>100 ) {
throw new Error("bound excedeed when calling add!");
}
}
public Object checkSub() throws Error {
if( ((Integer)args(0)).intVal()>50 ) {
throw new Error("bound excedeed when calling sub!");
}
}
}
}
Note that this aspect is very specific since it can only be applied
to the calcul0 instance. To program generic
aspects, you may refer to the JAC programmer's
Guide. Configuration methods are a first step towards
genericity since they allow the system to dynamically create the
pointcuts with the interpretation of the Aspect-Component
Configuration (ACC) files (*.acc).
In this case, you can parametrize the creation of the pointcuts
instead of hardcoding them in the aspect-component
constructor. For instance, the following two files have exactly
the same effect than the previous hardcoded aspect-component
except that a simple change of the object's name in the
configuration file allows the user of this aspect component to
make it work on other instances of the Calcul
class.
// MyCheckingAspect.java:
class MyCheckingAC extends AspectComponent {
// at configuration-time (just after the instantiation),
// this configuration method can be called to define the
// pointcuts
public void checkCalcul(String name) {
// this pointcut will make the add method of the
// instance named "name" wrapped
pointcut(name,"Calcul","add(float):void",
CheckingWrapper.class.getName(),"checkAdd",
false);
// same principles for sub...
pointcut(name,"Calcul","sub(float):void",
CheckingWrapper.class.getName(),"checkSub",
false);
}
// then, same as the hardcoded aspect...
Class CheckingWrapper extends Wrapper() {
(...)
}
}
// my-checking.acc: checkCalcul "calcul0";
NOTE: to be able to use and declare your new aspect
component in *.jac file, you should first declare
them in the global jac.prop file located in
$JAC_ROOT (see the jac.acs property).
The load-balancing aspect used in section Using AOP to program distributed applications follows the same structuration rules:
package jac.aspects.distribution;
import jac.core.*;
import jac.core.dist.*;
import gnu.regexp.*;
import java.util.*;
/**
* This Aspect Component allows the programmer to easily implement
* load-balancing features for its application when JAC is running in
* distributed mode.
*
* @author Renaud Pawlak
* @version 0.5.2 */
public class LoadBalancingAC extends AspectComponent {
/**
* This configuration method allows the user to define a round-trip
* load-balancer on a replication group.
*
* It assumes that a replication group exists on a set of host
* denoted by replicaExpr. It also assumes that an
* uncorrelated replica called wrappeeName exists on
* hostName. Note that this distributed scheme can be
* easilly obtained by configuring the deployment aspect for an
* object myObject like this:
*
* replicated "myObject" ".*[1-6]";
*
* This means that myObject is replicated on all
* the hosts one to six and that the replicas are strongly
* consistent. Then, you can configure the load-balancing:
*
* addRoundTripLoadBalancer "photorepository0" ".*" "s0" ".*[1-6]";
*
* Note that the round-trip balancer (located on s0) changes the
* replica it uses for each invocation. The followed sequence is
* 1,2,3,4,5,6,1,2,3,4,5,6,1,...
*
* An alternative to the round-trip load-balancer is the random
* load-balancer that randomly picks out the next replica to
* use. This can be useful when a total decoralation is needed for
* all clients.
*
* @param wrappeeName the name of the object that is replicated and
* that will act as a load-balancer proxy
* @param methods a pointcut expression for the method that perform
* the load-balancing (others perform local calls)
* @param hostName the host where the proxy load-balances
* @param replicaExpr a regular expression that matches all the
* hosts of the topology where the replicas are located
*
* @see #addRandomLoadBalancer(String,String,String,String) */
public void addRoundTripLoadBalancer( String wrappeeName,
String methods,
String hostName,
String replicaExpr ) {
pointcut( wrappeeName, ".*", methods,
new LoadBalancingWrapper( replicaExpr ),
"roundTripBalance", hostName );
}
/**
* This configuration method allows the user to define a random
* load-balancer on a replication group.
*
* It follows the same principles as a round-trip balancer but
* picks up the next replica to use randomly.
*
* @see #addRoundTripLoadBalancer(String,String,String,String) */
public void addRandomLoadBalancer( String wrappeeName,
String methods,
String hostName,
String replicaExpr ) {
pointcut( wrappeeName, ".*", methods,
new LoadBalancingWrapper( replicaExpr ),
"randomBalance", hostName );
}
/**
* This inner-wrapper handles the load-balancing wrapping methods that
* actually implement the load-balancing algorithms. */
public class LoadBalancingWrapper extends Wrapper {
int count = 0;
Vector replicas = null;
Random random = new Random();
String hostExpr;
boolean doFill = true;
public LoadBalancingWrapper( String hostExpr ) {
this.hostExpr = hostExpr;
}
public void invalidate() {
doFill = true;
}
/**
* Performs a round-trip load-balancing. */
public Object roundTripBalance() {
if( doFill ) {
replicas = Topology.getPartialTopology(hostExpr)
.getReplicas( this.wrappee() );
}
if( replicas.size() == 0 ) {
// none replicas where found, we perform a local call and
// will try to get them again on the next call
doFill = false;
return proceed();
}
if( count >= replicas.size() ) {
count = 0;
}
return ((RemoteRef)replicas.get(count++)).invoke(this.method(),this.args());
}
/**
* Performs a random load-balancing. */
public Object randomBalance() {
if( doFill ) {
replicas = Topology.getPartialTopology(hostExpr)
.getReplicas( this.wrappee() );
}
if( replicas.size() == 0 ) {
// none replicas where found, we perform a local call and
// will try to get them again on the next call
doFill = false;
return proceed();
}
return ((RemoteRef)replicas.get(random.nextInt(replicas.size())))
.invoke(this.method(),this.args());
}
}
}
In the latest distributions, JAC provides an IDE that supports UML-like and UML for aspects so that it greatly simplifies the programmer's task.
Before actually using the IDE, make sure that the JAC distribution is correctly installed and configured as depicted in the tutorial.
The IDE aspects should be correctly configured for your
environment, practically, you should edit the
$JAC_ROOT/src/jac/ide/persistence.acc file to define a
target directory for the storage:
configureStorage jac.aspects.persistence.FSStorage {
"your_path"};
This IDE 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).
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 (however, this IDE could be easily extended to support these if needed).
Make sure that JAC is correctly installed and launch the
application descriptor located in jac/src/jac/ide:
jac $JAC_ROOT/src/jac/ide/ide.jac
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 treatements 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 the 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" 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 open 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
new class should appear with a default name (NewClass). You can
modify its name by using the "Text tool" (
) button and click
on the title or by using the lower-left sub-panel. Just call it
"Invoices". This class represents a container for a set of
invoices.
Now create in the same way an "Invoice" class. You can add an
attribute by using the "Add attribute" button (
) of the
toolbar. Using the text tool, you can edit this attribute. You
MUST follow the conventions in the attribute definition,
i.e. attribute_name:attribute_type. The available types
are the classes that are already created and all the builtin
types (see in the main menu: Tools --> Type
repository). Just set the attribute to
"amount:double". With the same process, create an attribute
"date:Date".
You can now create another class "Client" with an attribute "name:String".
We can now relate the three classes together. Use the "New
relation" button (
). Press the left button down on the "Invoices"
class and, without releasing, move to the "Invoice" class and
let the button up. A new relation link should be created with
its default roles, names, and cardinalities. You can edit them
on the diagram using the text tool, or in the lower-right
sup-panel. Set the end cardinality to "0-*". Do the same to
create a relation between "Invoice" and "Client" set the start
cardinality to "0-*".
Please, also set the role names as shown in the following screenshot.
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" for instance. You can
also program the launching code of the program (this code
corresponds to the static void main(String[] args)
method that is used as an entry point for the Java program).
In JAC, the idea of a lauching code is to create 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). Thus, in the launching code editor, type the line:
new 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 code" and the "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 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 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.
First create an RTTI aspect (choose rtti for the aspect name and leave the aspect blank --- this is used when a personnal aspect is created in the IDE). As shown on the screenshot, the configuration should simply include the default system rtti that is useful for the GUI.
Then, create and configure the GUI aspect as shown in the following screenshoot.
Before starting, ensure that the code generation is ok by right-click on the project's node and "Generate code"+"Compile".
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).
Ensure that GEN_DIR/classes is in your
classpath.
Launch JAC with the application's desciptor that was automatically generated.
jac GEN_DIR/myFirstApplication/myFirstApplication.jac
The JAC's IDE 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 the IDE, the programmer can also create entirely new aspects despite it is not documented yet.