<groupId>org.apache.isis.viewer</groupId>
<artifactId>isis-viewer-wicket-applib</artifactId>
Consult these notes when migrating to new versions of the framework.
isis-mavendeps
Aggregator POMsTo remove boilerplate in your application’s pom.xml
, three new maven "aggregator projects have been defined:
org.apache.isis.mavendeps:isis-mavendeps-testing
aggregates dependencies for unit, integration and BDD tests
org.apache.isis.mavendeps:isis-mavendeps-webapp
aggregates dependencies for running as a webapp
org.apache.isis.mavendeps:isis-mavendeps-intellij
brings in a dependency on isis-core-webserver
(to run the application from the command line using org.apache.isis.WebServer
). This is defined in a profile which is actived only when running under the Intellij IDE.
The HelloWorld and SimpleApp archetypes both make use of these new aggregators.
The <groupId>
and <artifactId>
of the Wicket viewer have been made consistent with other artifacts:
the <groupId>
has been changed from org.apache.isis.viewer
to org.apache.isis.core
the <artifactId>
has been changed from isis-viewer-wicket-???
to isis-core-viewer-wicket-???
For example:
<groupId>org.apache.isis.viewer</groupId>
<artifactId>isis-viewer-wicket-applib</artifactId>
has been renamed to:
<groupId>org.apache.isis.core</groupId>
<artifactId>isis-core-viewer-wicket-applib</artifactId>
Domain services fall into three categories:
application services: written by the application developer and used only within the application
SPI services: written by the application developer but called by the framework
framework services: defined within the applib with a default implementation provided by the framework itself.
As described here, it is possible to override framework services so that the framework uses the replacement implementation. Previously this required explicitly setting either @DomainService#menuOrder()
or @DomainServiceLayout#menuOrder()
.
In 1.15.0, the default value for menuOrder
has been set to a value lower than that of the framework-provided implementations, and so will a custom implementation will always take precedence over the framework implementations without having to remember to also set menuOrder
.
Of course, your application can still override menuOrder
if it wishes. A small change (made in (ISIS-1688) is that if both are set, then the minimum value is used.
The metamodel validator has been extended with several new checks relating to JAXB view models:
that the view model can be instantiated:
has a public, no-arg constructor
is not abstract
is not a member inner class (nested static class is ok)
that JODA datetimes are annotated with the appropriate implementation of a JAXB XmlAdapter
that for references to persistent entities, that those persistent entities are annotated to use PersistentEntityAdapter
as their JAXB adapter.
... in other words, that the view model can be instantiated.
These checks are enabled by default but can be disabled with a configuration property if required.
ISIS-1613
improves the UI so that the framework does not repaint the entire page after a property edit or after invoking an action that returns the same object (this
). The overall effect is a smoother user experience.
However, it also results in "WARN" messages being emitted by Apache Wicket. These are not harmful, but may pollute the log.
To remove them, add the following to logging.properties
:
log4j.logger.org.apache.wicket.page.XmlPartialPageUpdate=ERROR,console
log4j.additivity.org.apache.wicket.page.XmlPartialPageUpdate=false
Bootstrapping the application can now be accomplished with less boilerplate, both for the regular webapp and in integration tests.
For more information, see the testing guide and reference guide for classes/methods/schema.
This ticket fixed a bug whereby - in the absence of an explicit @Property(optionality=…)
or @Nullable
annotation, a view model’s properties would be defaulted as optional rather than mandatory.
Note also that this bug fix means that numeric properties (eg java.lang.Integer
and java.lang.BigDecimal
) will default to zero if the view model is instantiated using FactoryService#instantiate(…)
, and dates (eg java.util.Date
and org.jodatime.LocalDate
) will default to the current date. This could cause your application to behave differently.
You should therefore inspect all properties of your view models and ensure that they are annotated as optional if required.
The configuration property isis.reflector.validator.jdoqlVariablesClause
was incorrectly named variablesClause
. This has now been corrected.
Any applications that used this configuration property should be updated.
@PostConstruct
always called (ISIS-1690)In previous versions, if any domain service threw an exception in their initialization method (annotated @PostConstruct
) then none of the remaining domain services would be initialized. Even though the failing service would cause an error to be logged during start-up, this could still manifest as the application starting (in a fashion) but then failing in unrelated areas later on.
As of this version, the framework now always calls ensures that all services are initialized, even if one or more of them throw an exception. The first exception encountered is then re-thrown (to preserve similar behaviour as possible to earlier versions).
The various (non-ASF) Isis Addons and Incode Catalog have also been combined into a single "Incode Platform".
While each module can still be consumed individually, the new platform versions consistently (a change in any one module will result in a re-release of all). This should make these modules easier to consume, and easier to maintain/develop.
All the modules remain open source, still licensed under the ASF v2.0 license.
As of this release, none of the groupId
s or artifactId
s have changed. They will be rationalized/made consistent in a future release; most probably to coincide with v2.0.0 of the framework.
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.
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.
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.
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) Incode Platform's audit module also implements the new SPI.
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) Incode Platform's 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.
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
.
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).
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.
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.
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.
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
.
There are two sets of changes relating to integration tests.
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()
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);
}
}
}
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
mixinThe 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.
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.
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.
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.
(As mentioned above), 1.12.0 provides a number of new mixin actions and properties:
clear hints action
download Layout XML action (prototype mode)
rebuild metamodel action (prototype mode)
id and version properties (for domain entities only)
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.
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 serviceThe DomainObjectContainer
domain 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_core-domain-api_DomainObjectContainer_object-persistence-api.adoc#_rgsvc_core-domain-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 DomainObjectContainer#persistIfNotAlready()
.
self-host
profileThe 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
removedThe 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.
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.
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; }
}
The Wicket viewer (its labels, buttons, messages etc) can now be internationalized using the TranslationService
.
To enable this, new msgId
s and corresponding translations must be added to the translations.po
file. Full details of these msgId
s 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.
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.
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) Incode Platform's 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.
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() { ... }
}
The way that the Isis Maven plugin is configured has changed slightly; check out its documentation for full details.
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.
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>
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>
.
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 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 |
In addition, change:
isis.persistor.datanucleus.impl.datanucleus.identifier.case=PreserveCase
to:
isis.persistor.datanucleus.impl.datanucleus.identifier.case=MixedCase
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
.
dom
packagesApache Isis automatically scans for certain classes on the classpath in order to configure itself. Specifically these are:
searching for classes annotated with @DomainService
.
searching for classes extending FixtureScript
searching for classes annotated with @PersistenceCapable
.
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 |
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.
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.
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 |
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.
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.
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
ModuleIn 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
ModuleSimilarly, 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 ModuleCreate a new myapp-app
Maven module:
in its pom.xml
, reference myapp-fixture
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>myapp-fixture</artifactId>
</dependency>
Since |
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) Incode Platform's 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.
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>
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. |
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
).
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).
In 1.7.0
we’ve continued the work started in 1.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.
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).
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).
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).
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).
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).
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.
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).
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).
ProfileStore
componentAs 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.