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 2022/09/03 17:08:39 UTC
[isis] branch master updated: ISIS-3202: JDO injection point resolving optimizations
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/master by this push:
new f2882a8d37 ISIS-3202: JDO injection point resolving optimizations
f2882a8d37 is described below
commit f2882a8d37a694b3eed07ab0415f6313b78bf620
Author: Andi Huber <ah...@apache.org>
AuthorDate: Sat Sep 3 19:08:32 2022 +0200
ISIS-3202: JDO injection point resolving optimizations
---
.../facets/object/entity/EntityFacet.java | 12 +++-
.../isis/core/metamodel/object/ManagedObject.java | 76 +++++++++++-----------
.../object/_ManagedObjectEntityHybrid.java | 8 +++
.../metamodel/object/_ManagedObjectSpecified.java | 12 +++-
.../object/_ManagedObjectSpecifiedLegacy.java | 52 ---------------
.../changetracking/JdoLifecycleListener.java | 11 ++--
.../jdo/datanucleus/changetracking/_Utils.java | 69 +++++---------------
.../entities/DnObjectProviderForIsis.java | 56 +++++++++++-----
.../metamodel/facets/entity/JdoEntityFacet.java | 36 ++++------
.../persistence/jpa/eclipselink/inject/_Util.java | 23 +++----
.../viewer/resources/HomePageReprRenderer.java | 2 +-
11 files changed, 153 insertions(+), 204 deletions(-)
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/entity/EntityFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/entity/EntityFacet.java
index b814ad62a0..64c62929da 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/entity/EntityFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/entity/EntityFacet.java
@@ -92,6 +92,16 @@ public interface EntityFacet extends Facet {
return (ObjectSpecification)getFacetHolder();
}
+ /**
+ * Introduced purely for optimization purposes.
+ * @implNote if possible memoizes the fact as to whether
+ * services were already injected into given pojo,
+ * and if so allows to skip any consecutive injection attempts
+ */
+ default boolean isInjectionPointsResolved(final @Nullable Object pojo) {
+ return pojo==null;
+ }
+
/**
* Optionally the stringified OID,
* based on whether the entity has one associated.
@@ -158,6 +168,4 @@ public interface EntityFacet extends Facet {
return new _EntityFacetForTesting(persistenceStandard, facetHolder);
}
-
-
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/ManagedObject.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/ManagedObject.java
index ef2646d3af..6baff36a98 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/ManagedObject.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/ManagedObject.java
@@ -69,7 +69,8 @@ extends
* </ul>
* @implNote realized by a singleton (static) {@link ManagedObject} instance;
*/
- UNSPECIFIED(TypePolicy.NO_TYPE, BookmarkPolicy.NO_BOOKMARK, PojoPolicy.NO_POJO),
+ UNSPECIFIED(TypePolicy.NO_TYPE, BookmarkPolicy.NO_BOOKMARK, PojoPolicy.NO_POJO,
+ InjectionPolicy.NEVER_INJECT),
/**
* <h1>Contract</h1><ul>
@@ -78,7 +79,8 @@ extends
* <li>Pojo (null, immutable)</li>
* </ul>
*/
- EMPTY(TypePolicy.ABSTRACT_TYPE_ALLOWED, BookmarkPolicy.NO_BOOKMARK, PojoPolicy.NO_POJO),
+ EMPTY(TypePolicy.ABSTRACT_TYPE_ALLOWED, BookmarkPolicy.NO_BOOKMARK, PojoPolicy.NO_POJO,
+ InjectionPolicy.NEVER_INJECT),
/**
* <h1>Contract</h1><ul>
@@ -87,7 +89,8 @@ extends
* <li>Pojo (immutable)</li>
* </ul>
*/
- VALUE(TypePolicy.EXACT_TYPE_REQUIRED, BookmarkPolicy.IMMUTABLE, PojoPolicy.IMMUTABLE),
+ VALUE(TypePolicy.EXACT_TYPE_REQUIRED, BookmarkPolicy.IMMUTABLE, PojoPolicy.IMMUTABLE,
+ InjectionPolicy.NEVER_INJECT),
/**
* <h1>Contract</h1><ul>
@@ -96,7 +99,8 @@ extends
* <li>Pojo (immutable)</li>
* </ul>
*/
- SERVICE(TypePolicy.EXACT_TYPE_REQUIRED, BookmarkPolicy.IMMUTABLE, PojoPolicy.IMMUTABLE),
+ SERVICE(TypePolicy.EXACT_TYPE_REQUIRED, BookmarkPolicy.IMMUTABLE, PojoPolicy.IMMUTABLE,
+ InjectionPolicy.NEVER_INJECT),
/**
* <h1>Contract</h1><ul>
@@ -105,7 +109,8 @@ extends
* <li>Pojo (mutable, but immutable obj. ref.)</li>
* </ul>
*/
- VIEWMODEL(TypePolicy.EXACT_TYPE_REQUIRED, BookmarkPolicy.REFRESHABLE, PojoPolicy.STATEFUL),
+ VIEWMODEL(TypePolicy.EXACT_TYPE_REQUIRED, BookmarkPolicy.REFRESHABLE, PojoPolicy.STATEFUL,
+ InjectionPolicy.ALWAYS_INJECT),
/**
* <h1>Contract</h1><ul>
@@ -114,7 +119,8 @@ extends
* <li>Pojo (refetchable)</li>
* </ul>
*/
- ENTITY(TypePolicy.EXACT_TYPE_REQUIRED, BookmarkPolicy.IMMUTABLE, PojoPolicy.REFETCHABLE),
+ ENTITY(TypePolicy.EXACT_TYPE_REQUIRED, BookmarkPolicy.IMMUTABLE, PojoPolicy.REFETCHABLE,
+ InjectionPolicy.ALWAYS_INJECT),
/**
* <h1>Contract</h1><ul>
@@ -123,7 +129,8 @@ extends
* <li>Pojo (allowed stateful, immutable obj. ref)</li>
* </ul>
*/
- MIXIN(TypePolicy.EXACT_TYPE_REQUIRED, BookmarkPolicy.NO_BOOKMARK, PojoPolicy.STATEFUL),
+ MIXIN(TypePolicy.EXACT_TYPE_REQUIRED, BookmarkPolicy.NO_BOOKMARK, PojoPolicy.STATEFUL,
+ InjectionPolicy.ALWAYS_INJECT),
/**
* <h1>Contract</h1><ul>
@@ -132,7 +139,8 @@ extends
* <li>Pojo (allowed stateful, immutable obj. ref)</li>
* </ul>
*/
- OTHER(TypePolicy.EXACT_TYPE_REQUIRED, BookmarkPolicy.NO_BOOKMARK, PojoPolicy.STATEFUL),
+ OTHER(TypePolicy.EXACT_TYPE_REQUIRED, BookmarkPolicy.NO_BOOKMARK, PojoPolicy.STATEFUL,
+ InjectionPolicy.NEVER_INJECT),
/**
* <h1>Contract</h1><ul>
@@ -141,7 +149,8 @@ extends
* <li>Pojo (unmod. Collection of pojos)</li>
* </ul>
*/
- PACKED(TypePolicy.ABSTRACT_TYPE_ALLOWED, BookmarkPolicy.NO_BOOKMARK, PojoPolicy.PACKED);
+ PACKED(TypePolicy.ABSTRACT_TYPE_ALLOWED, BookmarkPolicy.NO_BOOKMARK, PojoPolicy.PACKED,
+ InjectionPolicy.NEVER_INJECT);
static enum TypePolicy {
/** has no type information */
@@ -200,10 +209,22 @@ extends
* supports unpacking into a {@link Can} of {@link ManagedObject}s;*/
public boolean isPacked() { return this == PACKED; }
}
+ static enum InjectionPolicy {
+ /** don't inject services into accompanied pojo */
+ NEVER_INJECT,
+ /** always inject services into accompanied pojo */
+ ALWAYS_INJECT;
+ ////
+ /** don't inject services into accompanied pojo */
+ public boolean isNeverInject() { return this == NEVER_INJECT; }
+ /** always inject services into accompanied pojo */
+ public boolean isAlwaysInject() { return this == ALWAYS_INJECT; }
+ }
private final TypePolicy typePolicy;
private final BookmarkPolicy bookmarkPolicy;
private final PojoPolicy pojoPolicy;
+ private final InjectionPolicy injectionPolicy;
/**
* UNSPECIFIED
@@ -273,37 +294,18 @@ extends
public static Specialization inferFrom(
final @Nullable ObjectSpecification spec,
final @Nullable Object pojo) {
- if(spec==null) {
- return UNSPECIFIED;
- }
- if(spec.isNonScalar()) {
- return PACKED;
- }
- if(pojo==null) {
- return EMPTY;
- }
- if(spec.isValue()) {
- return VALUE;
- }
- if(spec.isInjectable()) {
- return SERVICE;
- }
- if(spec.isViewModel()) {
- return VIEWMODEL;
- }
- if(spec.isEntity()) {
- return ENTITY;
- }
- if(spec.isMixin()) {
- return MIXIN;
- }
- if(!spec.isAbstract()) {
- return OTHER;
- }
+ if(spec==null) { return UNSPECIFIED; }
+ if(spec.isNonScalar()) { return PACKED; }
+ if(pojo==null) { return EMPTY; }
+ if(spec.isValue()) { return VALUE; }
+ if(spec.isInjectable()) { return SERVICE; }
+ if(spec.isViewModel()) { return VIEWMODEL; }
+ if(spec.isEntity()) { return ENTITY; }
+ if(spec.isMixin()) { return MIXIN; }
+ if(!spec.isAbstract()) { return OTHER; }
log.warn("failed specialization attempt for {}", spec);
return UNSPECIFIED;
}
-
}
/**
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectEntityHybrid.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectEntityHybrid.java
index 91df684f61..99f4bf9ea1 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectEntityHybrid.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectEntityHybrid.java
@@ -125,6 +125,14 @@ implements Refetchable {
.fold(Refetchable::peekAtPojo, Refetchable::peekAtPojo);
}
+ @Override
+ protected boolean isInjectionPointsResolved() {
+ // overriding the default for optimization, let the EntityFacet handle injection
+ // as a side-effect potentially injects if required
+ return getSpecification().entityFacetElseFail()
+ .isInjectionPointsResolved(peekAtPojo());
+ }
+
// -- HELPER
private void triggerReassessment() {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectSpecified.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectSpecified.java
index 76a9f9efe7..d4b1748a4b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectSpecified.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectSpecified.java
@@ -67,12 +67,20 @@ implements ManagedObject {
if(specialization.getTypePolicy().isExactTypeRequired()) {
MmAssertionUtil.assertExactType(specification, pojo);
}
- if(getSpecification().isEntityOrViewModel()) {
- getServiceInjector().injectServicesInto(pojo); // might be redundant
+ if(getSpecialization().getInjectionPolicy().isAlwaysInject()) {
+ if(!isInjectionPointsResolved()) {
+ getServiceInjector().injectServicesInto(pojo); // might be redundant
+ }
}
return pojo;
}
+ /**
+ * override if there is optimization available
+ * @apiNote must only be called by {@link #assertCompliance(Object)}
+ */
+ protected boolean isInjectionPointsResolved() { return false; }
+
@Override
public String getTitle() {
return _InternalTitleUtil.titleString(
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectSpecifiedLegacy.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectSpecifiedLegacy.java
deleted file mode 100644
index 05e17541ca..0000000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectSpecifiedLegacy.java
+++ /dev/null
@@ -1,52 +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.core.metamodel.object;
-
-import java.util.function.Supplier;
-
-import org.apache.isis.core.metamodel.context.MetaModelContext;
-
-import lombok.Getter;
-import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
-import lombok.experimental.Accessors;
-
-@RequiredArgsConstructor
-abstract class _ManagedObjectSpecifiedLegacy
-implements ManagedObject {
-
- @Getter(onMethod_ = {@Override}) @Accessors(makeFinal = true)
- private final Specialization specialization;
-
- @Override
- public final MetaModelContext getMetaModelContext() {
- return getSpecification().getMetaModelContext();
- }
-
- @Override
- public final Supplier<ManagedObject> asSupplier() {
- return ()->this;
- }
-
- @Override
- public final <T> T assertCompliance(final @NonNull T pojo) {
- return pojo; // legacy implementation - don't check
- }
-
-}
diff --git a/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/changetracking/JdoLifecycleListener.java b/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/changetracking/JdoLifecycleListener.java
index 056184fc1f..1d92379e16 100644
--- a/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/changetracking/JdoLifecycleListener.java
+++ b/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/changetracking/JdoLifecycleListener.java
@@ -33,7 +33,6 @@ import org.datanucleus.enhancement.Persistable;
import org.apache.isis.commons.functional.Either;
import org.apache.isis.commons.internal.assertions._Assert;
-import org.apache.isis.commons.internal.base._Casts;
import org.apache.isis.core.metamodel.context.MetaModelContext;
import org.apache.isis.core.metamodel.facets.object.publish.entitychange.EntityChangePublishingFacet;
import org.apache.isis.core.metamodel.object.ManagedObject;
@@ -91,9 +90,7 @@ DetachLifecycleListener, DirtyLifecycleListener, LoadLifecycleListener, StoreLif
log.debug("postLoad {}", ()->_Utils.debug(event));
final Persistable pojo = _Utils.persistableFor(event);
val entity = adaptEntity(pojo);
-
objectLifecyclePublisher.onPostLoad(entity);
-
}
@Override
@@ -153,10 +150,10 @@ DetachLifecycleListener, DirtyLifecycleListener, LoadLifecycleListener, StoreLif
// [ISIS-3126] pre-dirty nested loop prevention,
// assuming we can cast the DN StateManager to the custom one as provided by the framework
- _Casts.castTo(DnObjectProviderForIsis.class, pojo.dnGetStateManager())
- .ifPresentOrElse(stateManager->
- stateManager.acquirePreDirtyPropagationLock(pojo.dnGetObjectId())
- .ifPresent(lock->lock.releaseAfter(doPreDirty)),
+ DnObjectProviderForIsis.extractFrom(pojo).ifPresentOrElse(
+ stateManager->
+ stateManager.acquirePreDirtyPropagationLock(pojo.dnGetObjectId())
+ .ifPresent(lock->lock.releaseAfter(doPreDirty)),
doPreDirty);
}
diff --git a/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/changetracking/_Utils.java b/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/changetracking/_Utils.java
index cd46eb93c0..2d34d36bc5 100644
--- a/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/changetracking/_Utils.java
+++ b/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/changetracking/_Utils.java
@@ -23,12 +23,11 @@ import javax.jdo.ObjectState;
import javax.jdo.listener.InstanceLifecycleEvent;
import org.datanucleus.enhancement.Persistable;
-import org.springframework.lang.Nullable;
import org.apache.isis.commons.internal.assertions._Assert;
import org.apache.isis.core.metamodel.context.MetaModelContext;
import org.apache.isis.core.metamodel.object.ManagedObject;
-import org.apache.isis.core.metamodel.object.ManagedObjects;
+import org.apache.isis.persistence.jdo.datanucleus.entities.DnObjectProviderForIsis;
import lombok.NonNull;
import lombok.val;
@@ -46,19 +45,11 @@ final class _Utils {
final @NonNull InstanceLifecycleEvent event) {
final Persistable pojo = _Utils.persistableFor(event);
if(pojo!=null) {
- mmc.getServiceInjector().injectServicesInto(pojo);
- }
- }
-
- String debug(final InstanceLifecycleEvent event) {
- // try to be side-effect free here ...
- final Persistable pojo = _Utils.persistableFor(event);
- ObjectState state = JDOHelper.getObjectState(pojo);
- //if(state == ObjectState.PERSISTENT_CLEAN) {
- //return String.format("entity: %s", pojo);
- //} else {
- return String.format("entity: %s (%s)", pojo.getClass().getSimpleName(), state);
- //}
+ DnObjectProviderForIsis.extractFrom(pojo)
+ .ifPresentOrElse(
+ DnObjectProviderForIsis::injectServicesIfNotAlready,
+ ()->mmc.getServiceInjector().injectServicesInto(pojo));
+ }
}
ManagedObject adaptEntity(
@@ -71,45 +62,15 @@ final class _Utils {
return entity;
}
- ManagedObject adaptNullableEntity(
- final @NonNull MetaModelContext mmc,
- final @Nullable Object entityPojo) {
-
- return entityPojo == null
- ? ManagedObject.unspecified()
- : adaptEntity(mmc, entityPojo);
- }
-
- ManagedObject adaptNullableAndInjectServices(
- final @NonNull MetaModelContext mmc,
- final @Nullable Object entityPojo) {
-
- return entityPojo == null
- ? ManagedObject.unspecified()
- : adaptEntityAndInjectServices(mmc, entityPojo);
- }
-
- ManagedObject adaptEntityAndInjectServices(
- final @NonNull MetaModelContext mmc,
- final @NonNull Object entityPojo) {
- return injectServices(mmc, adaptEntity(mmc, entityPojo));
- }
-
-
- private static ManagedObject injectServices(
- final @NonNull MetaModelContext mmc,
- final @NonNull ManagedObject adapter) {
-
- if(ManagedObjects.isNullOrUnspecifiedOrEmpty(adapter)) {
- return adapter;
- }
-
- if(adapter.getSpecification().isValue()) {
- return adapter; // guard against value objects
- }
- mmc.getServiceInjector().injectServicesInto(adapter.getPojo());
- return adapter;
+ String debug(final InstanceLifecycleEvent event) {
+ // try to be side-effect free here ...
+ final Persistable pojo = _Utils.persistableFor(event);
+ ObjectState state = JDOHelper.getObjectState(pojo);
+ //if(state == ObjectState.PERSISTENT_CLEAN) {
+ //return String.format("entity: %s", pojo);
+ //} else {
+ return String.format("entity: %s (%s)", pojo.getClass().getSimpleName(), state);
+ //}
}
-
}
diff --git a/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/entities/DnObjectProviderForIsis.java b/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/entities/DnObjectProviderForIsis.java
index 1abbcb9c8f..53db0aac31 100644
--- a/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/entities/DnObjectProviderForIsis.java
+++ b/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/entities/DnObjectProviderForIsis.java
@@ -29,8 +29,10 @@ import org.datanucleus.enhancement.Persistable;
import org.datanucleus.metadata.AbstractClassMetaData;
import org.datanucleus.state.ReferentialStateManagerImpl;
import org.datanucleus.store.FieldValues;
+import org.springframework.lang.Nullable;
import org.apache.isis.applib.services.inject.ServiceInjector;
+import org.apache.isis.commons.internal.base._Casts;
import org.apache.isis.commons.internal.collections._Maps;
import org.apache.isis.core.metamodel.context.MetaModelContext;
import org.apache.isis.persistence.jdo.spring.integration.TransactionAwarePersistenceManagerFactoryProxy;
@@ -54,65 +56,66 @@ extends ReferentialStateManagerImpl {
this.serviceInjector = extractServiceInjectorFrom(ec).orElse(null);
}
+ @SuppressWarnings("rawtypes")
@Override
public void initialiseForHollow(final Object id, final FieldValues fv, final Class pcClass) {
super.initialiseForHollow(id, fv, pcClass);
- injectServices(myPC);
+ injectServicesIfNotAlready();
}
- @SuppressWarnings("deprecation")
+ @SuppressWarnings({ "deprecation", "rawtypes" })
@Override
public void initialiseForHollowAppId(final FieldValues fv, final Class pcClass) {
super.initialiseForHollowAppId(fv, pcClass);
- injectServices(myPC);
+ injectServicesIfNotAlready();
}
@Override
public void initialiseForHollowPreConstructed(final Object id, final Persistable pc) {
super.initialiseForHollowPreConstructed(id, pc);
- injectServices(myPC);
+ injectServicesIfNotAlready();
}
@Override
public void initialiseForPersistentClean(final Object id, final Persistable pc) {
super.initialiseForPersistentClean(id, pc);
- injectServices(myPC);
+ injectServicesIfNotAlready();
}
@Override
public void initialiseForEmbedded(final Persistable pc, final boolean copyPc) {
super.initialiseForEmbedded(pc, copyPc);
- injectServices(myPC);
+ injectServicesIfNotAlready();
}
@Override
public void initialiseForPersistentNew(final Persistable pc, final FieldValues preInsertChanges) {
super.initialiseForPersistentNew(pc, preInsertChanges);
- injectServices(myPC);
+ injectServicesIfNotAlready();
}
@Override
public void initialiseForTransactionalTransient(final Persistable pc) {
super.initialiseForTransactionalTransient(pc);
- injectServices(myPC);
+ injectServicesIfNotAlready();
}
@Override
public void initialiseForDetached(final Persistable pc, final Object id, final Object version) {
super.initialiseForDetached(pc, id, version);
- injectServices(myPC);
+ injectServicesIfNotAlready();
}
@Override
public void initialiseForPNewToBeDeleted(final Persistable pc) {
super.initialiseForPNewToBeDeleted(pc);
- injectServices(myPC);
+ injectServicesIfNotAlready();
}
@Override
public void initialiseForCachedPC(final CachedPC cachedPC, final Object id) {
super.initialiseForCachedPC(cachedPC, id);
- injectServices(myPC);
+ injectServicesIfNotAlready();
}
// -- HELPER
@@ -143,17 +146,29 @@ extends ReferentialStateManagerImpl {
return Optional.of(serviceInjector);
}
- private void injectServices(final Persistable entity) {
- if(entity==null) {
- return;
+ private boolean injectionPointsResolved = false;
+
+ /**
+ * Returns whether injection points are resolved for myPC.
+ */
+ public boolean injectServicesIfNotAlready() {
+ if(myPC==null) {
+ this.injectionPointsResolved = false; // reset
+ return true;
+ }
+ if(injectionPointsResolved) {
+ //XXX would be nice count as a metric
+ return true;
}
if(serviceInjector!=null) {
- serviceInjector.injectServicesInto(entity);
+ serviceInjector.injectServicesInto(myPC);
+ this.injectionPointsResolved = true;
} else {
log.warn("cannot inject services into entity of type {}, "
+ "as there is no ServiceInjector available",
- entity.getClass());
+ myPC.getClass());
}
+ return injectionPointsResolved;
}
// -- [ISIS-3126] PRE-DIRTY NESTED LOOP PREVENTION
@@ -175,6 +190,7 @@ extends ReferentialStateManagerImpl {
private final Map<Object, PreDirtyPropagationLock> preDirtyPropagationLocks =
_Maps.newHashMap();
+ //TODO there is probably only ever one id per instance: verify an simplify
private final PreDirtyPropagationLock createPreDirtyPropagationLock(final Object id) {
return ()->preDirtyPropagationLocks.remove(id);
}
@@ -202,6 +218,14 @@ extends ReferentialStateManagerImpl {
return lockIfGranted;
}
+ // -- UTILITY
+
+ public static Optional<DnObjectProviderForIsis> extractFrom(final @Nullable Persistable pojo) {
+ return pojo!=null
+ ? _Casts.castTo(DnObjectProviderForIsis.class, pojo.dnGetStateManager())
+ : Optional.empty();
+ }
+
// --
/*
diff --git a/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/metamodel/facets/entity/JdoEntityFacet.java b/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/metamodel/facets/entity/JdoEntityFacet.java
index 2e6ac99997..a103cc544e 100644
--- a/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/metamodel/facets/entity/JdoEntityFacet.java
+++ b/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/metamodel/facets/entity/JdoEntityFacet.java
@@ -57,6 +57,7 @@ import org.apache.isis.core.metamodel.objectmanager.ObjectManager;
import org.apache.isis.core.metamodel.services.objectlifecycle.ObjectLifecyclePublisher;
import org.apache.isis.core.runtime.idstringifier.IdStringifierLookupService;
import org.apache.isis.persistence.jdo.datanucleus.entities.DnEntityStateProvider;
+import org.apache.isis.persistence.jdo.datanucleus.entities.DnObjectProviderForIsis;
import org.apache.isis.persistence.jdo.metamodel.facets.object.persistencecapable.JdoPersistenceCapableFacetFactory;
import org.apache.isis.persistence.jdo.provider.entities.JdoFacetContext;
import org.apache.isis.persistence.jdo.spring.integration.TransactionAwarePersistenceManagerFactoryProxy;
@@ -78,6 +79,7 @@ public class JdoEntityFacet
extends FacetAbstract
implements EntityFacet {
+ // self managed injections via getPersistenceManager or getTransactionalProcessor
@Inject private TransactionAwarePersistenceManagerFactoryProxy pmf;
@Inject private TransactionService txService;
@Inject private ObjectManager objectManager;
@@ -119,6 +121,16 @@ implements EntityFacet {
return primaryKeyType;
}
+ @Override
+ public boolean isInjectionPointsResolved(final Object pojo) {
+ if(pojo instanceof Persistable) {
+ DnObjectProviderForIsis.extractFrom((Persistable) pojo)
+ .map(DnObjectProviderForIsis::injectServicesIfNotAlready)
+ .orElse(false);
+ }
+ return pojo==null;
+ }
+
@Override
public Optional<String> identifierFor(final Object pojo) {
@@ -292,8 +304,6 @@ implements EntityFacet {
getTransactionalProcessor()
.runWithinCurrentTransactionElseCreateNew(()->pm.makePersistent(pojo))
.ifFailureFail();
-
- //TODO integrate with entity change tracking
}
@Override
@@ -314,8 +324,6 @@ implements EntityFacet {
getTransactionalProcessor()
.runWithinCurrentTransactionElseCreateNew(()->pm.deletePersistent(pojo))
.ifFailureFail();
-
- //TODO integrate with entity change tracking
}
@Override
@@ -334,8 +342,6 @@ implements EntityFacet {
getTransactionalProcessor()
.runWithinCurrentTransactionElseCreateNew(()->pm.refresh(pojo))
.ifFailureFail();
-
- //TODO integrate with entity change tracking
}
@Override
@@ -359,12 +365,6 @@ implements EntityFacet {
return jdoFacetContext.isMethodProvidedByEnhancement(method);
}
- // -- INTERACTION TRACKER LAZY LOOKUP
-
- // memoizes the lookup, just an optimization
-// private final _Lazy<InteractionLayerTracker> isisInteractionTrackerLazy = _Lazy.threadSafe(
-// ()->getServiceRegistry().lookupServiceElseFail(InteractionLayerTracker.class));
-
// -- DEPENDENCIES
private PersistenceManager getPersistenceManager() {
@@ -381,25 +381,18 @@ implements EntityFacet {
return txService;
}
-// private JdoPersistenceSession getJdoPersistenceSession() {
-// return isisInteractionTrackerLazy.get().currentInteractionSession()
-// .map(interactionSession->interactionSession.getAttribute(JdoPersistenceSession.class))
-// .orElseThrow(()->_Exceptions.illegalState("no JdoPersistenceSession on current thread"));
-// }
-
// -- HELPER
private Can<ManagedObject> fetchWithinTransaction(final Supplier<List<?>> fetcher) {
-
return getTransactionalProcessor().callWithinCurrentTransactionElseCreateNew(
()->_NullSafe.stream(fetcher.get())
- .map(fetchedObject->adopt(objectLifecyclePublisher, fetchedObject))
+ .map(fetchedObject->adapt(objectLifecyclePublisher, fetchedObject))
.collect(Can.toCan()))
.ifFailureFail()
.getValue().orElseThrow();
}
- private ManagedObject adopt(
+ private ManagedObject adapt(
final ObjectLifecyclePublisher objectLifecyclePublisher,
final Object fetchedObject) {
// handles lifecycle callbacks and injects services
@@ -409,7 +402,6 @@ implements EntityFacet {
if(fetchedObject instanceof Persistable) {
// an entity
val entity = objectManager.adapt(fetchedObject);
-
objectLifecyclePublisher.onPostLoad(entity);
return entity;
} else {
diff --git a/persistence/jpa/eclipselink/src/main/java/org/apache/isis/persistence/jpa/eclipselink/inject/_Util.java b/persistence/jpa/eclipselink/src/main/java/org/apache/isis/persistence/jpa/eclipselink/inject/_Util.java
index 189ea980e1..0a97b69afa 100644
--- a/persistence/jpa/eclipselink/src/main/java/org/apache/isis/persistence/jpa/eclipselink/inject/_Util.java
+++ b/persistence/jpa/eclipselink/src/main/java/org/apache/isis/persistence/jpa/eclipselink/inject/_Util.java
@@ -34,17 +34,18 @@ import javax.enterprise.inject.spi.InjectionTarget;
import javax.inject.Provider;
import org.apache.isis.applib.services.inject.ServiceInjector;
+import org.apache.isis.commons.internal._Constants;
import org.apache.isis.commons.internal.exceptions._Exceptions;
import lombok.SneakyThrows;
final class _Util {
- static <T> CreationalContext<T> createCreationalContext(Contextual<T> contextual) {
+ static <T> CreationalContext<T> createCreationalContext(final Contextual<T> contextual) {
return new CreationalContext<T>() {
@Override
- public void push(T incompleteInstance) {
+ public void push(final T incompleteInstance) {
// silently ignore
}
@@ -56,7 +57,7 @@ final class _Util {
};
}
- static <T> AnnotatedType<T> createAnnotatedType(Class<T> type) {
+ static <T> AnnotatedType<T> createAnnotatedType(final Class<T> type) {
return new AnnotatedType<T>() {
@@ -78,7 +79,7 @@ final class _Util {
}
@Override
- public <X extends Annotation> X getAnnotation(Class<X> annotationType) {
+ public <X extends Annotation> X getAnnotation(final Class<X> annotationType) {
_Exceptions.throwNotImplemented();
return null;
}
@@ -90,7 +91,7 @@ final class _Util {
}
@Override
- public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
+ public boolean isAnnotationPresent(final Class<? extends Annotation> annotationType) {
_Exceptions.throwNotImplemented();
return false;
}
@@ -122,17 +123,17 @@ final class _Util {
return new InjectionTarget<T>() {
@Override @SneakyThrows
- public T produce(CreationalContext<T> ctx) {
- return type.getJavaClass().newInstance();
+ public T produce(final CreationalContext<T> ctx) {
+ return type.getJavaClass().getConstructor(_Constants.emptyClasses).newInstance();
}
@Override
- public void inject(T instance, CreationalContext<T> ctx) {
+ public void inject(final T instance, final CreationalContext<T> ctx) {
serviceInjectorProvider.get().injectServicesInto(instance);
}
@Override
- public void dispose(T instance) {
+ public void dispose(final T instance) {
// silently ignore
}
@@ -143,12 +144,12 @@ final class _Util {
}
@Override
- public void postConstruct(T instance) {
+ public void postConstruct(final T instance) {
// silently ignore
}
@Override
- public void preDestroy(T instance) {
+ public void preDestroy(final T instance) {
// silently ignore
}
};
diff --git a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/HomePageReprRenderer.java b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/HomePageReprRenderer.java
index f30b81beb5..9f632da409 100644
--- a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/HomePageReprRenderer.java
+++ b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/HomePageReprRenderer.java
@@ -43,7 +43,7 @@ import lombok.val;
public class HomePageReprRenderer
extends ReprRendererAbstract<Void> {
- // injection points not directly managed by Spring, instead resolved via constructor
+ // self managed injections via constructor
@Inject BrandingUiService brandingUiService;
HomePageReprRenderer(