01 June 2017

Dependencies

The following dependencies have been upgraded

  • com.google.code.findbugs:jsr305:3.0.2

  • org.slf4j:slf4j-simple:1.7.25

  • org.slf4j:slf4j-log4j:1.7.25

  • com.google.guava:guava:22.0

  • org.awaitility:awaitility:3.0.0

  • org.codehaus.groovy:groovy-all:2.4.11

  • org.jetbrains.kotlin:kotlin-stdlib:1.1.2-4

  • com.googlecode.lanterna:lanterna:2.7.9

Runtime

XML Configuration

XML has been added as part of the supported formats. You may write any configuration file using XML, for example

griffon-app/resources/DataSource.xml
<?xml version="1.0"?>
<configuration>
    <dataSource>
        <driverClassName>org.h2.Driver</driverClassName>
    </dataSource>
    <environments>
        <development>
            <dataSource>
                <url>jdbc:h2:mem:@application.name@-dev</url>
            </dataSource>
        </development>
        <test>
            <dataSource>
                <url>jdbc:h2:mem:@application.name@-test</url>
            </dataSource>
        </test>
        <production>
            <dataSource>
                <url>jdbc:h2:mem:@application.name@-prod</url>
            </dataSource>
        </production>
    </environments>
</configuration>

Configuration Value Injection

Configuration values may be injected into managed beans. Simply annotate a field or a setter with @Configured. Take for example the following configuration

griffon-app/conf/sample/swing/groovy/Config.groovy
application {
    title = 'JavaFX + Groovy'
    startupGroups = ['sample']
    autoShutdown = true
}
props {
    string = 'string'
    number = 42
    date   = '1970-12-24'
}
mvcGroups {
    'sample' {
        model      = 'sample.javafx.groovy.SampleModel'
        view       = 'sample.javafx.groovy.SampleView'
        controller = 'sample.javafx.groovy.SampleController'
    }
}

Any of those configuration values may be set on a managed bean, such as the SampleModel class

griffon-app/models/sample/javafx/groovy/SampleModel.groovy
package sample.javafx.groovy

import griffon.core.artifact.GriffonModel
import griffon.metadata.ArtifactProviderFor
import griffon.transform.FXObservable
import griffon.core.configuration.Configured

@ArtifactProviderFor(GriffonModel)
class SampleModel {
    @FXObservable String input
    @FXObservable String output

    @Configured('application.title')
    String title

    @Configured('props.string')
    String string

    @Configured('props.number')
    int number

    @Configured(value = 'props.date', format = 'YYYY-MM-dd')
    Date date

    @Configured(value = 'props.undefined', defaultValue = 'undefined')
    String undefined
}

Values will be injected before @PostConstruct is triggered on the managed bean. Type conversion will be carried out using property editors.

Typed MVCGroup support

It’s now possible to define typed MVC groups. This feature assumes the MVC group has the required Model, View, and Controller members; it won’t work for groups that define less than these 3 members. For example

src/main/java/org/example/FooMVCGroup.java
package org.example;

import javax.inject.Named;
import griffon.core.mvc.MVCGroup;
import org.codehaus.griffon.runtime.core.mvc.AbstractTypedMVCGroup;

@Named("foo")
public class FooMVCGroup extends AbstractTypedMVCGroup<FooModel, FooView, FooController> {
    public FooMVCGroup(MVCGroup delegate) {
        super(delegate);
    }
}

Instances of this group can be created as follows

FooMVCGroup fooGroup1 = createMVCGroup(FooMVCGroup.class);
FooMVCGroup fooGroup2 = createMVCGroup(FooMVCGroup.class, "foo2");

You may refer to the exact types of each MVC member using a typed MVC group, for example

FooMVCGroup fooGroup = createMVCGroup(FooMVCGroup.class);
fooGroup.model().setSomeProperty("value"); // returned model type is FooModel

// the following won't even compile
MVCGroup mvcGroup = createMVCGroup("foo");
mvcGroup.getModel().setSomeProperty("value"); // returned model type is GriffonModel !!

JavaFX Support

Two new widgets are now available: IndexedCardPane and NamedCardPane. They provide similar capabilities as the ones found in java.awt.CardLayout. The first widget stores its children using an indexed List while the second widget uses "keys" instead of indexes.

New MatchingBindings class provides matching capabilities on ObservableList/ObservableSet/ObservableMap

  • Apply allMatch, anyMatch, and noneMatch predicates.

You can now create TableColumns and fill out a TableView with the brand new TableViewFormat and TableViewModel classes as shown by:

TableViewFormat<Measurement> tableFormat = new DefaultTableFormat<>(
    new DefaultTableFormat.Column("name", 0.2d),
    new DefaultTableFormat.Column("amount", 0.1d),
    new DefaultTableFormat.Column("timestamp")
);
ObservableList<Measurement> measurements = uiThreadAwareObservableList(model.getMeasurements());
TableViewModel<Measurement> tableModel = new DefaultTableViewModel<>(measurements, tableFormat);
tableModel.attachTo(measurementsTableView);
measurementsTableView.setEditable(false);

Buildtime

Gradle Wrapper

Gradle wrapper version on all Lazybones templates has been bumped to 3.5.

Compatibility

Implementation classes of Configuration were moved to the org.codehaus.griffon.runtime.core.configuration package. Plugins that rely on reading custom configuration files (such as persistence plugins like datasource et al) must be updated to their latest versions.

Full binary compatibility report between Griffon 2.11.0 and 2.10.0 can be found here.

A list of fixed issues can be found at the 2.11.0 milestone page.