Consult these notes when migrating to new versions of the framework.

From v1.13.x to 1.14.0

New metamodel validations

This release defines a number of metamodel validations. These can be enabled or disabled using configuration properties:

  • isis.reflector.validator.explicitObjectType

    Whether to check that the class has an object type explicitly specified somehow. This is strongly recommended, but is disabled by default to prevent migration issues.

  • isis.reflector.validator.jdoqlFromClause

    Whether to check that the class name in JDOQL FROM clause matches or is a supertype of the class on which it is annotated. This is enabled by default.

  • isis.reflector.validator.jdoqlVariablesClause

    Whether to check that the class name in JDOQL VARIABLES clause is a recognized class. This is enabled by default.

  • isis.reflector.validator.mixinsOnly

    This is disabled by default; if enabled, this configuration property will treat any contributed service as invalid; instead use mixins (as a simpler/less confusing programming model).

  • isis.reflector.validator.noParamsOnly

    When searching for disableXxx() or hideXxx() supporting methods, whether to search only for the no-param version (or also for supporting methods that match the parameter types of the action).

    This is disabled by default; if enabled then this makes for a simpler programming model.

  • isis.reflector.validator.serviceActionsOnly

    Domain services are stateless (at least conceptually) and so should not have any properties or collections; any that are defined will not be rendered by the viewers.

    This is disabled by default; if enabled, then this ensure that domain services only declare actions and so makes for a simpler programming model.

From v1.12.x to 1.13.0

Most applications written against v1.12.x should run against v1.13.0 with few if any changes. That said, this release has removed a small number of features that were dependent on internal APIs, and some configuration properties are now removed/unsupported. We therefore do recommend that you read and keep in mind these notes when you upgrade your app.

If you do encounter any difficulties then let us know via the users mailing list, so we can support you and document issues here.

Command changes

The main feature in 1.13.0 is the InteractionContext domain service to represent an action invocation/property edit, with the re-positioning of CommandContext to represent the _intention to invoke an action/edit a property. You can read more about this design in the reference guide on domain services, in the commands and events section.

This refactoring completely overhauls the structure of the XML mementos passed to CommandService (to persist) and to BackgroundCommandService (to invoke persisted commands in the background). If you are using these services then ensure that there are no pending commands at the point at which you cut-over. If you have any code that makes assumptions on the format of the XML, it will also need to be rewritten. Note that the XML which is persisted henceforth is well-defined and any future changes to it will be backward compatible; see schema reference guide. In fact, there are three schema: for commands (cmd.xsd), inteactions (ixn.xsd) and for changes (chg.xsd). These replace the earlier aim.xsd schema (which was an amalgam of cmd.xsd and ixn.xsd).

The reworked CommandService now properly supports property edits in the exact same way as action invocations.

As a side-effect of this work, note also that:

  • the CommandService#startTransaction(…​) SPI is NO LONGER CALLED by the framework.

  • the BackgroundService#asActionInvocationMemento(…​) (not formally part of the API) is also no longer called by the framework; moreover the default implementation now throws an exception to this effect.

Auditing

The AuditingService SPI service has been deprecated, instead replaced by the AuditerService.

There can be more than one implementation of this new SPI, and a framework-provided implementation (AuditerServiceLogging) will log to a file. The (non-ASF) Isis addons' audit module also implements the new SPI.

Publishing

The PublishingService SPI service and its supporting EventSerializer domain service, have both deprecated, instead replaced by the PublisherService.

There can be more than one implementation of this new SPI, and a framework-provided implementation (PublisherServiceLogging) will log to a file. The (non-ASF) Isis addons' publishmq module also implements the new SPI.

The new service also supports the notion of published property edits; the new @Property#publishing() annotation attribute can be used to specify. The ` isis.services.publish.properties` configuration property can be used to specify a fallback default for properties where the attribute is not set explicitly.

Conversely, neither the @Action#publishingPayloadFactory() nor the @DomainObject#publishingPayloadFactory() are supported by PublisherService; instead the consumers of the events are expected to callback for any additional information, eg using Resful Objects viewer.

Auto-logout

The new configuration property isis.authentication.shiro.autoLogoutIfAlreadyAuthenticated (documented more fully in the security guide) is by default set to false, thereby disabling auto-logout behaviour that is believed to be the root cause of some exceptions thrown by the Restful Objects viewer during a race condition. The previous behaviour can be re-enabled by setting to true.

Safe 'rememberMe' cookies

Apache Isis leverages Apache Wicket's rememberMe support which holds remembered user/passwords in an encrypted cookie.

If a hard-coded and publicly known value were to be used (as was the case prior to 1.13.0), then it would be possible for rememberMe user/password to be intercepted and decrypted, possibly compromising access. The isis.viewer.wicket.rememberMe.encryptionKey configuration property therefore allows a private key to be specified, baked into the application.

If no value is set then (for safety) a random UUID will be used as the encryption key. (The net effect of this fallback behaviour is that 'rememberMe' will work, but only until the webapp is restarted (after which the end-user will have to log in again).

Related, the isis.viewer.wicket.suppressRememberMe configuration property has been replaced by isis.viewer.wicket.rememberMe.suppress (though the old configuration property is still supported).

Custom programming models

In previous releases the isis.reflector.facets configuration property could be used to specify a new implementation of the (internal) ProgrammingModel API. This configuration property is no longer supported. See the beyond the basics guide for an alternative broadly equivalent approach.

injectXxx() no longer supported

Apache Isis automatically injects domain services into other domain objects, supporting the @Inject annotation, also injection to set…​() setter methods and finally injection into inject…​() methods. This last method is now no longer supported by default. It can be re-enabled if necessary using the isis.services.injector.injectPrefix configuration property.

It is also possible to disable injection to set…​() methods (using the isis.services.injector.setPrefix configuration property), though this is enabled by default.

Disabling auto-wiring has a positive impact on bootstrap times, as well as standarding Apache Isis' conventions to be more in line with JEE.

Optionally ignore deprecated facets

The isis.reflector.facets.ignoreDeprecated configuration property indicates whether to continue to honour or to simply ignore any deprecated annotations and other semantics that make up the programming model.

This is disabled by default, in other words deprecated facets continue to be recognized. Be aware that enabling this setting could substantially alter the semantics of your application. To be safe, we recommend that you first run the application using isis.reflector.validator.allowDeprecated set to false; if any deprecated annotations etc. are in use, then the app will fail-fast and refuse to start.

ApplicationFeatureRepository

The isis.services.applicationFeatures.init configuration property is used to control whether the ApplicationFeatureRepository domain service lazily or eagerly initializes itself based on the framework’s internal metamodel.

Previously this service eagerly initialized itself, causing the framework to have to traverse the domain object model graph for all types, noticeably increasing the bootstrap time. For 1.13.0 this service now initializes itself lazily. The previous behaviour (of eager initialization) can be re-enabled by setting this property to eager.

Integration testing

There are two sets of changes relating to integration tests.

Builder

The IsisSystemForTest.Builder class is used to bootstrap integration tests.

A number of the clauses within this class have been removed:

  • with(PersistenceMechanismInstaller persistenceMechanismInstaller)

    Apache Isis has for many releases only supported a single implementation of persistence mechanism (JDO/DataNucleus), so this builder method is redundant.

  • with(ProgrammingModel programmingModel)

    Instead, use AppManifest#getConfiguration() to include/exclude facets

  • with(MetaModelValidator metaModelValidator)

    Instead, use AppManifest#getConfiguration() to specify a custom validator.

  • withServicesIn(String…​ packagePrefixes) and withServices(Object…​ services)

    Instead, use AppManifest#getAdditionalServices()

  • withFixtures(InstallableFixture…​ fixtures)

    Instead, use AppManifest#getFixtures()

Centralizing configuration

Previously when bootstrapping the integration tests, the IsisConfigurationForJdoIntegTests was provided as a custom implementation of IsisConfiguration, providing a number of configuration settings specifically for running integration tests (eg run using an in-memory database). This design split the responsiblity of providing the configuration properties between that class and AppManifest.

A new AppManifest.Util helper class now allows these responsibilities to belong exlusively to the AppManifest. For example:

public class DomainAppSystemInitializer {
    public static void initIsft() {
        IsisSystemForTest isft = IsisSystemForTest.getElseNull();
        if(isft == null) {
            isft = new IsisSystemForTest.Builder()
                    .withLoggingAt(org.apache.log4j.Level.INFO)
                    .with(new DomainAppAppManifest() {
                        @Override
                        public Map<String, String> getConfigurationProperties() {
                            final Map<String, String> map = Maps.newHashMap();
                            Util.withJavaxJdoRunInMemoryProperties(map);
                            Util.withDataNucleusProperties(map);
                            Util.withIsisIntegTestProperties(map);
                            return map;
                        }
                    })
                    .build();
            isft.setUpSystem();
            IsisSystemForTest.set(isft);
        }
    }
}

web.xml

In the web.xml, the "isis.viewers" context-param is now ignored. Instead the viewer_wicket.properties and viewer_restfulobjects.properties will both be loaded if present (but neither need be present).

HasTransactionId mixin

The HasTransactionId mixin interface has subtly changed its meaning (and is now somewhat mis-named). Prior to 1.13.0, this identifier was the GUID of the Isis transaction in which the object was created. As of 1.13.0, this identifier actually is for the request/interaction (as per the new InteractionContext service) in which the object was created.

Notable new features

The following are new features so do not impact in themselves impact any migration effort, but you may wish to start taking advantage of once you have upgraded.

  • @Nullable annotation

    The @Nullable annotation can now be used to specify the optionality of properties and parameters.

  • ActionDomainEvent for mixins

    Previously it was not possible to discover the mixed-in domain object when an ActionDomainEvent was raised by a mixin action. This is now possible, through the mixedIn() method.

  • Blob and Clob file types

    The @Property#fileAccept() and @Parameter#fileAccept() annotation attributes can be used to hint at the file type to upload for a blob or clob.

  • Live reloading

    The isis.viewer.wicket.liveReloadUrl configuration property allows live reloading of objects if the layout is updated, reducing feedback times. Further guidance on setting this up can be found here.

  • Docker support

    The overrides.properties configuration file, if present, is loaded last as the configuration property file, with its contents overriding any previously defined configuration properties. This simple idea makes it easy to create Docker container images; see here for further discussion.

From v1.11.0 to 1.12.0

Existing projects written against v1.11.x should run against v1.12.0 with few if any changes. If you do encounter any difficulties then let us know via the users mailing list, so we can support you and document issues here.

Dynamic XML Layouts

The major new feature in 1.12.0 is dynamic XML layouts, providing much enhanced support for custom layouts.

The new Xxx.layout.xml file is optional; without it domain objects will continue to be rendered as before, using metadata from annotations (@DomainObjectLayout, @PropertyLayout, @CollectionLayout, @ActionLayout, @MemberOrder and @MemberGroupLayout), and also from any Xxx.layout.json file that might already exist. There is therefore no requirement to move to the new more flexible XML-based layout.

If you do want to start using the new format, then you will find that 1.12.0 provides a mixin action (available in prototype mode only) called "download XML layout". This will allow you to download the current layout file for the object being rendered. This can then be saved alongside the class' Java source file. Once a Xxx.layout.xml file is present, any existing Xxx.layout.json file will be ignored; any annotations though will continue to be honoured.

If you wish to migrate all your domain objects to use XML layouts, this can be done using the "download layouts (XML)" (on the "Prototyping" menu), as a single zip file. This can then be unzipped into the src/main/java directory.

Mixins

(As mentioned above), 1.12.0 provides a number of new mixin actions and properties:

These are in addition to the download JDO metadata mixin action (prototype mode) provided in earlier versions of the framework.

The properties are grouped in a "metadata" fieldset, and the mixin actions associated with that fieldset. If the domain object is a view model rather than an entity (that is, has no id or version) then the actions will instead be rendered as top-level actions.

Most of these mixin object members are visible only in prototype mode, though some are visible in production mode and so potentially visible to end-users. If you wish to suppress these members from the view, you can either use security, or alternatively you can write subscribers to veto the visibility of these members by subscribing to their respective domain events.

JAXB view models are editable

All @XmlRootElement view models are now implicitly editable. Therefore any view models that should be read-only should have editing attribute disabled using @DomainObject#editing() (or use a subscriber to veto editability).

DomainObjectContainer domain service

The DomainObjectContainerdomain service has been deprecated, with its methods moved to a new set of more fine-grained domain services, such as RepositoryService and MessageService.

The DomainObjectContainer service will continue to be supported until Apache Isis v2.0.0, but in the meantime, consider changing existing application code to use these new domain services.

Please note that when migrating from _rgsvc_api_DomainObjectContainer_object-persistence-api.adoc#_rgsvc_api_DomainObjectContainer_object-persistence-api[DomainObjectContainer#persist()] to RepositoryService#persist(), no exception will be thrown if the Domain Object is already persisted, so the behavior of RepositoryService#persist() will be the same as that of _rgsvc_api_DomainObjectContainer_object-persistence-api.adoc#_rgsvc_api_DomainObjectContainer_object-persistence-api[DomainObjectContainer#persistIfNotAlready()].

Removal of the self-host profile

The self-host profile has been removed from the SimpleApp archetype. Instead, run the application using either the org.apache.isis.WebServer main class, or mvn jetty:run, or build the WAR and deploy to a servlet container such as Tomcat.

isis.viewer.wicket.disableModalDialogs removed

The Apache Isis Wicket viewer uses a modal dialog for action parameters. Before this feature was implemented (prior to 1.4.0), action parameters were rendered on their own page. This property was provided to re-enable the old behaviour.

The property has now been removed and this feature removed; actions parameters are always now always shown in a modal dialog.

From v1.10.0 to 1.11.0

Existing projects written against v1.10.0 should run against v1.11.0 with few if any changes. If you do encounter any difficulties then let us know via the users mailing list, so we can support you and document issues here.

Swagger UI

The new SwaggerService allows Swagger spec files to be generated from the Apache Isis metamodel. These can be downloaded directly through the SwaggerResource (mapped to /restful/swagger/public and /restful/swagger/private) as well as from the Wicket UI through the SwaggerServiceMenu.

In addition, the SimpleApp archetype now bundles Swagger UI, which documents the main features of the REST API and allows it to be explored.

To enable this in your application, first update the web.xml:

<servlet>
    <servlet-name>WebjarsServlet</servlet-name>                         (1)
    <servlet-class>org.webjars.servlet.WebjarsServlet</servlet-class>
    <init-param>
        <param-name>disableCache</param-name>
        <param-value>false</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>WebjarsServlet</servlet-name>
    <url-pattern>/webjars/*</url-pattern>
</servlet-mapping>
...
<filter>
    <filter-name>IsisSessionFilterForRestfulObjects</filter-name>
    ...
    <init-param>
        <param-name>whenNoSession</param-name>
        <param-value>auto</param-value>                                 (2)
    </init-param>
    <init-param>
        <param-name>passThru</param-name>                               (3)
        <param-value>/restful/swagger</param-value>
    </init-param>
</filter>
1 provides access to the Swagger UI (packaged as a webjar)
2 issues a 401 status, but with the WWW-Authenticate challenge suppressed if requested from the Swagger UI
3 provides access to the RESTful resource that generates the Swagger spec.

There is also an HTML page to load the Swagger UI itself; this resides in src/main/webapp/swagger-ui/index.html. Copy the file from Apache Isis' repo, or from the app generated by the SimpleApp archetype.

The text of the simple app’s about/index.html has also changed (the <li> for the /restful URL has been replaced with a /swagger-ui URL). If you use this file, then update it.

If your application is bootstrapped using an AppManifest (recommended; here) then the default implementation of the SwaggerService will automatically be discovered and registered. However, if you are still using the older isis.properties configuration file to explicitly register services then you will need to add in this service.

RoutingService

The new RoutingService SPI service provides a plugin point to the Wicket viewer so that a different object than that returned from an action invocation can be rendered.

The framework provides a default implementation of this service that will - instead of a void or a null result - render the home page (as per the @HomePage annotation) if there is one. This is therefore a subtle change in the UI. If you wish to retain the original behaviour (to return the "no results" page instead), then you should implement your own no-op implementation of this service:

@DomainService
@DomainServiceLayout(menuOrder="1")
public class IdentityRoutingService implements RoutingService {
    public boolean canRoute(Object original) { return true; }
    public Object route(Object original) { return original; }
}

Wicket Viewer i18n

The Wicket viewer (its labels, buttons, messages etc) can now be internationalized using the TranslationService.

To enable this, new msgIds and corresponding translations must be added to the translations.po file. Full details of these msgIds can be found in i18n section of the "beyond the basics" guide.

If no translations are available, then the fallback is to use the previous mechanism, ie Wicket’s original resource bundles. This feature can therefore be considered as optional.

From v1.9.0 to 1.10.0

Existing projects written against v1.9.0 should run against v1.10.0 with only a few minor changes. If you do encounter any difficulties then let us know via the users mailing list, so we can support you and document issues here.

Remove references to isis-viewer-wicket parent pom.

In earlier releases the Wicket viewer defined its own parent pom.xml for dependency management and its dependencies and to declare the various submodules that make up the viewer. This pom.xml has now been incorporated into the parent pom.xml for the Core framework.

Therefore, in the parent pom.xml of your own domain applications, remove:

<dependencyManagement>
    <dependencies>
        ...
        <dependency>
            <groupId>org.apache.isis.viewer</groupId>
            <artifactId>isis-viewer-wicket</artifactId>
            <version>${isis.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        ...
    </dependencies>
</dependencyManagement>

allowLateRegistration

One possible issue is that (as per ISIS-830) the EventBusService is now initialized as one of the first domain services; this is to ensure that any object lifecycle events caused by domain services initializing themselves can be posted on the event bus for subscribers. The typical case for such lifecycle events to occur is from domain services that seed reference data; one such example can be found in the (non-ASF) Isis addons' security module.

In previous releases, the ordering of initialization for the EventBusService was undefined (but would typically be towards the "end" of the list of services. What this meant in practice is that it generally didn’t matter whether (domain service) subscribers were initialized before or after seed services.

Now, though, because the EventBusService is initialized early on, it proactively checks that all subscribers have been registered before any event posts occur (so that no events get missed). If any subscriber attempts to register after at least one event has been posted, then the service will fail fast and the framework will not start. The error looks something like:

: EXEC
org.isisaddons.module.security.seed.scripts.IsisModuleSecurityAdminUser
seed-users-and-roles-fixture-script/isis-applib-fixture-results-role-and-permissions
: EXEC
org.isisaddons.module.security.seed.scripts.IsisApplibFixtureResultsRoleAndPermissions
19:41:19,478  [IsisTransaction      main       INFO ]  abort transaction
IsisTransaction@5dc1597f[state=MUST_ABORT,commands=1]
19:41:19,495  [IsisWicketApplication main       ERROR]  Failed to initialize
com.google.inject.ProvisionException: Guice provision errors:

1) Error in custom provider,
org.apache.isis.core.runtime.system.transaction.IsisTransactionManagerException:
java.lang.IllegalStateException: Events have already been posted; too late
to register any further (singleton) subscribers
  at
org.apache.isis.core.runtime.runner.IsisInjectModule.provideIsisSystem(IsisInjectModule.java:139)

To ensure that subscriber domain services are initialized before "seed" domain services, the @DomainServiceLayout#menuOrder() attribute can be used. Normally this attribute is just used to order UI-visible services on the menu bars, but it also is used internally to sequence the internal list of services being initialized.

Alternatively, you can disable this checking within the EventBusService using:

isis.services.eventbus.allowLateRegistration=true

If you do that, be aware that not all subscribers may not receive some events generated by other domain services.

For more details, see the EventBusService man page.

Simplify domain events

The domain event superclasses now provide no-arg versions; the framework will use new (non-API) setters to initialize.

This means that domain events can be substantially simplified, eg from this:

public class ToDoItem {
    public static class CompletedEvent extends ActionDomainEvent<ToDoItem> {
        private static final long serialVersionUID = 1L;
        public CompletedEvent(
                final ToDoItem source,
                final Identifier identifier,
                final Object... arguments) {
            super("completed", source, identifier, arguments);
        }
    }
    @Action(domainEvent=CompletedEvent.class)
    public ToDoItem completed() { ... }
}

to just this:

public class ToDoItem {
    public static class CompletedEvent extends ActionDomainEvent<ToDoItem> { }  (1)
    @Action(domainEvent=CompletedEvent.class)
    public ToDoItem completed() { ... }
}

isis-maven-plugin

The way that the Isis Maven plugin is configured has changed slightly; check out its documentation for full details.

From v1.8.0 to 1.9.0

Upgrading to DataNucleus 4

Apache Isis 1.9.0 updates to DataNucleus 4.0.0, which requires some changes (simplifications) to the Maven configuration.

If you starting a new app then you can start from the SimpleApp archetype; its Maven configuration has been updated.

If you have an existing Apache Isis app that you want to upgrade, then you’ll need to make some changes.

In the parent pom.xml

under the project/properties, remove:

<!-- must be consistent with the versions defined by the JDO Objectstore -->
<datanucleus-accessplatform-jdo-rdbms.version>3.3.6</datanucleus-accessplatform-jdo-rdbms.version>
<datanucleus-maven-plugin.version>3.3.2</datanucleus-maven-plugin.version>

In dom/pom.xml,

under build/plugins, remove:

<plugin>
    <groupId>org.datanucleus</groupId>
    <artifactId>datanucleus-maven-plugin</artifactId>
    <version>${datanucleus-maven-plugin.version}</version>
    <configuration>
        <fork>false</fork>
        <log4jConfiguration>${basedir}/log4j.properties</log4jConfiguration>
        <verbose>true</verbose>
        <props>${basedir}/datanucleus.properties</props>
    </configuration>
    <executions>
        <execution>
            <phase>compile</phase>
            <goals>
                <goal>enhance</goal>
            </goals>
        </execution>
    </executions>
</plugin>

and (if you have it) under build/pluginManagement/plugins, remove:

<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
<plugin>
    <groupId>org.eclipse.m2e</groupId>
    <artifactId>lifecycle-mapping</artifactId>
    <version>1.0.0</version>
    <configuration>
        <lifecycleMappingMetadata>
            <pluginExecutions>
                <pluginExecution>
                    <pluginExecutionFilter>
                        <groupId>
                            org.datanucleus
                        </groupId>
                        <artifactId>
                            datanucleus-maven-plugin
                        </artifactId>
                        <versionRange>
                            [3.2.0-release,)
                        </versionRange>
                        <goals>
                            <goal>enhance</goal>
                        </goals>
                    </pluginExecutionFilter>
                    <action>
                        <ignore></ignore>
                    </action>
                </pluginExecution>
            </pluginExecutions>
        </lifecycleMappingMetadata>
    </configuration>
</plugin>

and instead, under <profiles> add:

<profile>
    <id>enhance</id>
    <activation>
        <activeByDefault>true</activeByDefault>
    </activation>
    <properties>
        <datanucleus-maven-plugin.version>4.0.1</datanucleus-maven-plugin.version>
    </properties>
    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
                    <groupId>org.eclipse.m2e</groupId>
                    <artifactId>lifecycle-mapping</artifactId>
                    <version>1.0.0</version>
                    <configuration>
                        <lifecycleMappingMetadata>
                            <pluginExecutions>
                                <pluginExecution>
                                    <pluginExecutionFilter>
                                        <groupId>org.datanucleus</groupId>
                                        <artifactId>datanucleus-maven-plugin</artifactId>
                                        <versionRange>[${datanucleus-maven-plugin.version},)</versionRange>
                                        <goals>
                                            <goal>enhance</goal>
                                        </goals>
                                    </pluginExecutionFilter>
                                    <action>
                                        <ignore></ignore>
                                    </action>
                                </pluginExecution>
                            </pluginExecutions>
                        </lifecycleMappingMetadata>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.datanucleus</groupId>
                <artifactId>datanucleus-maven-plugin</artifactId>
                <version>${datanucleus-maven-plugin.version}</version>
                <configuration>
                    <fork>false</fork>
                    <log4jConfiguration>${basedir}/log4j.properties</log4jConfiguration>
                    <verbose>true</verbose>
                    <props>${basedir}/datanucleus.properties</props>
                </configuration>
                <executions>
                    <execution>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>enhance</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.datanucleus</groupId>
            <artifactId>datanucleus-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.datanucleus</groupId>
            <artifactId>datanucleus-jodatime</artifactId>
        </dependency>
        <dependency>
            <groupId>org.datanucleus</groupId>
            <artifactId>datanucleus-api-jdo</artifactId>
        </dependency>
    </dependencies>
</profile>

If you don’t use Eclipse then you can omit the org.eclipse.m2e plugin in <pluginManagement>.

In the webapp’s persistor_datanucleus.properties

in src/main/webapp/WEB-INF/,

change:

isis.persistor.datanucleus.impl.datanucleus.autoCreateSchema=true
isis.persistor.datanucleus.impl.datanucleus.validateTables=true
isis.persistor.datanucleus.impl.datanucleus.validateConstraints=true

to:

isis.persistor.datanucleus.impl.datanucleus.schema.autoCreateAll=true
isis.persistor.datanucleus.impl.datanucleus.schema.validateTables=true
isis.persistor.datanucleus.impl.datanucleus.schema.validateConstraints=true

Previously Apache Isis would automatically add the auto-create property if they were absent from isis.properties, set to "true". The framework does still add the property, but now sets it to "false". This is to prevent the framework from unexpectedly modifying a target database if the application was misconfigured and the auto-create property not defined.

The framework will also automatically add the auto-validate property. Previously this was set to "true" and it is still set to "true"; there is no risk of the target database being modified as a result of this auto-validate property being defaulted by the framework.

Setting autoCreateAll to true is important to do when running with an in-memory database. If you don’t do this then the tables will be created lazily anyway by DataNucleus, but in some circumstances this can lead to deadlocks.

In addition, change:

isis.persistor.datanucleus.impl.datanucleus.identifier.case=PreserveCase

to:

isis.persistor.datanucleus.impl.datanucleus.identifier.case=MixedCase

Run mvn clean !

Be careful to ensure that your classes are only enhanced by the DataNucleus 4 enhancer, and not by the DataNucleus 3 enhancer. Or even, be careful that they are not doubly enhanced. One of our committers had this situation and it led to all sorts of bizarre issues. The solution, it turned out, was actually just to do a full mvn clean.

If you are struggling and suspect you may have misconfigured the enhancer plugin, then you can decompile the bytecode (eg in IntelliJ) and take a look:

  • A class enhanced with DataNucleus 3 would implement javax.jdo.spi.PersistenceCapable interface

  • A class enhanced with DataNucleus 4 will implement org.datanucleus.enhancer.Persistable.

Specify all dom packages

Apache Isis automatically scans for certain classes on the classpath in order to configure itself. Specifically these are:

For the last of these we have tightened up the validation, to ensure that each package specified in the isis.persistor.datanucleus.RegisterEntities.packagePrefix key does indeed include at least one annotated entity. This should include any domain classes for addon modules.

For example, the (non-ASF) Isis addons' todoapp's configuration now reads:

isis.persistor.datanucleus.RegisterEntities.packagePrefix=\
                todoapp.dom.module,\
                org.isisaddons.module.security.dom,\
                org.isisaddons.module.settings.dom,\
                org.isisaddons.module.sessionlogger.dom,\
                org.isisaddons.module.command.dom,\
                org.isisaddons.module.audit.dom,\
                org.isisaddons.module.publishing.dom

Alternatively, could have just specified org.isisaddons.module instead of enumerating every addon. This would be a bit slower, but more maintainable.

If you fail to do specify all packages things may still work, however DataNucleus will build up its metamodel lazily. This can call issues: we’ve seen malformed SQL being submitted when DN wasn’t aware of subclasses of a superclass, and we’ve also seen deadlocks when running against HSQLDB as it attempts to perform a DDL statement intermixed with DML statements.

Upgrading to Java 8

Apache Isis 1.9.0 is the first version to support Java 8. You can continue to use Java 7, but if you want to move to Java 8 then there are several small changes to be made.

In the parent pom.xml

under build/pluginManagement/plugins, add (or update) maven-compiler-plugin:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <compilerArgument>-parameters</compilerArgument>
    </configuration>
    <executions>
        <execution>
            <id>source</id>
            <phase>compile</phase>
        </execution>
        <execution>
            <id>test</id>
            <phase>test-compile</phase>
        </execution>
    </executions>
</plugin>

The -parameters argument causes the Java compiler to capture the names of method parameters in the .class files. Apache Isis can be configured to use this, thereby avoiding the requirement to annotate every parameter with @ParameterLayout(named=…​) or @Named(). The necessary configuration is provided in an Isis addons' paraname8 metamodel extension (non-ASF).

We also recommend that you add the maven-enforcer-plugin (if not used already). Again, this resides under <build>/<pluginManagement>/<plugins>:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-enforcer-plugin</artifactId>
    <version>1.3.1</version>
    <configuration>
        <rules>
            <requireMavenVersion>
                <version>[3.2.1,)</version>
            </requireMavenVersion>
            <requireJavaVersion>
                <version>[1.8.0,)</version>
            </requireJavaVersion>
            <requirePluginVersions>
                <message>All plugin versions must be defined!</message>
                <banLatest>true</banLatest>
                <banRelease>true</banRelease>
            </requirePluginVersions>
            <DependencyConvergence />
        </rules>
    </configuration>
    <executions>
        <execution>
            <id>validate-enforce</id>
            <phase>validate</phase>
            <goals>
                <goal>enforce</goal>
            </goals>
        </execution>
    </executions>
</plugin>

ExceptionRecognizerCompositeForJdoObjectStore

The ExceptionRecognizerCompositeForJdoObjectStore service (an implementation of the ExceptionRecognizer SPI) recognizes certain expected exceptions thrown by the JDO objectstore (for example, violations of uniqueness) and converts them into meaningful messages for the end-user.

Prior to 1.9.0 this implementation was not annotated with @DomainService and thus needed to be explicitly registered in isis.properties.

In 1.9.0 the service has been annotated with @DomainService meaning that:

  • it must be removed from isis.services property in isis.properties configuration file

  • in integration tests, if the service is explicitly registered, then it should be removed; for example:

    public class EstatioIntegTestBuilder extends IsisSystemForTest.Builder {
        public EstatioIntegTestBuilder() {
            ...
            withServices(
            // new ExceptionRecognizerCompositeForJdoObjectStore() (1)
            );
        }
        ...
    }
    1 remove this line (or comment it out, as shown)

If you fail to do this you will get an exception to the effect of duplicate service Ids being registered.

Now that the ExceptionRecognizerCompositeForJdoObjectStore no longer needs to be explicitly registered, you might (very rarely) require the opposite situation, namely to disable the service. As this can’t be done by just removing it from isis.properties, you instead can set a new configuration property isis.services.ExceptionRecognizerCompositeForJdoObjectStore.disable:

#isis.services.ExceptionRecognizerCompositeForJdoObjectStore.disable=false

If you did not register this service directly but instead registered a subclass of this service, then you should refactor your code so that your implementation is in a separate service, eg by subclassing ExceptionRecognizerComposite. You should probably also annotate with @DomainService.

FixtureScriptsSpecificationProvider

The FixtureScriptsSpecificationProvider SPI service is an alternative to subclassing the FixtureScripts domain service. The logic that would normally be in the subclass moves to the provider service instead, and the framework instantiates a fallback default instance, FixtureScriptsDefault.

This new design is optional; if you continue to provide your own subclass then everything will continue as before. However the new design is more flexible and involves less code.

See user guide for further discussion.

War packaging

As discussed in SimpleApp archetype and elsewhere, the org.apache.isis.WebServer provides the ability to run your app from an embedded jetty. This is great for prototyping. The class resides in the isis-core-webserver module, which also has the dependency on jetty.

In 1.9.0 we have upgraded the jetty dependency to use Jetty 9.2.0 (org.eclipse.jetty.aggregate:jetty-all:9.2.11.v20150529, to be precise). One consequence of this is that the packaged WAR file will not boot on Tomcat.

One fix is to simply remove the isis-core-webserver module as a dependency of your webapp module, however this will prevent you from using our org.apache.isis.WebServer launcher. That’s not necessarily a bad thing; you could continue to use jetty:run, say. But it might be a change to your development workflow that you don’t want.

Alternatively you can change your webapp’s pom.xml so that when the war is packaged up it excludes the jetty files. To do this, locate the maven-war-plugin module definition (under <build>/<plugins> and add to its <configuration> section:

<plugin>
    <artifactId>maven-war-plugin</artifactId>
    <configuration>
        ...
        <packagingExcludes>
            WEB-INF/lib/isis-core-webserver*.jar,
            WEB-INF/lib/javax.servlet-api-*.jar,
            WEB-INF/lib/javax.websocket-api-*.jar,
            WEB-INF/lib/jetty-all-*.jar
        </packagingExcludes>
    </configuration>
</plugin>

For future projects the SimpleApp archetype has been updated with this change.

Bootstrapping using AppManifest

Apache Isis 1.9.0 provides a simplified programmatic way of bootstrapping the application, that also unifies bootstrapping for integration tests.

For now this new bootstrapping mechanism is optional (you don’t have to change your code), but it may become mandatory in future releases. The SimpleApp archetype has been updated to use this new mechanism.

The instructions below assume that your application is structured as per the simpleapp archetype. Adjust accordingly.

myapp-dom Module

In your myapp-dom module (containing definitions of your persistent entities and domain services), create an empty class to represent the module. This should be at the root package for the domain, eg:

package myapp.dom;
public final class MyAppDomainModule {
    private MyAppDomainModule(){}
}

Since there is no requirement to actually instantiate this class (it merely provides the location of the myapp.dom package), we give it a private constructor.

If you have any other modules where you have either domain services or entities, similarly create an empty "module" class.

myapp-fixture Module

Similarly, in your myapp-fixture module (containing fixture scripts used for testing and demos), do likewise:

package myapp.fixture;
public class MyAppFixtureModule {
    private MyAppFixtureModule(){}
}

myapp-app Maven Module

Create a new myapp-app Maven module:

  • in its pom.xml, reference myapp-fixture

    <dependency>
        <groupId>${project.groupId}</groupId>
        <artifactId>myapp-fixture</artifactId>
    </dependency>

    Since myapp-fixture will reference myapp-dom there’s no need for a direct reference to myapp-dom

  • also add in dependencies to the core framework:

    <dependency>
        <groupId>org.apache.isis.core</groupId>
        <artifactId>isis-core-wrapper</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.isis.core</groupId>
        <artifactId>isis-core-runtime</artifactId>
    </dependency>
  • if your application uses any of the (non-ASF) Isis Addons modules, then add dependencies to these modules in the pom.xml. You should be able to copy-and-paste the dependencies from the pom.xml of your myapp-webapp module.

Create a module class for the myapp module also:

package myapp.app;
public final class MyAppAppModule {
    private MyAppAppModule() {}
}

Next, create an AppManifest implementation, eg:

package myapp.app;
public class MyAppAppManifest implements AppManifest {
    @Override
    public List<Class<?>> getModules() {                             (1)
        return Arrays.asList(
                MyAppDomainModule.class,
                MyAppFixtureModule.class,
                MyAppAppModule.class
        );
    }
    @Override
    public List<Class<?>> getAdditionalServices() { return null; }  (2)
    @Override
    public String getAuthenticationMechanism() { return null; }
    @Override
    public String getAuthorizationMechanism() { return null; }
    @Override
    public List<Class<? extends FixtureScript>> getFixtures() { return null; }
    @Override
    public Map<String, String> getConfigurationProperties() { return null; }
}
1 the module classes, whose packages specify the existence of domain services and/or persistent entities. If your app uses (non-ASF) Isis Addons modules, then include the module classes for these addons in getModules(). For example, the (non-ASF) Isis addons' security module provides the org.isisaddons.module.security.SecurityModule class.
2 any additional services, as per isis.services configuration property.

For details of the usages of the other methods in this interface, see the reference guide documentation.

If in your myapp-dom module you have application-level services and view models (services that depend on persistent domain entities but not the other way around), then we recommend that you move this code to the new myapp-app module. This makes the layering clearer, and avoids circular dependencies between application-layer vs domain-layer logic.

Update parent

in the parent pom.xml, declare and reference the new myapp-app module:

<dependencyManagement>
    <dependencies>
        ...
        <dependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>myapp-app</artifactId>
            <version>${project.version}</version>
        </dependency>
        ...
    </dependencies>
</dependencyManagement>

<modules>
    <module>app</module>
    ...
</modules>

Update myapp-integtests

In its pom.xml:

  • add a dependency on myapp-app

  • remove dependency on myapp-fixture (and on myapp-dom, if present)

  • remove dependencies on isis-core-wrapper and isis-core-runtime (since now obtained transitively from myapp-app)

Also update (simplify) MyAppSystemInitializer to use the new AppManifest, eg:

public class MyAppSystemInitializer {
    public static void initIsft() {
        IsisSystemForTest isft = IsisSystemForTest.getElseNull();
        if(isft == null) {
            isft = new IsisSystemForTest.Builder()
                    .withLoggingAt(org.apache.log4j.Level.INFO)
                    .with(new DomainAppAppManifest())                   (1)
                    .with(new IsisConfigurationForJdoIntegTests())      (2)
                    .build()
                    .setUpSystem();
            IsisSystemForTest.set(isft);
        }
    }
}
1 bootstrapping using the new AppManifest implementation
2 if your bootstrapping previously explicitly overrode certain configuration properties, this can instead be moved to the getConfigurationProperties() method of your AppManifest implementation.

Update myapp-webapp

In its pom.xml:

  • add a dependency on myapp-app

  • remove dependency on myapp-fixture (and on myapp-dom, if present)

  • remove dependencies on isis-core-wrapper and isis-core-runtime (since now obtained transitively from myapp-app)

  • (if you didn’t previously), move any dependencies to addons or other services referenced in the AppManifest to the pom.xml of the new myapp-app module.

Remove configuration properties that are no longer needed:

  • in isis.properties:

    • remove isis.services-installer

    • remove isis.services.ServicesInstallerFromAnnotation.packagePrefix

    • remove isis.services

  • in persistor_datanucleus.properties

    • remove isis.persistor.datanucleus.RegisterEntities.packagePrefix

Finally, specify the AppManifest to use to bootstrap the app. You have a choice here:

  • either update isis.properties, using the isis.appManifest key to specify the AppManifest implementation, eg:

    isis.appManifest=domainapp.app.DomainAppAppManifest
  • alternatively, specify the AppManifest by overriding the IsisWicketApplication#newWicketModule(), eg:

    @Override
    protected Module newIsisWicketModule() {
        final Module isisDefaults = super.newIsisWicketModule();
        ...
        final Module overrides = new AbstractModule() {
            @Override
            protected void configure() {
                ...
                bind(AppManifest.class).toInstance(new DomainAppAppManifest());
            }
        };
    
        return Modules.override(isisDefaults).with(overrides);
    }

If the second (programmatic) approach is used, this overrides the first approach (using isis.properties).

From v1.7.0 to 1.8.0

Existing projects written against v1.7.0 should run against v1.8.0 without any changes. In particular (unlike 1.6.0 and 1.7.0) there should be no need to update pom.xml files of existing projects. If you do encounter any difficulties then let us know via the users mailing list, so we can support you and document issues here.

That said, many of the existing annotations have been deprecated in 1.8.0, replaced with a simplified and rationalized set of annotations; see here. To help you migrate your application over to the new annotations, there is a new configuration property that can be set in isis.properties:

isis.reflector.validator.allowDeprecated=false

If this flag is present and set to false, then metamodel validation errors will be thrown on startup if any deprecated annotations are encountered. These can be viewed either in the console or by browsing to the app (an error page will be displayed).

From v1.6.0 to 1.7.0

In v1.7.0 we’ve continued the work started in v1.6.0 in modularizing the framework. The most important change to note is that all Apache Isis core modules (with the Maven groupId of org.apache.isis.module have now MOVED to Isis Addons.

In addition, we’ve retired some obsolete (and unused) functionality, specifically the ProfileStore component.

To move up amounts to changing POM files and, where required, updating package names for any referenced modules.

Reorganized 'modules'

The following modules are no longer released as part of Apache Isis core and have moved to Isis Addons (or in one case, back into Apache Isis core).

Minor changes are required to pom.xml files and (in some cases) to isis.properties config file.

In one or two exceptional cases it may be necessary to fix up import statements if there are reference to changed package/class names in code (most likely any dependency on the devutils module or settings module).

Audit module

In pom.xml, replace:

<dependency>
    <groupId>org.apache.isis.module</groupId>
    <artifactId>isis-module-audit-jdo</artifactId>
</dependency>

with:

<dependency>
    <groupId>org.isisaddons.module.audit</groupId>
    <artifactId>isis-module-audit-dom</artifactId>
</dependency>

If necessary, also update any services registered in isis.properties (package/class names may have changed slightly).

Command module

In pom.xml, replace:

<dependency>
    <groupId>org.apache.isis.module</groupId>
    <artifactId>isis-module-command-jdo</artifactId>
</dependency>

with:

<dependency>
    <groupId>org.isisaddons.module.command</groupId>
    <artifactId>isis-module-command-dom</artifactId>
</dependency>

If necessary, also update any services registered in isis.properties (package/class names may have changed slightly).

DevUtils module

In pom.xml, replace:

<dependency>
    <groupId>org.apache.isis.module</groupId>
    <artifactId>isis-module-devutils-applib</artifactId>
</dependency>

with:

<dependency>
    <groupId>org.isisaddons.module.devutils</groupId>
    <artifactId>isis-module-devutils-dom</artifactId>
</dependency>

Remove any references to:

<dependency>
    <groupId>org.apache.isis.module</groupId>
    <artifactId>isis-module-devutils</artifactId>
</dependency>

or to:

<dependency>
    <groupId>org.apache.isis.module</groupId>
    <artifactId>isis-module-devutils-impl</artifactId>
</dependency>

These modules are no longer required (the org.apache.isis.module:isis-module-devutils-applib and org.apache.isis.module:isis-module-devutils-impl submodules have been combined into the new org.isisaddons.module.devutils:isis-module-devutils-dom module).

If necessary, also update any services registered in isis.properties (package/class names may have changed slightly).

Publishing module

In pom.xml, replace:

<dependency>
    <groupId>org.apache.isis.module</groupId>
    <artifactId>isis-module-publishing-jdo</artifactId>
</dependency>

with:

<dependency>
    <groupId>org.isisaddons.module.publishing</groupId>
    <artifactId>isis-module-publishing-dom</artifactId>
</dependency>

If necessary, also update any services registered in isis.properties (package/class names may have changed slightly).

Publishing Event Serializer RO module

Remove any references to:

<dependency>
    <groupId>org.apache.isis.module</groupId>
    <artifactId>isis-module-publishingeventserializer-ro</artifactId>
</dependency>

This module has been merged with org.isisaddons.module.publishing:isis-module-publishing-dom, above.

Settings module

In pom.xml, replace:

<dependency>
    <groupId>org.apache.isis.module</groupId>
    <artifactId>isis-module-settings-applib</artifactId>
</dependency>

with:

<dependency>
    <groupId>org.isisaddons.module.settings</groupId>
    <artifactId>isis-module-settings-dom</artifactId>
</dependency>

Remove any references to:

<dependency>
    <groupId>org.apache.isis.module</groupId>
    <artifactId>isis-module-settings</artifactId>
</dependency>

or to:

<dependency>
    <groupId>org.apache.isis.module</groupId>
    <artifactId>isis-module-settings-impl</artifactId>
</dependency>

These modules are no longer required (the org.apache.isis.module:isis-module-settings-applib and org.apache.isis.module:isis-module-settings-impl submodules have been combined into the new org.isisaddons.module.settings:isis-module-settings-dom module).

If necessary, also update any services registered in isis.properties (package/class names may have changed slightly).

Background module

In pom.xml, remove:

<dependency>
    <groupId>org.apache.isis.module</groupId>
    <artifactId>isis-module-background</artifactId>
</dependency>

The service classes have been moved into existing org.apache.isis.core:isis-core-runtime Maven module (that is, already be referenced in the pom.xml).

If necessary, also update any services registered in isis.properties (package/class names may have changed slightly).

Retired ProfileStore component

As per ISIS-802, the ProfileStore component has been removed. This functionality was not surfaced or available in the Wicket or Restful Objects viewers, so there is no meaningful loss of functionality. However, Maven pom.xml files will require updating:

Specifically, remove any dependencies on org.apache.isis:isis-core-profilestore:

<dependency>
    <groupId>org.apache.isis.core</groupId>
    <artifactId>isis-core-profilestore</artifactId>
</dependency>

A number of corresponding classes/interfaces have also been removed from the Apache Isis applib:

  • org.apache.isis.applib.fixtures.userprofile.UserProfileService

  • org.apache.isis.applib.fixtures.userprofile.UserProfileServiceAware

  • org.apache.isis.applib.fixtures.UserProfileFixture

  • org.apache.isis.applib.profiles.Profile

  • org.apache.isis.applib.profiles.Perspective

It is highly unlikely that any existing production code references these classes.


Copyright © 2010~2017 The Apache Software Foundation, licensed under the Apache License, v2.0.
Apache, the Apache feather logo, Apache Isis, and the Apache Isis project logo are all trademarks of The Apache Software Foundation.