You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2019/10/09 14:17:44 UTC
[isis] 03/04: ISIS-2158: polish meta-model life cycle
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch v2
in repository https://gitbox.apache.org/repos/asf/isis.git
commit 554c93f85b628755e9e63bbb6e57fb54cb71780d
Author: Andi Huber <ah...@apache.org>
AuthorDate: Wed Oct 9 12:16:03 2019 +0200
ISIS-2158: polish meta-model life cycle
---
.../facets/object/mixin/MixinIntendedAs.java | 2 +-
.../ViewModelSemanticCheckingFacetFactory.java | 3 +-
.../DomainObjectAnnotationFacetFactory.java | 6 +-
.../metamodel/specloader/ServiceInitializer.java | 181 ---------------
.../metamodel/specloader/SpecificationLoader.java | 64 ++----
.../specloader/SpecificationLoaderDefault.java | 110 +++------
.../specloader/postprocessor/PostProcessor.java | 12 +-
.../specloader/validator/MetaModelValidator.java | 7 +
.../MetaModelValidatorForValidationFailures.java | 24 +-
.../specloader/ServiceInitializerTest.java | 249 ---------------------
.../SpecificationLoaderTestAbstract.java | 7 +-
.../service/JdoPersistenceLifecycleService.java | 12 +-
.../system/session/IsisSessionFactoryDefault.java | 47 +---
.../domainmodel/SpecloaderPerformanceTest.java | 6 +-
14 files changed, 114 insertions(+), 616 deletions(-)
diff --git a/core/detached-tests/src/test/java/org/apache/isis/metamodel/facets/object/mixin/MixinIntendedAs.java b/core/detached-tests/src/test/java/org/apache/isis/metamodel/facets/object/mixin/MixinIntendedAs.java
index ed2c39f..64a6843 100644
--- a/core/detached-tests/src/test/java/org/apache/isis/metamodel/facets/object/mixin/MixinIntendedAs.java
+++ b/core/detached-tests/src/test/java/org/apache/isis/metamodel/facets/object/mixin/MixinIntendedAs.java
@@ -58,7 +58,7 @@ abstract class MixinIntendedAs {
.build());
((ProgrammingModelAbstract)programmingModel).init(new ProgrammingModelInitFilterDefault());
- MetaModelContext.current().getSpecificationLoader().init();
+ MetaModelContext.current().getSpecificationLoader().createMetaModel();
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/ViewModelSemanticCheckingFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/ViewModelSemanticCheckingFacetFactory.java
index 394afe2..ea9b7d9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/ViewModelSemanticCheckingFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/ViewModelSemanticCheckingFacetFactory.java
@@ -42,7 +42,8 @@ implements MetaModelRefiner {
super(FeatureType.OBJECTS_ONLY);
}
- private final MetaModelValidatorForValidationFailures validator = new MetaModelValidatorForValidationFailures();
+ private final MetaModelValidatorForValidationFailures validator =
+ new MetaModelValidatorForValidationFailures();
@Override
public void process(final ProcessClassContext processClassContext) {
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java
index db1fbb5..3fc4b7b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java
@@ -84,8 +84,10 @@ import lombok.val;
public class DomainObjectAnnotationFacetFactory extends FacetFactoryAbstract
implements MetaModelRefiner, PostConstructMethodCache, ObjectSpecIdFacetFactory {
- private final MetaModelValidatorForValidationFailures autoCompleteMethodInvalid = new MetaModelValidatorForValidationFailures();
- private final MetaModelValidatorForMixinTypes mixinTypeValidator = new MetaModelValidatorForMixinTypes("@DomainObject#nature=MIXIN");
+ private final MetaModelValidatorForValidationFailures autoCompleteMethodInvalid =
+ new MetaModelValidatorForValidationFailures();
+ private final MetaModelValidatorForMixinTypes mixinTypeValidator =
+ new MetaModelValidatorForMixinTypes("@DomainObject#nature=MIXIN");
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/ServiceInitializer.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/ServiceInitializer.java
deleted file mode 100644
index 02a78ee..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/ServiceInitializer.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.isis.metamodel.specloader;
-
-import java.lang.reflect.Method;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-
-import org.apache.isis.commons.internal.collections._Maps;
-import org.apache.isis.config.IsisConfigurationLegacy;
-import org.apache.isis.metamodel.commons.MethodExtensions;
-
-import lombok.extern.log4j.Log4j2;
-
-@Log4j2 @Deprecated //TODO[2125] remove
-class ServiceInitializer {
-
- private final List<Object> services;
-
- private final Map<String, String> props;
-
- private Map<Object, Method> postConstructMethodsByService = _Maps.newLinkedHashMap();
- private Map<Object, Method> preDestroyMethodsByService = _Maps.newLinkedHashMap();
-
- public ServiceInitializer(
- final IsisConfigurationLegacy configuration,
- final List<Object> services) {
- this.props = configuration.copyToMap();
- this.services = services;
- }
-
- // -- validate
-
- public void validate() {
-
- for (final Object service : services) {
- log.debug("checking for @PostConstruct and @PostDestroy methods on {}", service.getClass().getName());
- final Method[] methods = service.getClass().getMethods();
-
- // @PostConstruct
- for (final Method method : methods) {
-
- final PostConstruct postConstructAnnotation = method.getAnnotation(PostConstruct.class);
- if(postConstructAnnotation == null) {
- continue;
- }
- final Method existing = postConstructMethodsByService.get(service);
- if(existing != null) {
- throw new RuntimeException("Found more than one @PostConstruct method; service is: " + service.getClass().getName() + ", found " + existing.getName() + " and " + method.getName());
- }
-
- final Class<?>[] parameterTypes = method.getParameterTypes();
- switch(parameterTypes.length) {
- case 0:
- break;
- case 1:
- if(Map.class != parameterTypes[0]) {
- throw new RuntimeException("@PostConstruct method must be no-arg or 1-arg accepting java.util.Map; method is: " + service.getClass().getName() + "#" + method.getName());
- }
- break;
- default:
- throw new RuntimeException("@PostConstruct method must be no-arg or 1-arg accepting java.util.Map; method is: " + service.getClass().getName() + "#" + method.getName());
- }
- postConstructMethodsByService.put(service, method);
- }
-
- // @PreDestroy
- for (final Method method : methods) {
- final PreDestroy preDestroyAnnotation = method.getAnnotation(PreDestroy.class);
- if(preDestroyAnnotation == null) {
- continue;
- }
- final Method existing = preDestroyMethodsByService.get(service);
- if(existing != null) {
- throw new RuntimeException("Found more than one @PreDestroy method; service is: " + service.getClass().getName() + ", found " + existing.getName() + " and " + method.getName());
- }
-
- final Class<?>[] parameterTypes = method.getParameterTypes();
- switch(parameterTypes.length) {
- case 0:
- break;
- default:
- throw new RuntimeException("@PreDestroy method must be no-arg; method is: " + service.getClass().getName() + "#" + method.getName());
- }
- preDestroyMethodsByService.put(service, method);
- }
- }
-
- }
-
-
- // -- postConstruct
-
- public void postConstruct() {
- if(log.isInfoEnabled()) {
- log.info("calling @PostConstruct on all domain services");
- }
-
- Exception firstExceptionIfAny = null;
- for (final Map.Entry<Object, Method> entry : postConstructMethodsByService.entrySet()) {
- final Object service = entry.getKey();
- final Method method = entry.getValue();
-
- if(log.isDebugEnabled()) {
- log.debug(
- "... calling @PostConstruct method: " + service.getClass().getName() + ": " + method.getName());
- }
-
- final int numParams = method.getParameterTypes().length;
-
- // unlike shutdown, we don't swallow exceptions; would rather fail early
- try {
- if(numParams == 0) {
- MethodExtensions.invoke(method, service);
- } else {
- MethodExtensions.invoke(method, service, new Object[] { props });
- }
- } catch(Exception ex) {
- log.error(String.format(
- "@PostConstruct on %s#%s: failed",
- service.getClass().getName(), method.getName()),
- ex);
- if(firstExceptionIfAny == null) {
- firstExceptionIfAny = ex;
- }
- }
- }
- if(firstExceptionIfAny != null) {
- throw new RuntimeException(firstExceptionIfAny);
- }
- }
-
-
-
- // -- preDestroy
-
- public void preDestroy() {
- if(log.isInfoEnabled()) {
- log.info("calling @PreDestroy on all domain services");
- }
- for (final Map.Entry<Object, Method> entry : preDestroyMethodsByService.entrySet()) {
- final Object service = entry.getKey();
- final Method method = entry.getValue();
-
- if(log.isDebugEnabled()) {
- log.debug("... calling @PreDestroy method: {}: {}", service.getClass().getName(), method.getName());
- }
-
- try {
- MethodExtensions.invoke(method, service);
- } catch(Exception ex) {
- // do nothing
- log.warn(String.format(
- "@PreDestroy on %s#%s: failed, continuing anyway",
- service.getClass().getName(), method.getName()));
- }
- }
- }
-
-
-
-}
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoader.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoader.java
index 0893c94..867f8f4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoader.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoader.java
@@ -24,34 +24,43 @@ import javax.annotation.Nullable;
import org.apache.isis.commons.internal.base._Strings;
import org.apache.isis.metamodel.commons.ClassUtil;
+import org.apache.isis.metamodel.progmodel.ProgrammingModel;
import org.apache.isis.metamodel.spec.ObjectSpecId;
import org.apache.isis.metamodel.spec.ObjectSpecification;
import org.apache.isis.metamodel.specloader.specimpl.IntrospectionState;
+import lombok.val;
+
/**
- * Builds the meta-model.
- * TODO [2033] add missing java-doc
- *
+ * Builds the meta-model, utilizing an instance of {@link ProgrammingModel}
*/
public interface SpecificationLoader {
-
- // -- LIVE CYCLE
-
- void init();
-
- void shutdown();
+
+ /**
+ * Creates the meta-model, that is the set of {@link ObjectSpecification}s.
+ * @see {@link #disposeMetaModel()}
+ */
+ void createMetaModel();
+
+ /**
+ * Clears all instance references to {@link ObjectSpecification}s.
+ * @see {@link #createMetaModel()}
+ */
+ void disposeMetaModel();
+
+ void validateMetaModel();
// -- LOOKUP
/**
* @ThreadSafe
* <p>
- * Must be implemented thread-safe to avoid concurrent modification exceptions for if the caller
+ * Must be implemented thread-safe to avoid concurrent modification exceptions when the caller
* iterates over all the specifications and performs an activity that might give rise to new
- * ObjectSpec's being discovered, eg performing metamodel validation.
+ * ObjectSpec's being discovered, eg. performing meta-model validation.
* </p>
*
- * @return (defensive-copy) snapshot of all the (currently) loaded specifications
+ * @return snapshot of all the (currently) loaded specifications, a defensive-copy
*/
Collection<ObjectSpecification> snapshotSpecifications();
@@ -61,14 +70,6 @@ public interface SpecificationLoader {
*/
ObjectSpecification lookupBySpecIdElseLoad(ObjectSpecId objectSpecId);
- // default ObjectSpecification lookupBySpecIdElseLoad(ObjectSpecId objectSpecId) {
- // return lookupBySpecIdO(objectSpecId).orElseThrow(
- // ()->_Exceptions.unrecoverable(
- // "Failed to lookup ObjectSpecification by its id '" + objectSpecId + "'"));
- // }
-
- //ValidationFailures validate();
-
void reloadSpecification(Class<?> domainType);
/**
@@ -83,31 +84,12 @@ public interface SpecificationLoader {
*/
ObjectSpecification loadSpecification(@Nullable Class<?> domainType, IntrospectionState upTo);
- // default ObjectSpecification loadSpecification(@Nullable ObjectSpecId objectSpecId, IntrospectionState upTo) {
- // if(objectSpecId==null) {
- // return null;
- // }
- //
- // val className = objectSpecId.asString();
- //
- // if(_Strings.isNullOrEmpty(className)) {
- // return null;
- // }
- //
- // final Class<?> type = ClassUtil.forNameElseFail(className);
- // return loadSpecification(type, upTo);
- // }
-
// -- SHORTCUTS
default ObjectSpecification loadSpecification(@Nullable final Class<?> domainType) {
return loadSpecification(domainType, IntrospectionState.TYPE_INTROSPECTED);
}
- // default ObjectSpecification loadSpecification(@Nullable ObjectSpecId objectSpecId) {
- // return loadSpecification(objectSpecId.asString(), IntrospectionState.TYPE_INTROSPECTED);
- // }
-
default ObjectSpecification loadSpecification(
@Nullable String className,
@Nullable IntrospectionState introspectionState) {
@@ -115,7 +97,7 @@ public interface SpecificationLoader {
if(_Strings.isNullOrEmpty(className)) {
return null;
}
- final Class<?> type = ClassUtil.forNameElseFail(className);
+ val type = ClassUtil.forNameElseFail(className);
return introspectionState!=null
? loadSpecification(type, introspectionState)
: loadSpecification(type);
@@ -125,6 +107,8 @@ public interface SpecificationLoader {
return loadSpecification(className, null);
}
+
+
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoaderDefault.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoaderDefault.java
index dd51833..243eff7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoaderDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoaderDefault.java
@@ -20,19 +20,17 @@ package org.apache.isis.metamodel.specloader;
import java.util.Collection;
import java.util.List;
-import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
import javax.inject.Inject;
import org.springframework.stereotype.Service;
-import org.apache.isis.commons.internal.base._Blackhole;
import org.apache.isis.commons.internal.base._Timing;
import org.apache.isis.commons.internal.collections._Lists;
-import org.apache.isis.commons.internal.collections._Sets;
import org.apache.isis.commons.internal.environment.IsisSystemEnvironment;
import org.apache.isis.config.IsisConfiguration;
import org.apache.isis.config.registry.IsisBeanTypeRegistry;
@@ -50,6 +48,7 @@ import org.apache.isis.metamodel.specloader.specimpl.FacetedMethodsBuilderContex
import org.apache.isis.metamodel.specloader.specimpl.IntrospectionState;
import org.apache.isis.metamodel.specloader.specimpl.dflt.ObjectSpecificationDefault;
import org.apache.isis.metamodel.specloader.specimpl.standalonelist.ObjectSpecificationOnStandaloneList;
+import org.apache.isis.metamodel.specloader.validator.ValidationFailures;
import org.apache.isis.schema.utils.CommonDtoUtils;
import static org.apache.isis.commons.internal.base._With.requires;
@@ -85,12 +84,6 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
private final SpecificationCacheDefault<ObjectSpecification> cache =
new SpecificationCacheDefault<>();
- @PostConstruct
- public void preInit() {
- this.programmingModel = programmingModelService.getProgrammingModel();
- this.facetProcessor = new FacetProcessor(programmingModel);
- this.postProcessor = new PostProcessor(programmingModel);
- }
/** JUnit Test Support */
public static SpecificationLoaderDefault getInstance (
@@ -110,25 +103,30 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
return instance;
}
-
-
// -- LIVE CYCLE
+ @PostConstruct
+ public void init() {
+ if (log.isDebugEnabled()) {
+ log.debug("initialising {}", this);
+ }
+ this.programmingModel = programmingModelService.getProgrammingModel();
+ this.facetProcessor = new FacetProcessor(programmingModel);
+ this.postProcessor = new PostProcessor(programmingModel);
+ }
+
/**
* Initializes and wires up, and primes the cache based on any service
* classes (provided by the {@link IsisBeanTypeRegistry}).
*/
@Override
- public void init() {
+ public void createMetaModel() {
- if (log.isDebugEnabled()) {
- log.debug("initialising {}", this);
- }
+ log.info("About to creating the Metamodel");
- // initialize subcomponents
+ // initialize subcomponents, only after @PostConstruct has globally completed
facetProcessor.init();
postProcessor.init();
-
// need to completely load services and mixins (synchronously)
log.info("Loading all specs (up to state of {})", IntrospectionState.NOT_INTROSPECTED);
@@ -197,15 +195,32 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
}
stopWatch.stop();
- log.info("init() - took " + stopWatch);
+ log.info("createMetaModel() - took " + stopWatch);
}
+
+ @Override
+ public void validateMetaModel() {
+ val failures = new ValidationFailures();
+ programmingModel.streamValidators()
+ .forEach(validator->validator.validateInto(failures));
+ // return failures;
+ }
@Override
- public void shutdown() {
+ public void disposeMetaModel() {
cache.clear();
-
- log.info("shutting down {}", this);
+ log.info("Metamodel disposed.");
+ }
+
+ @PreDestroy
+ public void shutdown() {
+ log.debug("shutting down {}", this);
+ disposeMetaModel();
+ facetProcessor.shutdown();
+ postProcessor.shutdown();
+ postProcessor = null;
+ facetProcessor = null;
}
/**
@@ -379,57 +394,4 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
@Inject private IsisConfiguration isisConfiguration;
@Inject private IsisSystemEnvironment isisSystemEnvironment;
- // -- DEPRECATED
-
- // /**
- // * Loads the specifications of the specified types except the one specified
- // * (to prevent an infinite loop).
- // */
- // public boolean loadSpecifications(
- // final List<Class<?>> typesToLoad,
- // final Class<?> typeToIgnore,
- // final IntrospectionState upTo) {
- //
- // boolean anyLoadedAsNull = false;
- // for (final Class<?> typeToLoad : typesToLoad) {
- // if (typeToLoad != typeToIgnore) {
- // final ObjectSpecification objectSpecification =
- // internalLoadSpecification(typeToLoad, null, upTo);
- // final boolean loadedAsNull = (objectSpecification == null);
- // anyLoadedAsNull = loadedAsNull || anyLoadedAsNull;
- // }
- // }
- // return anyLoadedAsNull;
- // }
-
- // public ObjectSpecification peekSpecification(final Class<?> type) {
- //
- // final Class<?> substitutedType = classSubstitutor.getClass(type);
- // if (substitutedType == null) {
- // return null;
- // }
- //
- // final String typeName = substitutedType.getName();
- // ObjectSpecification spec = cache.get(typeName);
- // if (spec != null) {
- // return spec;
- // }
- //
- // return null;
- // }
-
- // /**
- // * Whether this class has been loaded.
- // */
- // private boolean loaded(final Class<?> cls) {
- // return loaded(cls.getName());
- // }
-
- // /**
- // * @see #loaded(Class).
- // */
- // private boolean loaded(final String fullyQualifiedClassName) {
- // return cache.get(fullyQualifiedClassName) != null;
- // }
-
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/postprocessor/PostProcessor.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/postprocessor/PostProcessor.java
index 25c5363..304e3f9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/postprocessor/PostProcessor.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/postprocessor/PostProcessor.java
@@ -30,10 +30,9 @@ import lombok.val;
public class PostProcessor {
private final ProgrammingModel programmingModel;
- // populated at #init
- List<ObjectSpecificationPostProcessor> postProcessors;
+ private List<ObjectSpecificationPostProcessor> postProcessors; // populated at #init
- public PostProcessor(final ProgrammingModel programmingModel) {
+ public PostProcessor(ProgrammingModel programmingModel) {
this.programmingModel = programmingModel;
}
@@ -41,13 +40,16 @@ public class PostProcessor {
postProcessors = programmingModel.streamPostProcessors().collect(Collectors.toList());
}
- public void postProcess(final ObjectSpecification objectSpecification) {
+ public void shutdown() {
+ postProcessors.clear();
+ }
+
+ public void postProcess(ObjectSpecification objectSpecification) {
for (val postProcessor : postProcessors) {
postProcessor.postProcess(objectSpecification);
}
-
}
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidator.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidator.java
index fda6611..547cc6f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidator.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidator.java
@@ -19,6 +19,10 @@
package org.apache.isis.metamodel.specloader.validator;
+import java.util.function.Consumer;
+
+import org.apache.isis.metamodel.facetapi.FacetHolder;
+
public interface MetaModelValidator {
/**
@@ -26,6 +30,9 @@ public interface MetaModelValidator {
*
* @param validationFailures
*/
+ //@Deprecated
void validateInto(ValidationFailures validationFailures);
+
+ //void validateInto(FacetHolder holder, Consumer<ValidationFailure> onFailure);
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidatorForValidationFailures.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidatorForValidationFailures.java
index 10ce038..f53626a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidatorForValidationFailures.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidatorForValidationFailures.java
@@ -41,17 +41,17 @@ public class MetaModelValidatorForValidationFailures extends MetaModelValidatorA
failures.add(identifier, pattern, arguments);
}
- public Facet addFailure(Facet facet, String message) {
- if(facet != null) {
- val holder = (IdentifiedHolder) facet.getFacetHolder();
- val identifier = holder.getIdentifier();
- failures.add(identifier, message + " " + identifier.toFullIdentityString());
- }
- return facet;
- }
-
- public void addFacet(final Facet facet, final String message) {
- FacetUtil.addFacet(addFailure(facet, message));
- }
+// public Facet addFailure(Facet facet, String message) {
+// if(facet != null) {
+// val holder = (IdentifiedHolder) facet.getFacetHolder();
+// val identifier = holder.getIdentifier();
+// failures.add(identifier, message + " " + identifier.toFullIdentityString());
+// }
+// return facet;
+// }
+
+// public void addFacet(Facet facet, String message) {
+// FacetUtil.addFacet(addFailure(facet, message));
+// }
}
diff --git a/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/ServiceInitializerTest.java b/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/ServiceInitializerTest.java
deleted file mode 100644
index c0b6134..0000000
--- a/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/ServiceInitializerTest.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.isis.metamodel.specloader;
-
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-
-import org.jmock.Expectations;
-import org.jmock.auto.Mock;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import org.apache.isis.commons.internal.collections._Maps;
-import org.apache.isis.config.IsisConfigurationLegacy;
-import org.apache.isis.unittestsupport.jmocking.JUnitRuleMockery2;
-import org.apache.isis.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
-
-import static org.apache.isis.commons.internal.base._NullSafe.stream;
-import static org.hamcrest.CoreMatchers.containsString;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-public class ServiceInitializerTest {
-
- @Rule
- public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_ONLY);
-
- private Map<String,String> props;
-
- @Mock
- private IsisConfigurationLegacy configuration;
- private ServiceInitializer serviceInitializer;
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- @Before
- public void setUp() throws Exception {
- props = _Maps.newHashMap();
- context.checking(new Expectations() {
- {
- allowing(configuration).copyToMap();
- will(returnValue(props));
- }
- });
- }
-
- @After
- public void tearDown() throws Exception {
- serviceInitializer = null;
- }
-
-
- private static List<Object> listOf(Object... elements) {
- return stream(elements)
- .collect(Collectors.toList());
- }
-
- public static class DomainServiceWithPostConstruct {
- boolean called;
- @PostConstruct
- public void x() {
- this.called = true;
- }
- }
-
- public static class DomainServiceWithPostConstructWithProperties {
- boolean called;
- Map<String,String> properties;
- @PostConstruct
- public void x(Map<String,String> properties) {
- this.properties = properties;
- this.called = true;
- }
- }
-
- @Test
- public void postConstruct() {
- final DomainServiceWithPostConstruct d1 = new DomainServiceWithPostConstruct();
- final DomainServiceWithPostConstructWithProperties d2 = new DomainServiceWithPostConstructWithProperties();
-
- serviceInitializer = new ServiceInitializer(configuration, listOf(d1, d2));
- serviceInitializer.validate();
-
- // when
- serviceInitializer.postConstruct();
-
- // then
- assertThat(d1.called, is(true));
- assertThat(d2.called, is(true));
- assertThat(d2.properties, is(props));
- }
-
-
- public static class DomainServiceWithPreDestroy {
- boolean called;
- @PreDestroy
- public void x() {
- this.called = true;
- }
- }
-
- @Test
- public void preDestroy() {
- final DomainServiceWithPreDestroy d1 = new DomainServiceWithPreDestroy();
- final DomainServiceWithPreDestroy d2 = new DomainServiceWithPreDestroy();
-
- serviceInitializer = new ServiceInitializer(configuration, listOf(d1, d2));
- serviceInitializer.validate();
-
- // when
- serviceInitializer.preDestroy();
-
- // then
- assertThat(d1.called, is(true));
- assertThat(d2.called, is(true));
- }
-
- public static class DomainServiceWithMultiplePostConstruct {
- boolean called;
- @PostConstruct
- public void x() {
- this.called = true;
- }
- @PostConstruct
- public void y() {
- this.called = true;
- }
- }
-
- @Test
- public void init_when_postConstructMultiple() {
- final DomainServiceWithMultiplePostConstruct d1 = new DomainServiceWithMultiplePostConstruct();
- expectedException.expectMessage(
- containsString(
- "Found more than one @PostConstruct method; service is: org.apache.isis.metamodel.specloader.ServiceInitializerTest$DomainServiceWithMultiplePostConstruct, found"));
- serviceInitializer = new ServiceInitializer(configuration, listOf(d1));
-
- // when
- serviceInitializer.validate();
- }
-
- public static class DomainServiceWithMultiplePreDestroy {
- boolean called;
- @PreDestroy
- public void x() {
- this.called = true;
- }
- @PreDestroy
- public void y() {
- this.called = true;
- }
- }
-
- @Test
- public void init_when_preDestroyMultiple() {
- final DomainServiceWithMultiplePreDestroy d1 = new DomainServiceWithMultiplePreDestroy();
- expectedException.expectMessage(
- containsString(
- "Found more than one @PreDestroy method; service is: org.apache.isis.metamodel.specloader.ServiceInitializerTest$DomainServiceWithMultiplePreDestroy, found"));
- serviceInitializer = new ServiceInitializer(configuration, listOf(d1));
-
- // when
- serviceInitializer.validate();
- }
-
- public static class DomainServiceWithPostConstructOneArgWrongType {
- boolean called;
- @PostConstruct
- public void y(Object o) {
- this.called = true;
- }
- }
-
- @Test
- public void init_when_postConstructWrongType() {
- final DomainServiceWithPostConstructOneArgWrongType d1 = new DomainServiceWithPostConstructOneArgWrongType();
- expectedException.expectMessage(
- "@PostConstruct method must be no-arg or 1-arg accepting java.util.Map; method is: org.apache.isis.metamodel.specloader.ServiceInitializerTest$DomainServiceWithPostConstructOneArgWrongType#y");
- serviceInitializer = new ServiceInitializer(configuration, listOf(d1));
-
- // when
- serviceInitializer.validate();
- }
-
- public static class DomainServiceWithPostConstructTwoArgs {
- boolean called;
- @PostConstruct
- public void y(Map<String,String> p, Object o) {
- this.called = true;
- }
- }
-
- @Test
- public void init_when_postConstructWrongArgs() {
- final DomainServiceWithPostConstructTwoArgs d1 = new DomainServiceWithPostConstructTwoArgs();
- expectedException.expectMessage(
- "@PostConstruct method must be no-arg or 1-arg accepting java.util.Map; method is: org.apache.isis.metamodel.specloader.ServiceInitializerTest$DomainServiceWithPostConstructTwoArgs#y");
- serviceInitializer = new ServiceInitializer(configuration, listOf(d1));
-
- // when
- serviceInitializer.validate();
- }
-
- public static class DomainServiceWithPreDestroyOneArgs {
- boolean called;
- @PreDestroy
- public void y(Object o) {
- this.called = true;
- }
- }
-
-
- @Test
- public void init_when_preDestroyWrongArgs() {
- final DomainServiceWithPreDestroyOneArgs d1 = new DomainServiceWithPreDestroyOneArgs();
- expectedException.expectMessage(
- "@PreDestroy method must be no-arg; method is: org.apache.isis.metamodel.specloader.ServiceInitializerTest$DomainServiceWithPreDestroyOneArgs#y");
- serviceInitializer = new ServiceInitializer(configuration, listOf(d1));
-
- // when
- serviceInitializer.validate();
- }
-
-
-}
diff --git a/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/SpecificationLoaderTestAbstract.java b/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/SpecificationLoaderTestAbstract.java
index c6cb32f..683c7ba 100644
--- a/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/SpecificationLoaderTestAbstract.java
+++ b/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/SpecificationLoaderTestAbstract.java
@@ -146,18 +146,15 @@ abstract class SpecificationLoaderTestAbstract {
((ProgrammingModelAbstract)programmingModel).init(new ProgrammingModelInitFilterDefault());
- _Timing.runVerbose("specificationLoader.init()", specificationLoader::init);
-
- //specificationLoader.init();
+ _Timing.runVerbose("specificationLoader.createMetaModel()", specificationLoader::createMetaModel);
specification = loadSpecification(specificationLoader);
-
}
@AfterEach
public void tearDown() throws Exception {
- specificationLoader.shutdown();
+ specificationLoader.disposeMetaModel();
}
protected abstract ObjectSpecification loadSpecification(SpecificationLoader reflector);
diff --git a/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/datanucleus/service/JdoPersistenceLifecycleService.java b/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/datanucleus/service/JdoPersistenceLifecycleService.java
index 9358d5d..8612b1a 100644
--- a/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/datanucleus/service/JdoPersistenceLifecycleService.java
+++ b/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/datanucleus/service/JdoPersistenceLifecycleService.java
@@ -19,6 +19,7 @@
package org.apache.isis.jdo.datanucleus.service;
import javax.annotation.PostConstruct;
+import javax.inject.Inject;
import javax.inject.Singleton;
import org.springframework.context.annotation.Bean;
@@ -28,15 +29,13 @@ import org.springframework.stereotype.Service;
import org.apache.isis.commons.internal.context._Context;
import org.apache.isis.commons.internal.exceptions._Exceptions;
import org.apache.isis.config.registry.IsisBeanTypeRegistry;
+import org.apache.isis.metamodel.specloader.SpecificationLoader;
import org.apache.isis.runtime.persistence.IsisJdoRuntimePlugin;
import org.apache.isis.runtime.system.context.session.AppLifecycleEvent;
import org.apache.isis.runtime.system.context.session.SessionLifecycleEvent;
import org.apache.isis.runtime.system.persistence.PersistenceSession;
import org.apache.isis.runtime.system.persistence.PersistenceSessionFactory;
import org.apache.isis.runtime.system.session.IsisSession;
-import org.apache.isis.runtime.system.session.IsisSessionFactory;
-
-import static org.apache.isis.commons.internal.base._With.requires;
import lombok.val;
import lombok.extern.log4j.Log4j2;
@@ -44,6 +43,7 @@ import lombok.extern.log4j.Log4j2;
@Service @Log4j2
public class JdoPersistenceLifecycleService {
+ @Inject private SpecificationLoader specificationLoader;
private PersistenceSessionFactory persistenceSessionFactory;
@PostConstruct
@@ -115,7 +115,7 @@ public class JdoPersistenceLifecycleService {
val persistenceSession =
persistenceSessionFactory.createPersistenceSession(authenticationSession);
- //TODO [2033] only to support IsisSessionFactoryDefault
+ // to support static call of PersistenceSession.current(PersistenceSession.class)
_Context.threadLocalPut(PersistenceSession.class, persistenceSession);
persistenceSession.open();
@@ -143,10 +143,6 @@ public class JdoPersistenceLifecycleService {
}
private void init() {
- //TODO [2033] specloader should rather be a Spring/CDI managed object
- val isisSessionFactory = _Context.getElseFail(IsisSessionFactory.class);
- val specificationLoader = isisSessionFactory.getSpecificationLoader();
- requires(specificationLoader, "specificationLoader");
persistenceSessionFactory.catalogNamedQueries(specificationLoader);
}
diff --git a/core/runtime/src/main/java/org/apache/isis/runtime/system/session/IsisSessionFactoryDefault.java b/core/runtime/src/main/java/org/apache/isis/runtime/system/session/IsisSessionFactoryDefault.java
index e973f18..936c9d7 100644
--- a/core/runtime/src/main/java/org/apache/isis/runtime/system/session/IsisSessionFactoryDefault.java
+++ b/core/runtime/src/main/java/org/apache/isis/runtime/system/session/IsisSessionFactoryDefault.java
@@ -85,18 +85,16 @@ public class IsisSessionFactoryDefault implements IsisSessionFactory {
localeInitializer.initLocale(configuration);
timeZoneInitializer.initTimeZone(configuration);
- // ... and make IsisSessionFactory available via the IsisContext static for those
- // places where we cannot yet inject.
- _Context.putSingleton(IsisSessionFactory.class, this); //TODO[2112] should no longer be required, since Spring manages this instance
-
runtimeEventService.fireAppPreMetamodel();
- val taskList = _ConcurrentTaskList.named("IsisSessionFactoryDefault Init");
+ val taskList = _ConcurrentTaskList.named("IsisSessionFactoryDefault Init")
- taskList.addRunnable("SpecificationLoader.init()", this::initMetamodel);
- taskList.addRunnable("ChangesDtoUtils.init()", ChangesDtoUtils::init);
- taskList.addRunnable("InteractionDtoUtils.init()", InteractionDtoUtils::init);
- taskList.addRunnable("CommandDtoUtils.init()", CommandDtoUtils::init);
+ .addRunnable("SpecificationLoader::createThenValidateMetaModel", this::createThenValidateMetaModel)
+ .addRunnable("ChangesDtoUtils::init", ChangesDtoUtils::init)
+ .addRunnable("InteractionDtoUtils::init", InteractionDtoUtils::init)
+ .addRunnable("CommandDtoUtils::init", CommandDtoUtils::init)
+ .addRunnable("AuthenticationManager::init", authenticationManager::init)
+ .addRunnable("AuthorizationManager::init", IsisContext.getAuthorizationManager()::init);
taskList.submit(_ConcurrentContext.forkJoin());
taskList.await();
@@ -105,33 +103,11 @@ public class IsisSessionFactoryDefault implements IsisSessionFactory {
}
- private void initMetamodel() {
- val authorizationManager = IsisContext.getAuthorizationManager();
-
- specificationLoader.init();
-
- // we need to do this before checking if the metamodel is valid.
- //
- // eg ActionChoicesForCollectionParameterFacetFactory metamodel validator requires a runtime...
- // at o.a.i.core.metamodel.specloader.specimpl.ObjectActionContributee.getServiceAdapter(ObjectActionContributee.java:287)
- // at o.a.i.core.metamodel.specloader.specimpl.ObjectActionContributee.determineParameters(ObjectActionContributee.java:138)
- // at o.a.i.core.metamodel.specloader.specimpl.ObjectActionDefault.getParameters(ObjectActionDefault.java:182)
- // at o.a.i.core.metamodel.facets.actions.action.ActionChoicesForCollectionParameterFacetFactory$1.validate(ActionChoicesForCollectionParameterFacetFactory.java:85)
- // at o.a.i.core.metamodel.facets.actions.action.ActionChoicesForCollectionParameterFacetFactory$1.visit(ActionChoicesForCollectionParameterFacetFactory.java:76)
- // at o.a.i.core.metamodel.specloader.validator.MetaModelValidatorVisiting.validate(MetaModelValidatorVisiting.java:47)
- //
- // also, required so that can still call isisSessionFactory#doInSession
- //
- // eg todoapp has a custom UserSettingsThemeProvider that is called when rendering any page
- // (including the metamodel invalid page)
- // at o.a.i.core.runtime.system.session.IsisSessionFactory.doInSession(IsisSessionFactory.java:327)
- // at todoapp.webapp.UserSettingsThemeProvider.getActiveTheme(UserSettingsThemeProvider.java:36)
-
- authenticationManager.init();
- authorizationManager.init();
+ private void createThenValidateMetaModel() {
+ specificationLoader.createMetaModel();
+ specificationLoader.validateMetaModel();
}
-
@PreDestroy
public void shutdown() {
// call might originate from a different thread than main
@@ -142,7 +118,8 @@ public class IsisSessionFactoryDefault implements IsisSessionFactory {
runtimeEventService.fireAppPreDestroy();
authenticationManager.shutdown();
- //specificationLoader.shutdown(); //[2112] lifecycle is managed by IoC
+ IsisContext.getAuthorizationManager().shutdown();
+ //specificationLoader.shutdown(); // lifecycle is managed by IoC
}
// --
diff --git a/examples/smoketests/src/test/java/org/apache/isis/testdomain/domainmodel/SpecloaderPerformanceTest.java b/examples/smoketests/src/test/java/org/apache/isis/testdomain/domainmodel/SpecloaderPerformanceTest.java
index 3181ac6..1f2c6c2 100644
--- a/examples/smoketests/src/test/java/org/apache/isis/testdomain/domainmodel/SpecloaderPerformanceTest.java
+++ b/examples/smoketests/src/test/java/org/apache/isis/testdomain/domainmodel/SpecloaderPerformanceTest.java
@@ -52,7 +52,7 @@ import lombok.val;
})
@TestPropertySource({
IsisPresets.DebugValidation,
- IsisPresets.DebugProgrammingModel,
+ //IsisPresets.DebugProgrammingModel,
})
@Incubating("not a real test, just for performance tuning")
@@ -81,8 +81,8 @@ class SpecloaderPerformanceTest {
for(int i=0; i<ITERATIONS; ++i) {
_Annotations.clearCache();
- specificationLoader.shutdown();
- specificationLoader.init();
+ specificationLoader.disposeMetaModel();
+ specificationLoader.createMetaModel();
if(System.currentTimeMillis() > goodUntilMillis) {
fail("timed out");