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 2020/09/01 10:29:20 UTC

[isis] branch master updated (7bcf0dc -> 798a24b)

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

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


    from 7bcf0dc  ISIS-2340: vaa: use converters when binding UI to backend
     new 11fa35f  ISIS-2332: new DomainObject.nature: JPA_ENTITY
     new 798a24b  ISIS-2332: fix spec-loader to consult bean-type-registry for BeanSort

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../org/apache/isis/applib/annotation/Nature.java  | 16 ++++++
 .../core/config/beans/IsisBeanTypeRegistry.java    | 10 +++-
 ...atableObjectFacetForDomainObjectAnnotation.java |  1 +
 .../specloader/SpecificationLoaderDefault.java     | 52 +++++++++++++++-----
 .../specimpl/ObjectSpecificationAbstract.java      | 57 +++++-----------------
 .../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, 103 insertions(+), 60 deletions(-)


[isis] 01/02: ISIS-2332: new DomainObject.nature: JPA_ENTITY

Posted by ah...@apache.org.
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 <ah...@apache.org>
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)
-@lombok.ToString(of = {"correspondingClass", "fullName", "managedObjectSort"})
+@lombok.ToString(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


[isis] 02/02: ISIS-2332: fix spec-loader to consult bean-type-registry for BeanSort

Posted by ah...@apache.org.
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 798a24bce8ba48f16f9de5590a65fb8743f1d9ec
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue Sep 1 12:28:56 2020 +0200

    ISIS-2332: fix spec-loader to consult bean-type-registry for BeanSort
---
 .../core/config/beans/IsisBeanTypeRegistry.java    |  9 +++-
 .../specloader/SpecificationLoaderDefault.java     | 62 +++++++++-------------
 .../specimpl/ObjectSpecificationAbstract.java      | 31 -----------
 3 files changed, 34 insertions(+), 68 deletions(-)

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 bbc12e8..2d1ba6b 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
@@ -82,7 +82,6 @@ public final class IsisBeanTypeRegistry implements IsisComponentScanInterceptor,
 
     @Override
     public void close() {
-
         managedBeanNamesByType.clear();
         introspectableTypes.clear();
         allCategorySets.forEach(Set::clear);
@@ -104,6 +103,12 @@ public final class IsisBeanTypeRegistry implements IsisComponentScanInterceptor,
 
         return defensiveCopy;
     }
+
+    public BeanSort lookupBeanSortByIntrospectableType(Class<?> type) {
+        synchronized (introspectableTypes) {
+            return introspectableTypes.getOrDefault(type, BeanSort.UNKNOWN);
+        }
+    }
     
     public void veto(Class<?> type) {
         vetoedTypes.add(type);
@@ -319,5 +324,7 @@ public final class IsisBeanTypeRegistry implements IsisComponentScanInterceptor,
         return null;
     }
 
+    
+
 
 }
\ No newline at end of file
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 b46a3b2..479ada0 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
@@ -25,6 +25,7 @@ import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Consumer;
+import java.util.function.Function;
 
 import javax.annotation.Nullable;
 import javax.annotation.PostConstruct;
@@ -209,7 +210,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
         facetProcessor.init();
         postProcessor.init();
 
-        val typeRegistry = isisBeanTypeRegistryHolder.getIsisBeanTypeRegistry();
+        val typeRegistry = getIsisBeanTypeRegistry();
 
         val knownSpecs = _Lists.<ObjectSpecification>newArrayList();
 
@@ -365,18 +366,18 @@ 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(
+    private ObjectSpecification loadSpecification(
             final @Nullable Class<?> type,
-            final @NonNull BeanSort sort) {
-        
+            final Function<Class<?>, BeanSort> beanClassifier,
+            final IntrospectionState upTo) {
+
         if(type==null) {
             return null;
         }
 
+        requires(upTo, "upTo");
+        
         val substitute = classSubstitutorRegistry.getSubstitution(type);
         if (substitute.isNeverIntrospect()) {
             return null; // never inspect
@@ -390,46 +391,31 @@ 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, sort));
+            cachedSpec = cache.computeIfAbsent(typeName, __->
+                createSpecification(substitutedType, beanClassifier.apply(type)));
         }
 
-        cachedSpec.introspectUpTo(IntrospectionState.NOT_INTROSPECTED);
+        cachedSpec.introspectUpTo(upTo);
 
         return cachedSpec;
+    }
+
+    @Nullable
+    private ObjectSpecification primeSpecification(
+            final @Nullable Class<?> type,
+            final @NonNull BeanSort sort) {
+        return loadSpecification(type, __->sort, IntrospectionState.NOT_INTROSPECTED);
         
     }
-    
+
     
     @Override @Nullable
     public ObjectSpecification loadSpecification(
             final @Nullable Class<?> type,
             final IntrospectionState upTo) {
 
-        if(type==null) {
-            return null;
-        }
-
-        requires(upTo, "upTo");
-        
-        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, BeanSort.UNKNOWN));
-        }
-
-        cachedSpec.introspectUpTo(upTo);
-
-        return cachedSpec;
+        return loadSpecification(
+                type, __->getIsisBeanTypeRegistry().lookupBeanSortByIntrospectableType(type), upTo);
     }
 
     @Override
@@ -509,6 +495,10 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
 
     // -- HELPER
     
+    private IsisBeanTypeRegistry getIsisBeanTypeRegistry() {
+        return isisBeanTypeRegistryHolder.getIsisBeanTypeRegistry();
+    }
+    
     private void guardAgainstMetamodelLockedAfterFullIntrospection(final Class<?> cls) {
         if(isMetamodelFullyIntrospected() 
                 && isisConfiguration.getCore().getMetaModel().getIntrospector().isLockAfterFullIntrospection()) {
@@ -550,7 +540,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
 
         // ... and create the specs
 
-        val typeRegistry = isisBeanTypeRegistryHolder.getIsisBeanTypeRegistry();
+        val typeRegistry = getIsisBeanTypeRegistry();
 
         val managedBeanNameIfAny = typeRegistry.getManagedBeanNameForType(cls);
         val objectSpec = new ObjectSpecificationDefault(
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 74609ea..0ef31b0 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
@@ -56,10 +56,8 @@ import org.apache.isis.core.metamodel.facets.all.describedas.DescribedAsFacet;
 import org.apache.isis.core.metamodel.facets.all.help.HelpFacet;
 import org.apache.isis.core.metamodel.facets.all.hide.HiddenFacet;
 import org.apache.isis.core.metamodel.facets.all.named.NamedFacet;
-import org.apache.isis.core.metamodel.facets.collections.CollectionFacet;
 import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet;
 import org.apache.isis.core.metamodel.facets.object.encodeable.EncodableFacet;
-import org.apache.isis.core.metamodel.facets.object.entity.EntityFacet;
 import org.apache.isis.core.metamodel.facets.object.icon.IconFacet;
 import org.apache.isis.core.metamodel.facets.object.immutable.ImmutableFacet;
 import org.apache.isis.core.metamodel.facets.object.mixin.MixinFacet;
@@ -69,8 +67,6 @@ import org.apache.isis.core.metamodel.facets.object.parented.ParentedCollectionF
 import org.apache.isis.core.metamodel.facets.object.parseable.ParseableFacet;
 import org.apache.isis.core.metamodel.facets.object.plural.PluralFacet;
 import org.apache.isis.core.metamodel.facets.object.title.TitleFacet;
-import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
-import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
 import org.apache.isis.core.metamodel.interactions.InteractionContext;
 import org.apache.isis.core.metamodel.interactions.InteractionUtils;
 import org.apache.isis.core.metamodel.interactions.ObjectTitleContext;
@@ -964,31 +960,4 @@ implements ObjectSpecification {
                 .getIsisBeanTypeRegistry();
     }
 
-    //TODO just make 'sort' a field of ObjectSpecification 
-    protected BeanSort sortOf(ObjectSpecification spec) {
-
-        if(isManagedBean()) { // <-- not a facet, because we get this information earlier (during class scanning)
-            return BeanSort.MANAGED_BEAN_CONTRIBUTING;
-        }
-        if(containsFacet(ValueFacet.class)) {
-            return BeanSort.VALUE;
-        }
-        if(containsFacet(ViewModelFacet.class)) {
-            return BeanSort.VIEW_MODEL;
-        }
-        if(containsFacet(MixinFacet.class)) {
-            return BeanSort.MIXIN;
-        }
-        if(containsFacet(CollectionFacet.class)) {
-            return BeanSort.COLLECTION;
-        }
-        if(containsFacet(EntityFacet.class)) {
-            return BeanSort.ENTITY;
-        }
-
-        return BeanSort.UNKNOWN;
-    }
-
-
-
 }