Apache Isis' simpleapp (as generated from the simpleapp archetype), converted to use the isis-script DSL (by vaulttec)
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.



This project contains a version of the app generated by Apache Isis' simpleapp archetype, but converted to use the isis-script DSL developed by Torsten Juergeleit.

Isis Script DSL is implemented with xtend and so provides a plugin for Eclipse IDE. It is also possible to build the app from the command line using Maven.


Here’s the SimpleObject domain class, written in isis-script:

@PersistenceCapable(identityType=IdentityType.DATASTORE, schema="simple", table="SimpleObject")
@DatastoreIdentity(strategy=IdGeneratorStrategy.IDENTITY, column="id")
@Version(strategy=VersionStrategy.VERSION_NUMBER, column="version")
	@Query(name = "find", language = "JDOQL",
		value = "SELECT FROM domainapp.dom.modules.simple.SimpleObject"),
	@Query(name = "findByName", language = "JDOQL",
		value = "SELECT FROM domainapp.dom.modules.simple.SimpleObject WHERE name.indexOf(:name) >= 0")
@Unique(name="SimpleObject_name_UNQ", members = #["name"])
@DomainObjectLayout(bookmarking = BookmarkPolicy.AS_ROOT, cssClassFa = "fa-flag")
entity SimpleObject {

	@Column(allowsNull="false", length = 40)
	@Property(editing = Editing.DISABLED)
	property String name

	property Integer count

	@Action(domainEvent = UpdateNameDomainEvent)
	action SimpleObject updateName {
		@Parameter(maxLength = 40)
		@ParameterLayout(named = "New name")
		parameter String newName {
			default {
		body {
		validate {
			if (newName.contains("!"))
				TranslatableString.tr("Exclamation mark is not allowed")
			else null
		event UpdateNameDomainEvent

	title {
		TranslatableString.tr("Object: {name}", "name", name)

By way of comparison, the original Java version is:

@PersistenceCapable(identityType=IdentityType.DATASTORE, schema="simple", table="SimpleObject")
@DatastoreIdentity(strategy=IdGeneratorStrategy.IDENTITY, column="id")
@Version(strategy=VersionStrategy.VERSION_NUMBER, column="version")
                name = "find", language = "JDOQL",
                value = "SELECT FROM domainapp.dom.modules.simple.SimpleObject "),
                name = "findByName", language = "JDOQL",
                value = "SELECT FROM domainapp.dom.modules.simple.SimpleObject WHERE name.indexOf(:name) >= 0 ")
@javax.jdo.annotations.Unique(name="SimpleObject_name_UNQ", members = {"name"})
@DomainObjectLayout(bookmarking = BookmarkPolicy.AS_ROOT, cssClassFa = "fa-flag")
public class SimpleObject implements Comparable<SimpleObject> {

    public TranslatableString title() {
        return TranslatableString.tr("Object: {name}", "name", getName());

    private String name;

    @javax.jdo.annotations.Column(allowsNull="false", length = 40)
            editing = Editing.DISABLED
    public String getName() {
        return name;
    public void setName(final String name) {
        this.name = name;

    public static class UpdateNameDomainEvent extends ActionDomainEvent<SimpleObject> {
        public UpdateNameDomainEvent(final SimpleObject source, final Identifier identifier, final Object... arguments) {
            super(source, identifier, arguments);
    @Action(domainEvent = UpdateNameDomainEvent.class )
    public SimpleObject updateName(
            @Parameter(maxLength = 40)
            @ParameterLayout(named = "New name")
            final String name) {
        return this;
    public String default0UpdateName() {
        return getName();
    public TranslatableString validateUpdateName(final String name) {
        return name.contains("!")? TranslatableString.tr("Exclamation mark is not allowed"): null;

    public Long getVersionSequence() {
        return (Long) JDOHelper.getVersion(this);

    public int compareTo(final SimpleObject other) {
        return ObjectContracts.compare(this, other, "name");

    private DomainObjectContainer container;

The most obvious difference is that the DSL includes keywords such as action, under which all the supporting methods are gathered. In contrast, the Java version has to group related methods together by naming convention (updateName(…​), validateUpdateName(…​) and default0UpdateName()).

Full details of the isis-script DSL can be found on the github repo

In addition, the body of isis-script methods are written in XTend, which provides a whole host of features over and above vanilla Java.

IDE support

As Torsten’s blog post shows, isis-script includes an Eclipse plugin. This provides:

  • automatic generation of Java code from isis-script

  • syntax highlighting

  • intellisense

  • markers

  • outlining

Setting up

Currently isis-script is still in development, so you’ll need to build it locally. It’s pretty easy to do, though.

Build isis-script

Clone the isis-script repo, and build using mvn:

git clone https://github.com/vaulttec/isis-script.git
git checkout develop
mvn clean install

All being well the code should run compile (I built using commit 9c31ad52f6995e1af9dd75f4668d67ee2f3d04cb, Sept 2015):

010 isis script repo mvn clean install completed

Do be aware, though: the first time I did this took about an hour (albeit on a moderately slow network). Thereafter it takes about 1 minute to recompile.

Install Eclipse Mars and plugins

Download Eclipse (the vanilla Java edition will suffice).

Then install plugins using Help > Install Software:

Download the simpleapp (this repo)

Clone this repo:

git clone https://github.com/isisaddons/isis-app-simpledsl

I also recommend you build this from the command line before importing into Eclipse:

mvn clean install

This should ensure that all the generated directories exist when we do the import.

Import into Eclipse

Import the project into Eclipse using File>Import:

110 eclipse file import

then Maven > Existing Maven Projects:

112 eclipse import maven projects

then select the source:

114 eclipse select source

when done the source code should be shown in the package explorer:

120 eclipse package explorer

Source and Generated Files

The source file is shown in an "Isis editor":

130 eclipse isis source file

The editor’s context menu can be used to navigate to the corresponding generated (Java) source:

210 isis source file context menu

The corresponding member is automatically highlighted:

220 isis generated file

And from the generated Java you can also navigate back to the source:

230 isis generated file context menu


Next, configure DataNucleus plugin as per the instructions on the Apache Isis website

Note the persistent-unit name in the manifest:

310 datanucleus manifest

Open up the dom project properties:

320 datanucleus project properties

and specify this persistence unit for the enhancer plugin:

330 datanucleus enhancer

Finally, back on the dom project’s context menu, enable auto-enhancement:

340 datanucleus auto enhancement

Using the Editor

Let’s take a quick look at the features available in the editor. To start with, the editor provides context sensitive intellisense:

410 editor intellisense

There’s also a quick outline view (ctrl+O), great for quick navigation:

420 editor quick outline

The outline is also available as a view:

430 editor outline view

Finally, any syntax errors are shown as markers and also in the problem view:

440 editor error markers

Running the app

You should be able to run the app either from Eclipse IDE, or from the command line.

To run within Eclipse, you’ll find that the webapp/ide/eclipse/launch directory contains some .launch configurations. These are set up to run Isis' org.apache.isis.WebServer (which bootstraps an embedded Jetty server).

You can run the app from the context menu of one of these .launch files:

510 eclipse run

and the console shows the app starting:

520 eclipse run console

Browsing to http://localhost:8080/wicket should hit the sign-in page (login sven/pass):

600 running app

and you can then use the app as normal:

610 running app dashboard

You can also build and then from the command line. To build:

mvn clean install

and to run use either:

mvn jetty:run

or if you prefer a splash screen:

mvn -P self-host antrun:run