You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2020/01/20 23:46:14 UTC

[isis] 01/03: ISIS-2062: adds documentation for config props

This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 7cd2f935a0571c6da125ead23b26b67d3f3cba28
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Mon Jan 20 19:34:38 2020 +0000

    ISIS-2062: adds documentation for config props
---
 .../apache/isis/core/config/IsisConfiguration.java | 366 ++++++++++++++++++++-
 .../runtimeservices/email/EmailServiceDefault.java |  19 +-
 .../email/EmailServiceDefaultTest_actually.java    |   6 +-
 .../flyway/adoc/modules/flyway/pages/about.adoc    |   2 +-
 ...entNegotiationServiceForRestfulObjectsV1_0.java |  16 +-
 5 files changed, 383 insertions(+), 26 deletions(-)

diff --git a/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java b/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java
index 0a36b62..63385a7 100644
--- a/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java
+++ b/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java
@@ -31,6 +31,7 @@ import java.util.Optional;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
+import javax.activation.DataSource;
 import javax.inject.Inject;
 import javax.inject.Named;
 import javax.validation.constraints.NotEmpty;
@@ -1353,17 +1354,50 @@ public class IsisConfiguration {
                 private final JaxbViewModel jaxbViewModel = new JaxbViewModel();
                 @Data
                 public static class JaxbViewModel {
+                    /**
+                     * If set, then ensures that all JAXB-style view models are concrete classes, not abstract.
+                     */
                     private boolean notAbstract = true;
+                    /**
+                     * If set, then ensures that all JAXB-style view models are either top-level classes or nested
+                     * static classes (in other words, checks that they are not anonymous, local nor nested
+                     * non-static classes).
+                     */
                     private boolean notInnerClass = true;
+                    /**
+                     * If set, then ensures that all JAXB-style view models have a no-arg constructor.
+                     */
                     private boolean noArgConstructor = false;
+                    /**
+                     * If set, then ensures that for all properties of JAXB-style view models where the property's type
+                     * is an entity, then that entity's type has been correctly annotated with
+                     * @{@link javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter} (so that the property's value can
+                     * be converted into a serializable form).
+                     */
                     private boolean referenceTypeAdapter = true;
+                    /**
+                     * If set, then ensures that for all properties of JAXB-style view models where the property's type
+                     * is a date or time, then that property has been correctly annotated with
+                     * @{@link javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter} (so that the property's value can
+                     * be converted into a serializable form).
+                     */
                     private boolean dateTimeTypeAdapter = true;
                 }
 
                 private final Jdoql jdoql = new Jdoql();
                 @Data
                 public static class Jdoql {
+                    /**
+                     * If set, then ensures that the 'FROM' clause within any JDOQL <code>@Query</code>s annotations
+                     * relates to a known entity type, and moreover that that type is compatible with the type on
+                     * which the annotation appears: meaning its either a supertype of or the same type as the
+                     * annotated type.
+                     */
                     private boolean fromClause = true;
+                    /**
+                     * If set, then ensures that the 'VARIABLES' clause within any JDOQL <code>@Query</code>s relates
+                     * to a known entity type.
+                     */
                     private boolean variablesClause = true;
                 }
             }
@@ -1375,11 +1409,13 @@ public class IsisConfiguration {
         public static class Runtime {
 
             /**
-             * Set to override {@link Locale#getDefault()}
+             * If set, then overrides the application's {@link Locale#getDefault()}
              */
             private Optional<String> locale = Optional.empty();
 
-            //TODO no meta data yet ... https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-configuration-metadata.html#configuration-metadata-property-attributes
+            /**
+             * If set, then override's the application's timezone.
+             */
             private String timezone;
 
         }
@@ -1391,18 +1427,45 @@ public class IsisConfiguration {
             private final Email email = new Email();
             @Data
             public static class Email {
+                /**
+                 * The port to use for sending email.
+                 */
                 private int port = 587;
+                /**
+                 * The maximum number of millseconds to wait to obtain a socket connection before timing out.
+                 */
                 private int socketConnectionTimeout = 2000;
+                /**
+                 * The maximum number of millseconds to wait to obtain a socket before timing out.
+                 */
                 private int socketTimeout = 2000;
+                /**
+                 * If an email fails to send, whether to propagate the exception (meaning that potentially the end-user
+                 * might see the exception), or whether instead to just indicate failure through the return value of
+                 * the method ({@link org.apache.isis.applib.services.email.EmailService#send(List, List, List, String, String, DataSource...))
+                 * that's being called.
+                 */
                 private boolean throwExceptionOnFail = true;
 
                 private final Override override = new Override();
                 @Data
                 public static class Override {
+                    /**
+                     * Intended for testing purposes only, if set then the requested <code>to:</code> of the email will
+                     * be ignored, and instead sent to this email address instead.
+                     */
                     @javax.validation.constraints.Email
                     private String to;
+                    /**
+                     * Intended for testing purposes only, if set then the requested <code>cc:</code> of the email will
+                     * be ignored, and instead sent to this email address instead.
+                     */
                     @javax.validation.constraints.Email
                     private String cc;
+                    /**
+                     * Intended for testing purposes only, if set then the requested <code>bcc:</code> of the email will
+                     * be ignored, and instead sent to this email address instead.
+                     */
                     @javax.validation.constraints.Email
                     private String bcc;
                 }
@@ -1410,9 +1473,46 @@ public class IsisConfiguration {
                 private final Sender sender = new Sender();
                 @Data
                 public static class Sender {
+                    /**
+                     * Specifies the host running the SMTP service.
+                     *
+                     * <p>
+                     *     If not specified, then the value used depends upon the email implementation.  The default
+                     *     implementation will use the <code>mail.smtp.host</code> system property.
+                     * </p>
+                     */
                     private String hostname;
+                    /**
+                     * Specifies the username to use to connect to the SMTP service.
+                     *
+                     * <p>
+                     *     If not specified, then the sender's {@link #getAddress() email address} will be used instead.
+                     * </p>
+                     */
                     private String username;
+                    /**
+                     * Specifies the password (corresponding to the {@link #getUsername() username} to connect to the
+                     * SMTP service.
+                     *
+                     * <p>
+                     *     This configuration property is mandatory (for the default implementation of the
+                     *     {@link org.apache.isis.applib.services.email.EmailService}, at least).
+                     * </p>
+                     */
                     private String password;
+                    /**
+                     * Specifies the email address of the user sending the email.
+                     *
+                     * <p>
+                     *     If the {@link #getUsername() username} is not specified, is also used as the username to
+                     *     connect to the SMTP service.
+                     * </p>
+                     *
+                     * <p>
+                     *     This configuration property is mandatory (for the default implementation of the
+                     *     {@link org.apache.isis.applib.services.email.EmailService}, at least).
+                     * </p>
+                     */
                     @javax.validation.constraints.Email
                     private String address;
                 }
@@ -1420,6 +1520,9 @@ public class IsisConfiguration {
                 private final Tls tls = new Tls();
                 @Data
                 public static class Tls {
+                    /**
+                     * Whether TLS encryption should be started (that is, <code>STARTTLS</code>).
+                     */
                     private boolean enabled = true;
                 }
             }
@@ -1427,6 +1530,12 @@ public class IsisConfiguration {
             private final ApplicationFeatures applicationFeatures = new ApplicationFeatures();
             @Data
             public static class ApplicationFeatures {
+                /**
+                 * Whether the {@link org.apache.isis.applib.services.appfeat.ApplicationFeatureRepository} (or the
+                 * default implementation of that service, at least) should compute the set of
+                 * <code>ApplicationFeature</code> that describe the metamodel
+                 * {@link ApplicationFeaturesInitConfiguration#EAGERLY eagerly}, or lazily.
+                 */
                 ApplicationFeaturesInitConfiguration init = ApplicationFeaturesInitConfiguration.NOT_SPECIFIED;
             }
 
@@ -1460,6 +1569,12 @@ public class IsisConfiguration {
                 private final Jdo jdo = new Jdo();
                 @Data
                 public static class Jdo {
+                    /**
+                     * Whether the {@link org.apache.isis.applib.services.exceprecog.ExceptionRecognizer}
+                     * implementation for JDO/DataNucleus object store - which attempts to sanitize any exceptions
+                     * arising from that object store - should be disabled (meaning that exceptions will potentially
+                     * propagate as more serious to the end user).
+                     */
                     private boolean disable = false;
                 }
             }
@@ -1472,10 +1587,39 @@ public class IsisConfiguration {
 
                 @Data
                 public static class Po {
+                    /**
+                     * Specifies the initial mode for obtaining/discovering translations.
+                     *
+                     * <p>
+                     *     There are three modes:
+                     *     <ul>
+                     *         <li>
+                     *              <p>
+                     *                  The default mode of {@link TranslationService.Mode#WRITE write} is appropriate for
+                     *                  integration testing or prototyping, meaning that the service records any requests made of it
+                     *                  but just returns the string unaltered.  This is a good way to discover new strings that
+                     *                  require translation.
+                     *              </p>
+                     *         </li>
+                     *         <li>
+                     *              <p>
+                     *                  The {@link TranslationService.Mode#READ read} mode is appropriate for production; the
+                     *                  service looks up translations that have previously been captured.
+                     *              </p>
+                     *         </li>
+                     *         <li>
+                     *             <p>
+                     *                 The {@link TranslationService.Mode#DISABLED disabled} performs no translation
+                     *                 and simply returns the original string unchanged.  Unlike the write mode, it
+                     *                 does <i>not</i> keep track of translation requests.
+                     *             </p>
+                     *         </li>
+                     *     </ul>
+                     * </p>
+                     */
                     TranslationService.Mode mode = TranslationService.Mode.WRITE;
                 }
             }
-
         }
     }
 
@@ -1733,14 +1877,100 @@ public class IsisConfiguration {
         private final Restfulobjects restfulobjects = new Restfulobjects();
         @Data
         public static class Restfulobjects {
+
+            /**
+             * Whether to enable the <code>x-ro-follow-links</code> support, to minimize round trips.
+             *
+             * <p>
+             *     The RO viewer provides the capability for the client to set the optional
+             *     <code>x-ro-follow-links</code> query parameter, as described in section 34.4 of the RO spec v1.0.
+             *     If used, the resultant representation includes the result of following the associated link, but
+             *     through a server-side "join", somewhat akin to GraphQL.
+             * </p>
+             *
+             * <p>
+             *     By default this functionality is disabled, this configuration property enables the feature.
+             *     If enabled, then the representations returned are non-standard with respect to the RO Spec v1.0.
+             * </p>
+             */
             private boolean honorUiHints = false;
+
+            /**
+             * When rendering domain objects, if set the representation returned is stripped back to a minimal set,
+             * excluding links to actions and collections and with a simplified representation of an object's
+             * properties.
+             *
+             * <p>
+             *     This is disabled by default.  If enabled, then the representations returned are non-standard with
+             *     respect to the RO Spec v1.0.
+             * </p>
+             */
             private boolean objectPropertyValuesOnly = false;
+
+            /**
+             * If set, then any unrecognised <code>Accept</code> headers will result in an HTTP <i>Not Acceptable</i>
+             * response code (406).
+             */
             private boolean strictAcceptChecking = false;
+
+            /**
+             * If set, then the representations returned will omit any links to the formal domain-type representations.
+             */
             private boolean suppressDescribedByLinks = false;
+
+            /**
+             * If set, then - should there be an interaction with an action, property or collection that is disabled -
+             * then this will prevent the <code>disabledReason</code> reason from being added to the returned
+             * representation.
+             *
+             * <p>
+             *     This is disabled by default.  If enabled, then the representations returned are non-standard with
+             *     respect to the RO Spec v1.0.
+             * </p>
+             */
             private boolean suppressMemberDisabledReason = false;
+
+            /**
+             * If set, then the <code>x-isis-format</code> key (under <code>extensions</code>) for properties will be
+             * suppressed.
+             *
+             * <p>
+             *     This is disabled by default.  If enabled, then the representations returned are non-standard with
+             *     respect to the RO Spec v1.0.
+             * </p>
+             */
             private boolean suppressMemberExtensions = false;
+
+            /**
+             * If set, then the <code>id</code> key for all members will be suppressed.
+             *
+             * <p>
+             *     This is disabled by default.  If enabled, then the representations returned are non-standard with
+             *     respect to the RO Spec v1.0.
+             * </p>
+             */
             private boolean suppressMemberId = false;
+
+            /**
+             * If set, then the detail link (in other words <code>links[rel='details' ...]</code>) for all members
+             * will be suppressed.
+             *
+             * <p>
+             *     This is disabled by default.  If enabled, then the representations returned are non-standard with
+             *     respect to the RO Spec v1.0.
+             * </p>
+             */
             private boolean suppressMemberLinks = false;
+
+            /**
+             * If set, then the update link (in other words <code>links[rel='update'... ]</code> to perform a bulk
+             * update of an object) will be suppressed.
+             *
+             * <p>
+             *     This is disabled by default.  If enabled, then the representations returned are non-standard with
+             *     respect to the RO Spec v1.0.
+             * </p>
+             */
             private boolean suppressUpdateLink = false;
 
             /**
@@ -1758,9 +1988,16 @@ public class IsisConfiguration {
              */
             @javax.validation.constraints.Pattern(regexp="^http[s]?://[^:]+?(:\\d+)?/([^/]+/)*$")
             private Optional<String> baseUri = Optional.empty();
+
+            @Deprecated
             private final Gsoc2013 gsoc2013 = new Gsoc2013();
+            @Deprecated
             @Data
             public static class Gsoc2013 {
+                /**
+                 * @deprecated
+                 */
+                @Deprecated
                 private boolean legacyParamDetails = false;
             }
         }
@@ -1769,16 +2006,37 @@ public class IsisConfiguration {
         @Data
         public static class Wicket {
 
+            /**
+             * Specifies the subclass of <
+             * code>org.apache.isis.viewer.wicket.viewer.wicketapp.IsisWicketApplication</code> that is used to
+             * bootstrap Wicket.
+             *
+             * <p>
+             *     There is usually very little reason to change this from its default.
+             * </p>
+             */
             private String app = "org.apache.isis.viewer.wicket.viewer.wicketapp.IsisWicketApplication";
 
             /**
-             * Whether the Ajax debug should be shown.
+             * Whether the Ajax debug should be shown, by default this is disabled.
              */
             private boolean ajaxDebugMode = false;
 
+            /**
+             * The base path at which the Wicket viewer is mounted.
+             */
             @javax.validation.constraints.Pattern(regexp="^[/].*[/]$") @NotNull @NotEmpty
             private String basePath = "/wicket/";
 
+            /**
+             * If the end user uses a deep link to access the Wicket viewer, but is not authenticated, then this
+             * configuration property determines whether to continue through to that original destination once
+             * authenticated, or simply to go to the home page.
+             *
+             * <p>
+             *     The default behaviour is to honour the original destination requested.
+             * </p>
+             */
             private boolean clearOriginalDestination = false;
 
             /**
@@ -1807,27 +2065,84 @@ public class IsisConfiguration {
             @NotNull @NotEmpty
             private String dateTimePattern = "dd-MM-yyyy HH:mm";
 
+            /**
+             * Whether the dialog mode rendered when invoking actions on domain objects should be to use
+             * the sidebar (the default) or to use a modal dialog.
+             *
+             * <p>
+             *     This can be overridden on a case-by-case basis using {@link ActionLayout#promptStyle()}.
+             * </p>
+             */
             private DialogMode dialogMode = DialogMode.SIDEBAR;
 
+            /**
+             * Whether the dialog mode rendered when invoking actions on domain services (that is, menus) should be to
+             * use a modal dialog (the default) or to use the sidebar panel.
+             *
+             * <p>
+             *     This can be overridden on a case-by-case basis using {@link ActionLayout#promptStyle()}.
+             * </p>
+             */
             private DialogMode dialogModeForMenu = DialogMode.MODAL;
 
+            /**
+             * If specified, then is rendered on each page to enable live reload.
+             *
+             * <p>
+             *     Configuring live reload also requires an appropriate plugin to the web browser (eg see
+             *     <a href="http://livereload.com/">livereload.com</a> and a mechanism to trigger changes, eg by
+             *     watching <code>Xxx.layout.xml</code> files.
+             * </p>
+             */
             private Optional<String> liveReloadUrl = Optional.empty();
 
+            /**
+             * The maximum number of characters to use to render the title of a domain object (alongside the icon)
+             * in any table, if not otherwise overridden by either {@link #getMaxTitleLengthInParentedTables()}
+             * or {@link #getMaxTitleLengthInStandaloneTables()}.
+             *
+             * <p>
+             *     If truncated, then the remainder of the title will be replaced with ellipses (...).
+             * </p>
+             */
             private int maxTitleLengthInTables = 12;
 
             private Integer maxTitleLengthInParentedTables;
+
+            /**
+             * The maximum number of characters to use to render the title of a domain object (alongside the icon) in a
+             * parented table.
+             *
+             * <p>
+             *     If truncated, then the remainder of the title will be replaced with ellipses (...).
+             * </p>
+             *
+             * <p>
+             *     If not specified, then the value of {@link #getMaxTitleLengthInTables()} is used.
+             * </p>
+             */
             public int getMaxTitleLengthInParentedTables() {
                 return maxTitleLengthInParentedTables != null ? maxTitleLengthInParentedTables : getMaxTitleLengthInTables();
             }
-            /**
-             * The maximum length that a title of an object will be shown when rendered in a parented table;
-             * will be truncated beyond this (with ellipses to indicate the truncation).
-             */
+
             public void setMaxTitleLengthInParentedTables(final int val) {
                 maxTitleLengthInParentedTables = val;
             }
 
             private Integer maxTitleLengthInStandaloneTables;
+
+            /**
+             * The maximum number of characters to use to render the title of a domain object (alongside the icon)
+             * in a standalone table, ie the result of invoking an action.
+             *
+             * <p>
+             *     If truncated, then the remainder of the title will be replaced with ellipses (...).
+             * </p>
+             *
+             * <p>
+             *     If not specified, then the value of {@link #getMaxTitleLengthInTables()} is used.
+             * </p>
+             */
             public int getMaxTitleLengthInStandaloneTables() {
                 return maxTitleLengthInStandaloneTables != null ? maxTitleLengthInStandaloneTables : getMaxTitleLengthInTables();
             }
@@ -1841,11 +2156,16 @@ public class IsisConfiguration {
 
             /**
              * Whether to use a modal dialog for property edits and for actions associated with properties.
+             *
+             * <p>
              * This can be overridden on a case-by-case basis using <code>@PropertyLayout#promptStyle</code> and
              * <code>@ActionLayout#promptStyle</code>.
+             * </p>
              *
+             * <p>
              * This behaviour is disabled by default; the viewer will use an inline prompt in these cases, making for a smoother
              * user experience. If enabled then this reinstates the pre-1.15.0 behaviour of using a dialog prompt in all cases.
+             * </p>
              */
             private PromptStyle promptStyle = PromptStyle.INLINE;
 
@@ -1853,15 +2173,20 @@ public class IsisConfiguration {
              * Whether to redirect to a new page, even if the object being shown (after an action invocation or a property edit)
              * is the same as the previous page.
              *
+             * <p>
              * This behaviour is disabled by default; the viewer will update the existing page if it can, making for a
              * smoother user experience. If enabled then this reinstates the pre-1.15.0 behaviour of redirecting in all cases.
+             * </p>
              */
             private boolean redirectEvenIfSameObject = false;
 
             /**
-             * in Firefox and more recent versions of Chrome 54+, cannot copy out of disabled fields; instead we use the
+             * In Firefox and more recent versions of Chrome 54+, cannot copy out of disabled fields; instead we use the
              * readonly attribute (https://www.w3.org/TR/2014/REC-html5-20141028/forms.html#the-readonly-attribute)
+             *
+             * <p>
              * This behaviour is enabled by default but can be disabled using this flag
+             * </p>
              */
             private boolean replaceDisabledTagWithReadonlyTag = true;
 
@@ -1877,23 +2202,44 @@ public class IsisConfiguration {
              * Whether to disable a no-arg action button after it has been clicked, to prevent users causing an error if they
              * do a double click.
              *
+             * <p>
              * This behaviour is enabled by default, but can be disabled using this flag.
+             * </p>
              */
             private boolean preventDoubleClickForNoArgAction = true;
 
+            /**
+             * Whether to show the footer menu bar.
+             *
+             * <p>
+             *     This is enabled by default.
+             * </p>
+             */
             private boolean showFooter = true;
 
             /**
              * Whether Wicket tags should be stripped from the markup.
              *
              * <p>
-             * Be aware that if Wicket tags are <i>not</i> stripped, then this may break CSS rules on some browsers.
+             *      By default this is enabled, in other words Wicket tags are stripped.  Please be aware that if
+             *      tags are <i>not</i> stripped, then this may break CSS rules on some browsers.
              * </p>
              */
             private boolean stripWicketTags = true;
 
+            /**
+             * Whether to suppress the sign-up link on the sign-in page.
+             *
+             * <p>
+             *     Although this is disabled by default (in other words the sign-up link is not suppressed), not that
+             *     in addition the application must provide an implementation of the
+             *     {@link org.apache.isis.applib.services.userreg.UserRegistrationService} as well as a
+             *     configured {@link org.apache.isis.applib.services.userreg.EmailNotificationService}.
+             * </p>
+             */
             private boolean suppressSignUp = false;
 
+
             private boolean suppressPasswordReset = false;
 
             /**
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/email/EmailServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/email/EmailServiceDefault.java
index 2178dfc..0b25db3 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/email/EmailServiceDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/email/EmailServiceDefault.java
@@ -112,7 +112,7 @@ public class EmailServiceDefault implements EmailService {
         return configuration.getCore().getRuntimeServices().getEmail().getTls().isEnabled();
     }
 
-    protected Boolean isThrowExceptionOnFail() {
+    protected boolean isThrowExceptionOnFail() {
         return configuration.getCore().getRuntimeServices().getEmail().isThrowExceptionOnFail();
     }
 
@@ -144,7 +144,12 @@ public class EmailServiceDefault implements EmailService {
     }
 
     @Override
-    public boolean send(final List<String> toList, final List<String> ccList, final List<String> bccList, final String subject, final String body,
+    public boolean send(
+            final List<String> toList,
+            final List<String> ccList,
+            final List<String> bccList,
+            final String subject,
+            final String body,
             final DataSource... attachments) {
 
         try {
@@ -194,19 +199,19 @@ public class EmailServiceDefault implements EmailService {
             }
 
 
-            final String overrideTo = getEmailOverrideTo();
+            final String overrideToList = getEmailOverrideTo();
             final String overrideCc = getEmailOverrideCc();
             final String overrideBcc = getEmailOverrideBcc();
 
-            final String[] toListElseOverride = actually(toList, overrideTo);
+            final String[] toListElseOverride = originalUnlessOverridden(toList, overrideToList);
             if (notEmpty(toListElseOverride)) {
                 email.addTo(toListElseOverride);
             }
-            final String[] ccListElseOverride = actually(ccList, overrideCc);
+            final String[] ccListElseOverride = originalUnlessOverridden(ccList, overrideCc);
             if (notEmpty(ccListElseOverride)) {
                 email.addCc(ccListElseOverride);
             }
-            final String[] bccListElseOverride = actually(bccList, overrideBcc);
+            final String[] bccListElseOverride = originalUnlessOverridden(bccList, overrideBcc);
             if (notEmpty(bccListElseOverride)) {
                 email.addBcc(bccListElseOverride);
             }
@@ -227,7 +232,7 @@ public class EmailServiceDefault implements EmailService {
 
     // -- HELPER
 
-    static String[] actually(final List<String> original, final String overrideIfAny) {
+    static String[] originalUnlessOverridden(final List<String> original, final String overrideIfAny) {
         final List<String> addresses = _Strings.isNullOrEmpty(overrideIfAny)
                 ? original == null
                 ? Collections.<String>emptyList()
diff --git a/core/runtimeservices/src/test/java/org/apache/isis/core/runtimeservices/email/EmailServiceDefaultTest_actually.java b/core/runtimeservices/src/test/java/org/apache/isis/core/runtimeservices/email/EmailServiceDefaultTest_actually.java
index 4612c86..c70cc9b 100644
--- a/core/runtimeservices/src/test/java/org/apache/isis/core/runtimeservices/email/EmailServiceDefaultTest_actually.java
+++ b/core/runtimeservices/src/test/java/org/apache/isis/core/runtimeservices/email/EmailServiceDefaultTest_actually.java
@@ -33,7 +33,7 @@ public class EmailServiceDefaultTest_actually {
     @Test
     public void when_null() throws Exception {
 
-        final String[] actually = EmailServiceDefault.actually(null, null);
+        final String[] actually = EmailServiceDefault.originalUnlessOverridden(null, null);
 
         assertThat(actually, is(not(nullValue())));
         assertThat(actually.length, is(0));
@@ -42,7 +42,7 @@ public class EmailServiceDefaultTest_actually {
     @Test
     public void when_not_null_but_no_override() throws Exception {
 
-        final String[] actually = EmailServiceDefault.actually(_Lists.of("joey@tribiani.com", "rachel@green.com"), null);
+        final String[] actually = EmailServiceDefault.originalUnlessOverridden(_Lists.of("joey@tribiani.com", "rachel@green.com"), null);
 
         assertThat(actually, is(not(nullValue())));
         assertThat(actually.length, is(2));
@@ -51,7 +51,7 @@ public class EmailServiceDefaultTest_actually {
     @Test
     public void when_not_null_but_with_override() throws Exception {
 
-        final String[] actually = EmailServiceDefault.actually(_Lists.of("joey@tribiani.com", "rachel@green.com"), "ross@geller.com");
+        final String[] actually = EmailServiceDefault.originalUnlessOverridden(_Lists.of("joey@tribiani.com", "rachel@green.com"), "ross@geller.com");
 
         assertThat(actually, is(not(nullValue())));
         assertThat(actually.length, is(1));
diff --git a/extensions/core/flyway/adoc/modules/flyway/pages/about.adoc b/extensions/core/flyway/adoc/modules/flyway/pages/about.adoc
index f905c5d..e93a879 100644
--- a/extensions/core/flyway/adoc/modules/flyway/pages/about.adoc
+++ b/extensions/core/flyway/adoc/modules/flyway/pages/about.adoc
@@ -60,7 +60,7 @@ In normal circumstances this is most easily peformed using with `autoCreateAll`
 If you want your tests to check your Flyway scripts beforehand, there is nothing to prevent you from using Flyway all the time, even for integration tests.
 
 One point to be aware of though is that the DDL syntax may vary between an in-memory database (such as H2) and a typical production database (such as PostgreSQL or SQL Server).
-Luckily, Spring Boot's Flyway integration allows different variants of scripts for different vendors to be stored, in `+db.migration.{vendor}+` package (where `{vendor}` is as defined by the https://github.com/spring-projects/spring-boot/blob/v2.2.3.RELEASE/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DatabaseDriver.java[DatabaseDriver] class).
+Luckily, Spring Boot's Flyway integration allows different variants of scripts for different vendors to be stored, in `+db.migration.{vendor}+` package (where `+{vendor}+` is as defined by the https://github.com/spring-projects/spring-boot/blob/v2.2.3.RELEASE/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DatabaseDriver.java[DatabaseDriver] class).
 The link:https://github.com/apache/isis-app-simpleapp[simpleapp starter app] also provides an example of this.
 
 
diff --git a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java
index 1430300..db3c6d4 100644
--- a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java
+++ b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java
@@ -71,10 +71,18 @@ import lombok.val;
 @Qualifier("RestfulObjectsV1_0")
 public class ContentNegotiationServiceForRestfulObjectsV1_0 implements ContentNegotiationService {
 
-    private boolean strictAcceptChecking;
 
-    @PostConstruct
-    public void init() {
+    protected final IsisConfiguration configuration;
+    protected final SpecificationLoader specificationLoader;
+
+    private final boolean strictAcceptChecking;
+
+    @Inject
+    public ContentNegotiationServiceForRestfulObjectsV1_0(
+            final IsisConfiguration configuration,
+            final SpecificationLoader specificationLoader) {
+        this.configuration = configuration;
+        this.specificationLoader = specificationLoader;
         this.strictAcceptChecking = configuration.getViewer().getRestfulobjects().isStrictAcceptChecking();
     }
 
@@ -407,7 +415,5 @@ public class ContentNegotiationServiceForRestfulObjectsV1_0 implements ContentNe
         return true;
     }
 
-    @Inject protected IsisConfiguration configuration;
-    @Inject protected SpecificationLoader specificationLoader;
 
 }