Fujaba Plug-In

The Fujaba plug-in for DRAGOS is based on the CodeGen2 plug-in. Thus, you first have to install this plug-in before you can install the DRAGOS plug-in.

After installing the DRAGOS plug-in you only need to activate it. Now, Fujaba no longer generates plain Java code, but Java code which uses DRAGOS.

Restrictions

The Fujaba plug-in imposes a few restrictions on the specification:

  • Persistent classes are only allowed to have a persistent super class or no super class at all.
  • The default constructor must not be specified. It is reserved for use by the runtime library.
  • Explicit invocations of new are strictly forbidden.
  • Do not implement your own setter- and getter-methods for attributes.
  • Do not access attributes directly use the getter-methods.
  • To conclude the last restrictions: Use Fujaba as a visual programming language as far as possible.

Currently not supported but planned for the very near future:

  • Issue a warning when
    • default constructor is specified
    • explicit use of new

Using the Generated Code

Basics

With a few exceptions the generated can be used as the one generated before. These exceptions them from using a database system instead of a plain main memory.

DRAGOS4Fujaba introduces the notion of a Repository. A repository hides the underlying DRAGOS graph and simplifies the access to it. Repositories are managed by the RepositoryManager which is in turn produced by a factory.

To use the code generated by Fujaba, you first have to initialize this factory:

RepositoryManagerFactory.startup();

Afterwards, a RepositoryManager can be created by calling

RepositoryManagerFactory.create(String datasourceURL);

The datasourceURL identifies the graph storage that should be used by DRAGOS to store the graphs persistently. A detailed description on the data source URL can be found in the corresponding API documentation.

To create a repository one has to use the method

RepositoryManager repoMan = RepositoryManagerFactory.create(String datasourceURL);

If you are only going to use one repository through out your realization you don't need to store the repository that has been returned. You retrieve the repository simply by invoking:

Repository myRepo = RepositoryManager.getDefaultRepository();

After we have a created the repository we should create the first instance of one of the classes we have generated. However, we can not use the usual Java approach

SomeObject o = new SomeObject();

Instead, we must use the repository's method newInstance:

SomeObject o = myRepo.createInstance(SomeObject.class);

Please note that any operation on the repository has to be enclosed in a transaction. For efficency reasons, the repository does not start a transaction on its own. See the next section how a transaction is started manually.

If we have only one repository we do not need the myRepo variable and simply create the instance using a static method of RepositoryManagerFactory:

SomeObject o = RepositoryManagerFactory.getDefaultRepository().newInstance(SomeObject.class);

Now that we have created our new object we can invoke all the methods on it we specified in Fujaba. If the specified methods create new instance the complexity shown above is done internally. So you only have to care about if you must create new instances on your own. In fact, the proposed way to create any initial data structures for the generated application is to model a static in Fujaba. Access to the Repository and transaction management will be handled by the generated code in this case.

Under certain circumstances you will be presented the nodes internally used by DRAGOS4Fujaba to store graph. This happens for example when you handle the events raised by DRAGOS upon graph modifications. In this case you would like to construct instances corresponding to the classes you have specified. For this the following to methods are available (the second uses the default repository again):

SomeObject o = myRepo.retrieveInstance(myNode);
SomeObject o = RepositoryManagerFactory.getDefaultRepository().getInstance(myNode);

Transaction Support

The code generated by the DRAGOS plug-in provides full transaction support. By default every single method is a transaction on its own. However, sometimes you would like to have more control and want to create the transactions on your own. One reason to so is efficiency, since transactions involves overhead. A second reason are modifications performed by several methods which must all be successful in order to avoid inconsistencies. Of course, the transaction support of DRAGOS4Fujaba makes full use of nested transactions if they are supported by the underlying data source.

To start a transaction you have to use one of the following two methods: The second one will use the default repository. This is a good choice when only one is in use.

TransactionUtil.begin(myRepo.getManager());
TransactionUtil.begin(); 

When you are done with your work you finish the transaction.

boolean success = TransactionUtil.finish();

If success is false then the transaction could not be committed and was aborted. Otherwise, the transaction has committed successfully.

In case of an error you should ensure the transaction can only be aborted. For this you simply invoke the following method:

TransactionUtil.markRollbackOnly();

Undo/Redo

The generated applications already provides all functionality required for undo/redo of all operations. When enabled for the RepositoryManager, a new version is automatically created when a transaction commits.

Using Constructors with parameters

The Fujaba Graph Model requires that each instance of the Instance class offers a parameter taking a NodeID. This is for the reason that each operation has to be mapped to a database transaction. Using the NodeID, this mapping is performed. The Code Generation creates a constructor taking just this parameter. It is called by the graph model when 1) a new object should be placed into the database or 2) an existing object is retrieved from the database. In both cases, assigning this NodeID to the interal field of the Instance class is required before _any_ operation on the object (like getting/setting attributes etc.) can be conducted. Therefore, defining and especially using the default constructor is strongly forbidden, as this would not enable the Instance object to be mapped to some node.

If you need to use constructors on your own, add a NodeID as the first parameter, and have the first statement super(nodeID);. You may then pass parameters to the getInstance method introduced above. For example, the following constructor which obeys these restrictions:

public MyClass(NodeID nid, String name) {
  super(nid);
  setName(name);
}

is invoked by the Repository when an according value is passed to the (optional/set-valued) parameter argument:

myRepo.createInstance(MyClass.class, "myName");

When using this constructor in a Fujaba specification, remember you may _not_ use new. The correct statement for this is:

RepositoryManagerFactory.getDefaultRepository().newInstance(MyClass.class, "myName");

Yes, we are aware this is nasty. However, there is no way to visually invoke constructors anyway in Fujaba, so you would use nasty Java-code without DRAGOS, too.