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
commit 11fa35fbb4f360a64b481f8ad5335f7f9626a574 Author: Andi Huber <[email protected]> AuthorDate: Tue Sep 1 11:47:59 2020 +0200 ISIS-2332: new DomainObject.nature: JPA_ENTITY also when spec-loading initially, use the immutable BeanSort from quick classification (as determined during class scanning) --- .../org/apache/isis/applib/annotation/Nature.java | 16 +++++++ .../core/config/beans/IsisBeanTypeRegistry.java | 1 + ...atableObjectFacetForDomainObjectAnnotation.java | 1 + .../specloader/SpecificationLoaderDefault.java | 54 ++++++++++++++++++---- .../specimpl/ObjectSpecificationAbstract.java | 26 +++++------ .../specimpl/dflt/ObjectSpecificationDefault.java | 4 +- .../bootstrapping/JpaBootstrappingTest.java | 11 +++++ .../isis/testdomain/jpa/entities/JpaBook.java | 2 + .../isis/testdomain/jpa/entities/JpaInventory.java | 2 + .../isis/testdomain/jpa/entities/JpaProduct.java | 4 +- .../testdomain/jpa/entities/JpaProductComment.java | 4 +- 11 files changed, 101 insertions(+), 24 deletions(-) diff --git a/api/applib/src/main/java/org/apache/isis/applib/annotation/Nature.java b/api/applib/src/main/java/org/apache/isis/applib/annotation/Nature.java index b044747..8ac77a7 100644 --- a/api/applib/src/main/java/org/apache/isis/applib/annotation/Nature.java +++ b/api/applib/src/main/java/org/apache/isis/applib/annotation/Nature.java @@ -55,6 +55,22 @@ public enum Nature { */ // tag::refguide[] JDO_ENTITY, + + // end::refguide[] + /** + * A domain entity whose persistence is managed internally by Isis, using JPA as the persistence implementation. + * Domain entities are considered to be part of the domain model layer. + * + * <p> + * Domain entities are considered to be part of the domain model layer. + * </p> + * + * <p> + * Currently implies no additional semantics other than documentation. + * </p> + */ + // tag::refguide[] + JPA_ENTITY, // end::refguide[] /** diff --git a/core/config/src/main/java/org/apache/isis/core/config/beans/IsisBeanTypeRegistry.java b/core/config/src/main/java/org/apache/isis/core/config/beans/IsisBeanTypeRegistry.java index f37a595..bbc12e8 100644 --- a/core/config/src/main/java/org/apache/isis/core/config/beans/IsisBeanTypeRegistry.java +++ b/core/config/src/main/java/org/apache/isis/core/config/beans/IsisBeanTypeRegistry.java @@ -273,6 +273,7 @@ public final class IsisBeanTypeRegistry implements IsisComponentScanInterceptor, case MIXIN: return BeanClassification.selfManaged(BeanSort.MIXIN); case JDO_ENTITY: + case JPA_ENTITY: return BeanClassification.selfManaged(BeanSort.ENTITY); case EXTERNAL_ENTITY: case INMEMORY_ENTITY: diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/recreatable/RecreatableObjectFacetForDomainObjectAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/recreatable/RecreatableObjectFacetForDomainObjectAnnotation.java index d1d0c3b..1b41056 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/recreatable/RecreatableObjectFacetForDomainObjectAnnotation.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/recreatable/RecreatableObjectFacetForDomainObjectAnnotation.java @@ -43,6 +43,7 @@ extends RecreatableObjectFacetDeclarativeInitializingAbstract { case NOT_SPECIFIED: case BEAN: case JDO_ENTITY: + case JPA_ENTITY: case MIXIN: // not a recreatable object, so no facet return null; diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java index 14d9046..b46a3b2 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java @@ -38,6 +38,7 @@ import org.springframework.core.annotation.Order; import org.springframework.stereotype.Service; import org.apache.isis.applib.annotation.OrderPrecedence; +import org.apache.isis.applib.services.metamodel.BeanSort; import org.apache.isis.applib.services.registry.ServiceRegistry; import org.apache.isis.core.commons.internal.assertions._Assert; import org.apache.isis.core.commons.internal.base._Blackhole; @@ -75,6 +76,7 @@ import org.apache.isis.core.metamodel.valuetypes.ValueTypeRegistry; import static org.apache.isis.core.commons.internal.base._With.requires; import lombok.Getter; +import lombok.NonNull; import lombok.Setter; import lombok.val; import lombok.extern.log4j.Log4j2; @@ -237,9 +239,9 @@ public class SpecificationLoaderDefault implements SpecificationLoader { .forEach(entry->{ val type = entry.getKey(); - val sort = entry.getValue(); - - val spec = loadSpecification(type, IntrospectionState.NOT_INTROSPECTED); + val sort = entry.getValue(); + + val spec = primeSpecification(type, sort); if(spec==null) { typeRegistry.veto(type); return; @@ -286,7 +288,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader { setMetamodelFullyIntrospected(true); } } - + @Override public ValidationFailures getValidationResult() { return validationResult.get(); @@ -363,9 +365,44 @@ public class SpecificationLoaderDefault implements SpecificationLoader { return true; } + + //TODO[ISIS-2332] when the cache is cleared, sort information get's lost + //instead better integrate the isis bean type registry with the spec loading + @Nullable + private ObjectSpecification primeSpecification( + final @Nullable Class<?> type, + final @NonNull BeanSort sort) { + + if(type==null) { + return null; + } + + val substitute = classSubstitutorRegistry.getSubstitution(type); + if (substitute.isNeverIntrospect()) { + return null; // never inspect + } + + val substitutedType = substitute.apply(type); + + val typeName = substitutedType.getName(); + + final ObjectSpecification cachedSpec; + + // we try not to block on long running code ... 'spec.introspectUpTo(upTo);' + synchronized (cache) { + cachedSpec = cache.computeIfAbsent(typeName, __->createSpecification(substitutedType, sort)); + } + + cachedSpec.introspectUpTo(IntrospectionState.NOT_INTROSPECTED); + + return cachedSpec; + + } + + @Override @Nullable public ObjectSpecification loadSpecification( - @Nullable final Class<?> type, + final @Nullable Class<?> type, final IntrospectionState upTo) { if(type==null) { @@ -387,7 +424,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader { // we try not to block on long running code ... 'spec.introspectUpTo(upTo);' synchronized (cache) { - cachedSpec = cache.computeIfAbsent(typeName, __->createSpecification(substitutedType)); + cachedSpec = cache.computeIfAbsent(typeName, __->createSpecification(substitutedType, BeanSort.UNKNOWN)); } cachedSpec.introspectUpTo(upTo); @@ -507,7 +544,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader { /** * Creates the appropriate type of {@link ObjectSpecification}. */ - private ObjectSpecification createSpecification(final Class<?> cls) { + private ObjectSpecification createSpecification(final Class<?> cls, final BeanSort beanSort) { guardAgainstMetamodelLockedAfterFullIntrospection(cls); @@ -518,6 +555,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader { val managedBeanNameIfAny = typeRegistry.getManagedBeanNameForType(cls); val objectSpec = new ObjectSpecificationDefault( cls, + beanSort, metaModelContext, facetProcessor, managedBeanNameIfAny.orElse(null), @@ -548,7 +586,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader { .forEach(spec -> { try { spec.introspectUpTo(upTo); - } catch (Throwable ex) { + } catch (Throwable ex) { log.error(ex); throw ex; } diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java index a8fe145..74609ea 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java @@ -95,7 +95,7 @@ import lombok.val; import lombok.extern.log4j.Log4j2; @EqualsAndHashCode(of = "correspondingClass", callSuper = false) [email protected](of = {"correspondingClass", "fullName", "managedObjectSort"}) [email protected](of = {"correspondingClass", "fullName", "beanSort"}) @Log4j2 public abstract class ObjectSpecificationAbstract extends FacetHolderImpl @@ -206,12 +206,14 @@ implements ObjectSpecification { public ObjectSpecificationAbstract( final Class<?> introspectedClass, final String shortName, + final BeanSort beanSort, final FacetProcessor facetProcessor, final PostProcessor postProcessor) { this.correspondingClass = introspectedClass; this.fullName = introspectedClass.getName(); this.shortName = shortName; + this.beanSort = beanSort; this.isAbstract = ClassExtensions.isAbstract(introspectedClass); @@ -876,19 +878,17 @@ implements ObjectSpecification { return new ObjectValidityContext(targetAdapter, getIdentifier(), interactionInitiatedBy); } - private BeanSort managedObjectSort; + //@Setter(AccessLevel.PROTECTED) + @Getter + private final BeanSort beanSort; - @Override - public BeanSort getBeanSort() { - if(managedObjectSort==null) { - setManagedObjectSort(sortOf(this)); - } - return managedObjectSort; - } - - protected void setManagedObjectSort(BeanSort managedObjectSort) { - this.managedObjectSort = managedObjectSort; - } +// @Override +// public BeanSort getBeanSort() { +// if(beanSort==null) { +// setBeanSort(sortOf(this)); +// } +// return beanSort; +// } // -- convenience isXxx (looked up from facets) diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java index d985165..9ccfeed 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java @@ -30,6 +30,7 @@ import javax.annotation.Nullable; import org.apache.isis.applib.Identifier; import org.apache.isis.applib.annotation.NatureOfService; +import org.apache.isis.applib.services.metamodel.BeanSort; import org.apache.isis.core.commons.collections.Can; import org.apache.isis.core.commons.internal.base._Lazy; import org.apache.isis.core.commons.internal.collections._Lists; @@ -100,13 +101,14 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl public ObjectSpecificationDefault( final Class<?> correspondingClass, + final BeanSort beanSort, final MetaModelContext metaModelContext, final FacetProcessor facetProcessor, final String nameIfIsManagedBean, final PostProcessor postProcessor, final ClassSubstitutorRegistry classSubstitutorRegistry) { - super(correspondingClass, determineShortName(correspondingClass), facetProcessor, postProcessor); + super(correspondingClass, determineShortName(correspondingClass), beanSort, facetProcessor, postProcessor); setMetaModelContext(metaModelContext); diff --git a/examples/smoketests/incubating/src/test/java/org/apache/isis/testdomain/bootstrapping/JpaBootstrappingTest.java b/examples/smoketests/incubating/src/test/java/org/apache/isis/testdomain/bootstrapping/JpaBootstrappingTest.java index 155868e..79ad201 100644 --- a/examples/smoketests/incubating/src/test/java/org/apache/isis/testdomain/bootstrapping/JpaBootstrappingTest.java +++ b/examples/smoketests/incubating/src/test/java/org/apache/isis/testdomain/bootstrapping/JpaBootstrappingTest.java @@ -43,6 +43,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import org.apache.isis.applib.services.repository.RepositoryService; import org.apache.isis.core.config.presets.IsisPresets; +import org.apache.isis.core.metamodel.facets.object.entity.EntityFacet; +import org.apache.isis.core.metamodel.specloader.SpecificationLoader; import org.apache.isis.core.runtime.iactn.IsisInteractionFactory; import org.apache.isis.testdomain.Incubating; import org.apache.isis.testdomain.Smoketest; @@ -67,6 +69,7 @@ class JpaBootstrappingTest /*extends IsisIntegrationTestAbstract*/ { @Inject private Optional<PlatformTransactionManager> platformTransactionManager; @Inject private RepositoryService repository; @Inject private IsisInteractionFactory isisInteractionFactory; + @Inject private SpecificationLoader specLoader; //@Inject private TransactionService transactionService; @BeforeAll @@ -106,6 +109,14 @@ class JpaBootstrappingTest /*extends IsisIntegrationTestAbstract*/ { assertTrue(platformTransactionManager.isPresent()); } + @Test @Order(0) + void jpaEntities_shouldBeRecognisedAsSuch() { + val spec = specLoader.loadSpecification(JpaProduct.class); + assertTrue(spec.isEntity()); + assertNotNull(spec.getFacet(EntityFacet.class)); + } + + @Test @Order(1) @Rollback(false) void sampleInventoryShouldBeSetUp() { diff --git a/examples/smoketests/stable/src/main/java/org/apache/isis/testdomain/jpa/entities/JpaBook.java b/examples/smoketests/stable/src/main/java/org/apache/isis/testdomain/jpa/entities/JpaBook.java index ceccbc8..9db0b9a 100644 --- a/examples/smoketests/stable/src/main/java/org/apache/isis/testdomain/jpa/entities/JpaBook.java +++ b/examples/smoketests/stable/src/main/java/org/apache/isis/testdomain/jpa/entities/JpaBook.java @@ -23,6 +23,7 @@ import javax.persistence.Entity; import org.apache.isis.applib.annotation.Auditing; import org.apache.isis.applib.annotation.DomainObject; +import org.apache.isis.applib.annotation.Nature; import org.apache.isis.applib.annotation.Property; import org.apache.isis.applib.annotation.Publishing; @@ -37,6 +38,7 @@ import lombok.ToString; //@Discriminator(value="Book") @DomainObject( objectType = "testdomain.jpa.Book", + nature = Nature.JPA_ENTITY, //TODO[ISIS-2332] should not be required, when using JPA quick classify SPI publishing=Publishing.ENABLED, auditing = Auditing.ENABLED) @NoArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/examples/smoketests/stable/src/main/java/org/apache/isis/testdomain/jpa/entities/JpaInventory.java b/examples/smoketests/stable/src/main/java/org/apache/isis/testdomain/jpa/entities/JpaInventory.java index 543e14a..8d49f05 100644 --- a/examples/smoketests/stable/src/main/java/org/apache/isis/testdomain/jpa/entities/JpaInventory.java +++ b/examples/smoketests/stable/src/main/java/org/apache/isis/testdomain/jpa/entities/JpaInventory.java @@ -26,6 +26,7 @@ import javax.persistence.Entity; import org.apache.isis.applib.annotation.Auditing; import org.apache.isis.applib.annotation.DomainObject; import org.apache.isis.applib.annotation.DomainObjectLayout; +import org.apache.isis.applib.annotation.Nature; import org.apache.isis.applib.annotation.Property; import lombok.AccessLevel; @@ -41,6 +42,7 @@ import lombok.ToString; //@Version(strategy= VersionStrategy.DATE_TIME, column="version") @DomainObject( objectType = "testdomain.jdo.Inventory", + nature = Nature.JPA_ENTITY, //TODO[ISIS-2332] should not be required, when using JPA quick classify SPI auditing = Auditing.ENABLED) @DomainObjectLayout() // causes UI events to be triggered @NoArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/examples/smoketests/stable/src/main/java/org/apache/isis/testdomain/jpa/entities/JpaProduct.java b/examples/smoketests/stable/src/main/java/org/apache/isis/testdomain/jpa/entities/JpaProduct.java index 6cc0461..ec03682 100644 --- a/examples/smoketests/stable/src/main/java/org/apache/isis/testdomain/jpa/entities/JpaProduct.java +++ b/examples/smoketests/stable/src/main/java/org/apache/isis/testdomain/jpa/entities/JpaProduct.java @@ -30,6 +30,7 @@ import javax.persistence.Id; import org.apache.isis.applib.annotation.Collection; import org.apache.isis.applib.annotation.DomainObject; import org.apache.isis.applib.annotation.Editing; +import org.apache.isis.applib.annotation.Nature; import org.apache.isis.applib.annotation.Property; import lombok.AccessLevel; @@ -44,7 +45,8 @@ import lombok.ToString; //@Inheritance(strategy=InheritanceStrategy.NEW_TABLE) //@Discriminator(strategy=DiscriminatorStrategy.VALUE_MAP, value="Product") @DomainObject( - objectType = "testdomain.jpa.Product" + objectType = "testdomain.jpa.Product", + nature = Nature.JPA_ENTITY //TODO[ISIS-2332] should not be required, when using JPA quick classify SPI ) @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/examples/smoketests/stable/src/main/java/org/apache/isis/testdomain/jpa/entities/JpaProductComment.java b/examples/smoketests/stable/src/main/java/org/apache/isis/testdomain/jpa/entities/JpaProductComment.java index bf3afbb..24634ac 100644 --- a/examples/smoketests/stable/src/main/java/org/apache/isis/testdomain/jpa/entities/JpaProductComment.java +++ b/examples/smoketests/stable/src/main/java/org/apache/isis/testdomain/jpa/entities/JpaProductComment.java @@ -27,6 +27,7 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import org.apache.isis.applib.annotation.DomainObject; +import org.apache.isis.applib.annotation.Nature; import org.apache.isis.applib.annotation.Property; import org.apache.isis.applib.mixins.timestamp.Timestampable; @@ -35,7 +36,8 @@ import lombok.Setter; @Entity @DomainObject( - objectType = "testdomain.jpa.ProductComment") + objectType = "testdomain.jpa.ProductComment", + nature = Nature.JPA_ENTITY) //TODO[ISIS-2332] should not be required, when using JPA quick classify SPI public class JpaProductComment implements Timestampable { @Id
