Warning

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/org.objectweb.jac.bat script (however, the compilation scripts should be ported).

Getting started

Installation of JAC

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:

  1. Extract the archive:
    cd <work_dir>
    tar zxf org.objectweb.jac.xxx.tar.gz
    
  2. Set environment variables. All the java libraries must be in your CLASSPATH, and JAC_ROOT must be set. You can customise 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/org.objectweb.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 org.objectweb.jac.bat and change the definition of JAC_ROOT and CLASSPATH.

  3. Since version 0.5.1, we distribute a jar file along with the sources, so this step is optional. So if you choose to compile the sources (should work fine under Linux, may need some adaptations under Windows), edit Make.rules if needed (for instance if you want to use javac instead of jikes), and run make:
    make
    

Running JAC samples

Requirements

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.

Compile the sample (Linux)

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.

Configure the persistence aspect (if needed by the sample)

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). 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.

By default, the samples use the filesystem storage and stores data files in a directory relative to JAC_ROOT

Configuring the filesystem storage

All you need to do is to specify a directory where object files will stored in the persistence.acc :

configureStorage org.objectweb.jac.aspects.persistence.FSStorage {
   "<directory>" };

The directory does not need to exist. It will be created if it does not exist.

Configuring the Postgresql storage

The src/org/objectweb/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 org.objectweb.jac.aspects.persistence.PostgresStorage. Note that if you change the sample program structure, the database may become inconsistent with the application.

Run the sample with JAC

In any directory, run jac with the *.jac file path as a last argument.

jac -G main src/org/objectweb/jac/samples/photos/photos.jac

It will launch JAC and the photos sample class with the Swing GUI (-G option). The main parameter after the -G is the name of the window to display. For more details about starting options.

Run the sample in distributed mode

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:

Using the web interface

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/org/objectweb/jac/default.

You can then perform any action you could perform with the swing GUI.

Programming the calcul sample

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.

Programming the base application

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;
   }

   // 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();
   }
}

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: Calcul

The launching class is a regular class that contains a static main method. For simplicity, we put the main() in the Calcul class.

Compile these files like you are used to doing in Java (*.jac and *.acc files do not need to be compiled).

javac Calcul.java

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 calcul.jac

Since no aspects are configured for the application, All you will see is this:

--- Launching Application calcul ---
JAC system shutdown: notifying all ACs...
Bye bye.

This is not very usefull, but is it prooves that JAC is working on your system.

Configuring the RTTI and GUI aspects

org.objectweb.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. Since JAC can detect that automatically, we do not need to add specific configurations for our sample application. All you need to do is create an empty file rtti.acc.

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:

// configuration for the Calcul class
class Calcul {
   // Show a button for each of these methods
   setMethodsOrder {add,sub};
   // Set the names of the parameters of add and sub methods
   setParameterNames add { "Value to add" };
   setParameterNames sub { "Value to sub" };
   // Set a default value for add
   setDefaultValues add { 1 };
}

// Says that all the methods of class Calcul can be called interactively
askForParameters "Calcul";

// The GUI main window configuration
window default {
   registerCustomized;
   setTitle "Calculator";

   // A real simple GUI
   setSubPanesGeometry 1 VERTICAL { false };
   // Display the object named "calcul0" in the panel "0" of the window.
   setPaneContent 0 Object { "calcul0" };
}

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: Calcul
aspects: \
  rtti rtti.acc true \
  gui gui.acc true

You can then launch the application with the following command:

jac -G default calcul.jac

And you should see a window like this:

The calcul sample main window

As you can see, the calcul instance is being introspected by the 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 Edit icon 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. Type a new value:

Edit box for value

When you click on 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:

Edit box for value

You will first notice that the default value to be added is "1". This is because of the setDefaultValues instruction in the gui.acc. When you click on OK, once again the view of the main window is automatically refreshed because JAC detected that the add method modifies the field value.

All this configuration works also with the WEB. If you launch JAC with the WEB-GUI server:

jac -W default calcul.jac

You will see the following output on the console:

--- Launching Application calcul ---
WARNING: Resource rtti.acc not found
13:34:52.863 EVENT  Starting Jetty/4.1
13:34:53.832 EVENT  Started HttpContext[/jac]
13:34:53.841 EVENT  Started HttpContext[/org/objectweb/jac/resources]
13:34:54.295 EVENT  Started SocketListener on 0.0.0.0:8088
13:34:54.306 EVENT  Started org.mortbay.http.HttpServer@100bac2
WARNING: Web server already started

Then, with you favorite web browser, go to http://localhost:8088/org/objectweb/jac/default:

The calcul sample screenshot

Configuring other aspects

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.

Using AOP to program distributed applications

JAC provides full support for distributed AOP. This means two things:

  1. the distribution of the application can be performed simply by configuring the aspects of the org.objectweb.jac.aspects.distribution package
  2. if you have cleany followed some basic programming rules, the functionnal program and the aspects it contains will be distributed without any problem or code reengineering

Basically, 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 org.objectweb.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.

Programming new aspects

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 org.objectweb.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.

// MyCheckingAC.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 org.objectweb.jac.prop file located in $JAC_ROOT (see the org.objectweb.jac.acs property).

The load-balancing aspect used in section Using AOP to program distributed applications follows the same structuration rules:

package org.objectweb.jac.aspects.distribution;

import org.objectweb.jac.core.*;
import org.objectweb.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());
      }
   }      
}

Using the IDE

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.

Requirements

Since the IDE is a JAC application, you must make sure that the JAC distribution is correctly installed and configured as depicted in the tutorial.

Warnings

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).

Getting started

Make sure that JAC is correctly installed and launch the application descriptor located in org/objectweb/jac/src/org/objectweb/jac/ide:

jac $JAC_ROOT/src/org/objectweb/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:

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).

Creating an application

Modeling the core business

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.

The JAC IDE

Click on the "New class" button (New class icon) 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" (Text tool icon) 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 (Add attribute icon) 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".

Classes are created

We can now relate the three classes together. Use the "New relation" button (New
      relation icon). 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.

The invoices.business
    class diagram

Creating the application

Global configuration

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();
My first application
	global configuration

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.

Configuring the RTTI/GUI aspect

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). No configuration is required for the moment.

The RTTI aspect configuration

Then, create and configure the GUI aspect as shown in the following screenshots.

The GUI aspect configuration
The GUI aspect configuration
The GUI aspect configuration

Starting the application

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

Important notes

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.