Quick start
To create a sample application pre-configured to work with the Fénix Framework, execute the following Maven command and follow the interactive mode:
mvn archetype:generate -DarchetypeGroupId=pt.ist -DarchetypeArtifactId=fenix-framework-application-archetype-clean -DarchetypeVersion=2.0 -DarchetypeRepository=https://fenix-ashes.ist.utl.pt/maven-public
The parameters that you can give to the clean application archetype (using the
-D switch) are:
fenixFrameworkVersion:- Description: The version of the Fenix Framework to use
- Default: Same as the archetype’s version.
backEndName- Description: The name of the backend to use. Some possible values are
mem,ispnandogm. - Default:
mem
- Description: The name of the backend to use. Some possible values are
backEndGroupId- Description: The groupId of the backend module to use.
- Default:
pt.ist
backEndArtifactId- Description: The artifactId of the backend module to use.
- Default:
fenix-framework-backend-mem
backEndVersion- Description: The version of the backend module to use.
- Default: Same as the archetype’s version.
codeGeneratorClassName- Description: The code generator class provided by the chosen backend.
Some possible values for each backend are:
mem->pt.ist.fenixframework.backend.mem.MemCodeGeneratorogm->pt.ist.fenixframework.backend.ogm.OgmCodeGeneratorispn->pt.ist.fenixframework.backend.infinispan.InfinispanCodeGenerator
- Default:
pt.ist.fenixframework.backend.mem.MemCodeGenerator
- Description: The code generator class provided by the chosen backend.
Some possible values for each backend are:
Hello world example
As a very simple example to illustrate the use of the Fénix Framework, let us create a Java application with a minimalist domain model.
In this application we model one new entity: The Person. We keep a
collection of people by establishing a relation between Person and
DomainRoot. The DomainRoot is a built-in entity that represents a
possible root for the domain objects’ model. When the framework initializes,
it automatically creates one instance of the DomainRoot (if it doesn’t already
exist). The Person type will have one instance for each person known.
Whenever the application is run we pass it the name of a new person and the application adds that person to its set of known people and asks each one of them to say “Hello”.
Let us start by creating the basic application structure with:
mvn archetype:generate -DarchetypeGroupId=pt.ist -DarchetypeArtifactId=fenix-framework-application-archetype-clean -DarchetypeVersion=2.0 -DarchetypeRepository=https://fenix-ashes.ist.utl.pt/maven-public -DgroupId=example -DartifactId=helloworld -Dversion=1.0-SNAPSHOT
Then, to define the domain model, edit the file in
src/main/dml/helloworld.dml and write the following content:
package example;
class Person {
String name;
}
relation KnownPeople {
.pt.ist.fenixframework.DomainRoot playsRole root;
Person playsRole people { multiplicity *; }
}
This defines the Person entity and adds a relation between DomainRoot and
Person, where a DomainRoot may have any number of Person related to it.
The package declaration is similar to the corresponding declaration in Java.
Now, this DML code takes care of defining the structural aspects of the
domain model, but has no behavior in it. For instance, we would like that each
Person could say hello. Also, in our example, we will be instantiating a
Person with a constructor that receives the name of the person and the
instance of the DomainRoot.
To implement the behavior, we write it in plain old Java. So, for the
Person, we may write (in Java, now):
package example;
import pt.ist.fenixframework.DomainRoot;
public class Person extends Person_Base {
public Person(String name, DomainRoot root) {
setName(name);
setRoot(root);
}
public void sayHello() {
System.out.println("Hello, I'm " + getName() + ".");
}
}
The Person class extends the Person_Base class, which is an abstract class
generated by the Fénix Framework that implements the structural aspects of the
Person entity (likewise for any other entity defined in a DML file).
To conclude this example, we just have to write our HelloWorld application,
which, as mentioned, will create the new people and then, ask all of them to
say hello. This can be done with:
package example;
import pt.ist.fenixframework.Atomic;
import pt.ist.fenixframework.DomainRoot;
import pt.ist.fenixframework.FenixFramework;
public class HelloWorld {
// FenixFramework will try automatic initialization when first accessed
public static void main(String [] args) {
try {
addNewPeople(args);
greetAll();
} finally {
// ensure an orderly shutdown
FenixFramework.shutdown();
}
}
@Atomic
private static void addNewPeople(String[] args) {
DomainRoot root = FenixFramework.getDomainRoot();
for (String name : args) {
new Person(name, root);
}
}
@Atomic
private static void greetAll() {
DomainRoot root = FenixFramework.getDomainRoot();
for (Person p : root.getPeople()) {
p.sayHello();
}
}
}
Notice the use of the @Atomic annotation to demarcate the
transactions. Operations involving domain objects must always
be performed inside a transaction.
And that’s all. Now, you just have to build it and run it. The complete example is available for download here. After decompressing it, you can execute it with:
mvn clean package exec:java -Dexec.mainClass="example.HelloWorld" -Dexec.args="John"
By default, the Fénix Framework is configured to use the in-memory backend, so, in the previous example, the application state is not persisted between executions. Here is the same example, now using the Infinispan backend to store the domain objects persistently.
