You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by ah...@apache.org on 2024/11/14 13:03:50 UTC

(causeway) branch v3 updated: CAUSEWAY-2297: attempt to clean the spec loader up a bit

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

ahuber pushed a commit to branch v3
in repository https://gitbox.apache.org/repos/asf/causeway.git


The following commit(s) were added to refs/heads/v3 by this push:
     new cec59712bf4 CAUSEWAY-2297: attempt to clean the spec loader up a bit
cec59712bf4 is described below

commit cec59712bf4f890e106a68562c18aa7efe00b6fe
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Nov 14 14:03:44 2024 +0100

    CAUSEWAY-2297: attempt to clean the spec loader up a bit
---
 .../beans/CausewayBeanFactoryPostProcessor.java    |  21 ++-
 .../core/config/beans/CausewayBeanMetaData.java    |   9 +-
 .../config/beans/CausewayBeanTypeClassifier.java   |  22 +--
 .../config/beans/CausewayBeanTypeRegistry.java     | 115 ++++++------
 .../_testing/MetaModelContext_forTesting.java      |   2 +-
 .../NavigableParentAnnotationFacetFactory.java     |   4 +-
 .../annotation/TitleAnnotationFacetFactory.java    |   2 +-
 .../ClassSubstitutorForDomainObjects.java          |   2 +-
 .../core/metamodel/spec/feature/ObjectFeature.java |   4 +-
 .../specloader/SpecificationLoaderDefault.java     | 201 ++++++++++-----------
 .../homepage/HomePageResolverServiceDefault.java   |   5 +-
 .../integtest/CommandLog_IntegTestAbstract.java    |   6 +-
 .../scripts/SeedUsersAndRolesFixtureScript.java    |   2 +-
 .../causeway/tabular/applib/DataTableProvider.java |   2 +-
 .../CausewayModulePersistenceJdoDatanucleus.java   |  13 +-
 .../EntityPropertyChangeSubscriberForTesting.java  |   2 +-
 .../bootstrapping/AutoConfigurationTest.java       |   2 +-
 .../CmdExecAuditSessLog_IntegTestAbstract.java     |   2 +-
 .../DomainModelTest_usingBadDomain.java            |   2 +-
 19 files changed, 209 insertions(+), 209 deletions(-)

diff --git a/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanFactoryPostProcessor.java b/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanFactoryPostProcessor.java
index 290be48005c..d457ce825c4 100644
--- a/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanFactoryPostProcessor.java
+++ b/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanFactoryPostProcessor.java
@@ -40,7 +40,7 @@ import org.apache.causeway.commons.collections.Can;
 import org.apache.causeway.commons.internal.base._NullSafe;
 import org.apache.causeway.commons.internal.base._Timing;
 import org.apache.causeway.core.config.CausewayModuleCoreConfig;
-import org.apache.causeway.core.config.beans.CausewayBeanTypeClassifier.Mode;
+import org.apache.causeway.core.config.beans.CausewayBeanTypeClassifier.ContextType;
 import org.apache.causeway.core.config.beans.aoppatch.AopPatch;
 
 import lombok.extern.log4j.Log4j2;
@@ -68,7 +68,7 @@ implements
     ApplicationContextAware {
 
     private CausewayBeanTypeClassifier causewayBeanTypeClassifier;
-    private Can<CausewayBeanMetaData> componentScanResult = Can.empty();
+    private CausewayBeanTypeRegistry componentScanResult = CausewayBeanTypeRegistry.empty();
 
     @Override
     public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
@@ -94,26 +94,27 @@ implements
 
         beanFactory.registerScope("causeway-domain-object", new CausewayDomainObjectScope(beanFactory));
 
-        this.componentScanResult = Can.ofCollection(componentCollector.introspectableTypes().values());
+        this.componentScanResult = new CausewayBeanTypeRegistry(
+                Can.ofCollection(componentCollector.introspectableTypes().values()));
 
         log.info("post processing {} bean definitions took {}ms", _NullSafe.size(beanDefNames), stopWatch.getMillis());
+
+        if(log.isDebugEnabled()) {
+            componentScanResult.streamScannedTypes()
+                .forEach(type->log.debug("discovered: {}", type));
+        }
     }
 
     @Bean(name = CausewayModuleCoreConfig.NAMESPACE + ".CausewayBeanTypeClassifier")
     public CausewayBeanTypeClassifier getCausewayBeanTypeClassifier() {
         return causewayBeanTypeClassifier!=null
                 ? causewayBeanTypeClassifier
-                : (causewayBeanTypeClassifier = new CausewayBeanTypeClassifier(Can.empty(), Mode.MOCKUP)); // JUnit support
+                : (causewayBeanTypeClassifier = new CausewayBeanTypeClassifier(Can.empty(), ContextType.MOCKUP)); // JUnit support
     }
 
     @Bean(name = CausewayModuleCoreConfig.NAMESPACE + ".CausewayBeanTypeRegistry")
     public CausewayBeanTypeRegistry getComponentScanResult() {
-        if(log.isDebugEnabled()) {
-            componentScanResult.forEach(type->{
-                log.debug("to be introspected: {}", type);
-            });
-        }
-        return new CausewayBeanTypeRegistry(componentScanResult);
+        return componentScanResult;
     }
 
 }
diff --git a/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanMetaData.java b/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanMetaData.java
index d58127ba208..3f599932a2e 100644
--- a/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanMetaData.java
+++ b/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanMetaData.java
@@ -46,6 +46,7 @@ implements Serializable {
         public boolean isJpa() { return this == JPA; }
         public boolean isJdo() { return this == JDO; }
         public boolean isUnspecified() { return this == UNSPECIFIED; }
+        public boolean isPresent() { return this == JPA || this == JDO; }
 
         public String titleCase() {
             return _Strings.capitalize(_Strings.lower(name()));
@@ -53,9 +54,11 @@ implements Serializable {
     }
 
     public enum DiscoveredBy {
-        CAUSEWAY,
+        CAUSEWAY_UPFRONT,
+        CAUSEWAY_ONTHEFLY,
         SPRING;
-        boolean isCauseway() { return this == CAUSEWAY; }
+        //boolean isCauseway() { return this == CAUSEWAY; }
+        //boolean isCausewayTest() { return this == CAUSEWAY_LAZY; }
         boolean isSpring() { return this == SPRING; }
     }
 
@@ -121,7 +124,7 @@ implements Serializable {
     }
     public static CausewayBeanMetaData programmatic(
             final @NonNull LogicalType logicalType) {
-        return new CausewayBeanMetaData(logicalType, BeanSort.PROGRAMMATIC, DiscoveredBy.CAUSEWAY, ManagedBy.CAUSEWAY, PersistenceStack.NONE);
+        return new CausewayBeanMetaData(logicalType, BeanSort.PROGRAMMATIC, DiscoveredBy.CAUSEWAY_ONTHEFLY, ManagedBy.CAUSEWAY, PersistenceStack.NONE);
     }
     public static CausewayBeanMetaData springContributing(
             final @NonNull LogicalType logicalType) {
diff --git a/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanTypeClassifier.java b/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanTypeClassifier.java
index bdaba61fcea..0b91e695d92 100644
--- a/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanTypeClassifier.java
+++ b/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanTypeClassifier.java
@@ -47,9 +47,9 @@ import lombok.NonNull;
 public record CausewayBeanTypeClassifier(
         @NonNull Can<String> activeProfiles,
         @NonNull _ClassCache classCache,
-        @NonNull Mode mode) {
+        @NonNull ContextType contextType) {
 
-    public enum Mode {
+    public enum ContextType {
         SPRING,
         MOCKUP
     }
@@ -57,11 +57,11 @@ public record CausewayBeanTypeClassifier(
     // -- CONSTRUCTION
 
     CausewayBeanTypeClassifier(final ApplicationContext applicationContext) {
-        this(Can.ofArray(applicationContext.getEnvironment().getActiveProfiles()), Mode.SPRING);
+        this(Can.ofArray(applicationContext.getEnvironment().getActiveProfiles()), ContextType.SPRING);
     }
 
-    CausewayBeanTypeClassifier(final Can<String> activeProfiles, final Mode mode) {
-        this(activeProfiles, _ClassCache.getInstance(), mode);
+    CausewayBeanTypeClassifier(final Can<String> activeProfiles, final ContextType contextType) {
+        this(activeProfiles, _ClassCache.getInstance(), contextType);
     }
 
     // -- CLASSIFY
@@ -116,14 +116,12 @@ public record CausewayBeanTypeClassifier(
             return CausewayBeanMetaData.vetoed(named.get(), discoveredBy); // reject
         }
 
-        // handle introspection veto ...
+        // handle introspection veto (programmatic bean) ...
         if(TypeProgrammaticMarker.anyMatchOn(typeHead)) {
-            return switch (mode) {
-                case SPRING -> switch (discoveredBy) {
-                     case SPRING -> CausewayBeanMetaData.springNotContributing(logicalType);
-                     case CAUSEWAY -> CausewayBeanMetaData.programmatic(named.get());
-                };
-                case MOCKUP -> CausewayBeanMetaData.springNotContributing(logicalType);
+            if(contextType==ContextType.MOCKUP) return CausewayBeanMetaData.springNotContributing(logicalType);
+            return switch (discoveredBy) {
+                 case SPRING, CAUSEWAY_UPFRONT -> CausewayBeanMetaData.springNotContributing(logicalType);
+                 case CAUSEWAY_ONTHEFLY -> CausewayBeanMetaData.programmatic(named.get());
             };
         }
 
diff --git a/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanTypeRegistry.java b/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanTypeRegistry.java
index 20445e22f55..7e63f4b7f8f 100644
--- a/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanTypeRegistry.java
+++ b/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanTypeRegistry.java
@@ -18,58 +18,72 @@
  */
 package org.apache.causeway.core.config.beans;
 
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Optional;
-import java.util.Set;
 import java.util.stream.Stream;
 
+import org.springframework.lang.Nullable;
+
+import org.apache.causeway.applib.annotation.HomePage;
 import org.apache.causeway.applib.annotation.Programmatic;
 import org.apache.causeway.commons.collections.Can;
+import org.apache.causeway.commons.internal.reflection._ClassCache;
 import org.apache.causeway.core.config.beans.CausewayBeanMetaData.PersistenceStack;
 
 import lombok.NonNull;
 
 /**
  * Holds discovered domain types grouped by bean-sort.
+ * <p>
+ * Except for view models, types need to be eagerly discovered by Spring,
+ * hence collections of those types cannot be modified on the fly.
  */
 @Programmatic
 public class CausewayBeanTypeRegistry {
 
+    public static CausewayBeanTypeRegistry empty() {
+        return new CausewayBeanTypeRegistry(Can.empty());
+    }
+    
     /**
      * (immutable) scan result, as used by the SpecificationLoader for introspection
      */
-    private final Can<CausewayBeanMetaData> introspectableTypes;
-    private final Map<Class<?>, CausewayBeanMetaData> introspectableTypesByClass = new HashMap<>();
+    private final Can<CausewayBeanMetaData> scannedTypes;
+    private final Can<CausewayBeanMetaData> entities;
+    private final PersistenceStack persistenceStack;
+    
+    private final Map<Class<?>, CausewayBeanMetaData> scannedTypesByClass = new HashMap<>();
 
     // -- DISTINCT CATEGORIES OF BEAN SORTS
 
-    private final Map<Class<?>, CausewayBeanMetaData> managedBeansContributing = new HashMap<>();
-    private final Map<Class<?>, CausewayBeanMetaData> entityTypes = new HashMap<>();
+    private final Map<Class<?>, CausewayBeanMetaData> domainServices = new HashMap<>();
     private final Map<Class<?>, CausewayBeanMetaData> viewmodelTypes = new HashMap<>();
     private final Map<Class<?>, CausewayBeanMetaData> mixinTypes = new HashMap<>();
     private final Map<Class<?>, CausewayBeanMetaData> valueTypes = new HashMap<>();
 
     // -- CONSTRUCTOR
 
-    public CausewayBeanTypeRegistry(final @NonNull Can<CausewayBeanMetaData> introspectableTypes) {
-        this.introspectableTypes = introspectableTypes;
+    CausewayBeanTypeRegistry(final @NonNull Can<CausewayBeanMetaData> scannedTypes) {
+        this.scannedTypes = scannedTypes;
 
-        introspectableTypes.forEach(typeMeta->{
+        var entityTypes = new HashMap<Class<?>, CausewayBeanMetaData>();
+        
+        scannedTypes.forEach(typeMeta->{
 
             var cls = typeMeta.getCorrespondingClass();
 
-            introspectableTypesByClass.put(cls, typeMeta);
+            scannedTypesByClass.put(cls, typeMeta);
 
             switch (typeMeta.beanSort()) {
             case MANAGED_BEAN_CONTRIBUTING:
-                managedBeansContributing.put(cls, typeMeta);
+                domainServices.put(cls, typeMeta);
                 return;
             case MIXIN:
                 mixinTypes.put(cls, typeMeta);
                 return;
             case ENTITY:
+                if(!typeMeta.persistenceStack().isPresent()) return;
                 entityTypes.put(cls, typeMeta);
                 return;
             case VIEW_MODEL:
@@ -89,61 +103,60 @@ public class CausewayBeanTypeRegistry {
                 return;
             }
         });
+        
+        this.entities = Can.ofCollection(entityTypes.values());
+        this.persistenceStack = entities.stream()
+                .map(CausewayBeanMetaData::persistenceStack)
+                .filter(PersistenceStack::isPresent)
+                .findFirst()
+                .orElse(PersistenceStack.UNSPECIFIED);
     }
 
-    // -- SIZE
-
-    public int managedBeansContributingCount() { return managedBeansContributing.size(); }
-    public int entityTypeCount() { return entityTypes.size(); }
-    public int viewmodelTypeCount() { return viewmodelTypes.size(); }
-    public int mixinTypeCount() { return mixinTypes.size(); }
-    public int valueTypeCount() { return valueTypes.size(); }
+    // -- FIELDS
 
-    // -- STREAM
+    /**
+     * Returns 'JDO' or 'JPA' based on metadata found during {@link CausewayBeanTypeClassifier type-classification}.
+     * If no (concrete) entity type is found, returns 'UNSPECIFIED'.
+     * @implNote assumes that there can be only one persistence stack
+     */
+    public PersistenceStack persistenceStack() {
+        return persistenceStack; 
+    }
+    
+    // -- STREAMS
 
-    public Stream<CausewayBeanMetaData> streamIntrospectableTypes() { return introspectableTypes.stream(); }
-    public Stream<Class<?>> streamManagedBeansContributing() { return managedBeansContributing.keySet().stream(); }
-    public Stream<Class<?>> streamEntityTypes() { return entityTypes.keySet().stream(); }
-    public Stream<Class<?>> streamViewmodelTypes() { return viewmodelTypes.keySet().stream(); }
+    public Stream<CausewayBeanMetaData> streamScannedTypes() { return scannedTypes.stream(); }
+    public Stream<Class<?>> streamDomainServices() { return domainServices.keySet().stream(); }
     public Stream<Class<?>> streamMixinTypes() { return mixinTypes.keySet().stream(); }
     public Stream<Class<?>> streamValueTypes() { return valueTypes.keySet().stream(); }
-
-    // -- AS SET
-
-    public Set<Class<?>> entityTypeSet() { return Collections.unmodifiableSet(entityTypes.keySet()); }
-
+    public Stream<Class<?>> streamEntityTypes() { return streamEntityTypes(persistenceStack); }
+    public Stream<Class<?>> streamEntityTypes(@Nullable final PersistenceStack selectedStack) {
+        if(selectedStack==null || !selectedStack.isPresent()) return Stream.empty();
+        return entities.stream()
+                .filter(typeMeta->typeMeta.persistenceStack()==selectedStack)
+                .<Class<?>>map(CausewayBeanMetaData::getCorrespondingClass);
+    }
+    
     // -- LOOKUP
 
-    /**
-     * If given type is part of the meta-model and is available for injection,
-     * returns the <em>Managed Bean's</em> name (id) as
-     * recognized by the IoC container.
-     */
-    public Optional<String> lookupManagedBeanNameForType(final Class<?> type) {
-        return Optional.ofNullable(managedBeansContributing.get(type))
+    public Optional<String> lookupDomainServiceNameForType(final Class<?> type) {
+        return Optional.ofNullable(domainServices.get(type))
                 .map(CausewayBeanMetaData::getBeanName);
     }
 
     public boolean containsManagedBeansContributing(@NonNull final Class<?> type) {
-        return managedBeansContributing.containsKey(type);
+        return domainServices.containsKey(type);
     }
-
-    /**
-     * Returns 'JDO' or 'JPA' based on metadata found during {@link CausewayBeanTypeClassifier type-classification}.
-     * If no (concrete) entity type is found, returns 'UNSPECIFIED'.
-     * @implNote assumes that there can be only one persistence stack
-     */
-    public PersistenceStack determineCurrentPersistenceStack() {
-        return entityTypes.values().stream()
-            .map(CausewayBeanMetaData::persistenceStack)
-            .filter(persistenceStack->!persistenceStack.isNone())
-            .filter(persistenceStack->!persistenceStack.isUnspecified())
-            .findFirst()
-            .orElse(PersistenceStack.UNSPECIFIED);
+    
+    public Optional<CausewayBeanMetaData> lookupScannedType(final Class<?> type) {
+        return Optional.ofNullable(scannedTypesByClass.get(type));
     }
 
-    public Optional<CausewayBeanMetaData> lookupIntrospectableType(final Class<?> type) {
-        return Optional.ofNullable(introspectableTypesByClass.get(type));
+    public Optional<Class<?>> findHomepageViewmodel() {
+        var classCache = _ClassCache.getInstance();
+        return viewmodelTypes.keySet().stream()
+                .filter(viewModelType -> classCache.head(viewModelType).hasAnnotation(HomePage.class))
+                .findFirst();
     }
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/_testing/MetaModelContext_forTesting.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/_testing/MetaModelContext_forTesting.java
index dce69411935..c6e50d9c6ed 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/_testing/MetaModelContext_forTesting.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/_testing/MetaModelContext_forTesting.java
@@ -350,7 +350,7 @@ extends MetaModelContext {
 
     public CausewayBeanTypeRegistry getCausewayBeanTypeRegistry() {
         if(causewayBeanTypeRegistry==null) {
-            causewayBeanTypeRegistry = new CausewayBeanTypeRegistry(Can.empty());
+            causewayBeanTypeRegistry = CausewayBeanTypeRegistry.empty();
         }
         return causewayBeanTypeRegistry;
     }
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/navparent/annotation/NavigableParentAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/navparent/annotation/NavigableParentAnnotationFacetFactory.java
index 4b0f94b66e7..24c9c8728ef 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/navparent/annotation/NavigableParentAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/navparent/annotation/NavigableParentAnnotationFacetFactory.java
@@ -156,7 +156,7 @@ implements MetaModelRefiner {
 
                 ValidationFailure.raiseFormatted(
                         spec,
-                        "%s: conflict for determining a strategy for retrievar of (navigable) parent for class, "
+                        "%s: conflict for determining a strategy for retrieval of (navigable) parent for class, "
                                 + "contains multiple annotations '@%s' having navigable=PARENT, "
                                 + "while at most one is allowed.\n\tConflicting members: %s",
                                 spec.getFeatureIdentifier().getClassName(),
@@ -179,7 +179,7 @@ implements MetaModelRefiner {
 
                     ValidationFailure.raiseFormatted(
                             spec,
-                            "%s: unable to determine a strategy for retrievar of (navigable) parent for class, "
+                            "%s: unable to determine a strategy for retrieval of (navigable) parent for class, "
                                     + "field '%s' annotated with '@%s' having navigable=PARENT does not provide a getter.",
                                     spec.getFeatureIdentifier().getClassName(),
                                     fieldEvaluator.getField().getName(),
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/annotation/TitleAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/annotation/TitleAnnotationFacetFactory.java
index ac0202e6b0a..f4b9bfbc56f 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/annotation/TitleAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/annotation/TitleAnnotationFacetFactory.java
@@ -86,7 +86,7 @@ implements MetaModelRefiner {
 
                 ValidationFailure.raiseFormatted(
                         objectSpec,
-                        "%s: conflict for determining a strategy for retrievar of title for class, "
+                        "%s: conflict for determining a strategy for retrieval of title for class, "
                         + "conflicting title facets %s",
                         objectSpec.getFeatureIdentifier().getClassName(),
                         conflictingFeatures.toString());
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/classsubstitutor/ClassSubstitutorForDomainObjects.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/classsubstitutor/ClassSubstitutorForDomainObjects.java
index d28a4cfce65..0d11067cc31 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/classsubstitutor/ClassSubstitutorForDomainObjects.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/classsubstitutor/ClassSubstitutorForDomainObjects.java
@@ -46,7 +46,7 @@ public class ClassSubstitutorForDomainObjects implements ClassSubstitutor {
 
     @Override
     public Substitution getSubstitution(@NonNull final Class<?> cls) {
-        var notSubstitutable = causewayBeanTypeRegistry.lookupIntrospectableType(cls)
+        var notSubstitutable = causewayBeanTypeRegistry.lookupScannedType(cls)
             .map(CausewayBeanMetaData::beanSort)
             .map(BeanSort::policy)
             .map(BeanPolicy::isNotSubstitutable)
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectFeature.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectFeature.java
index 10d414f9968..d08fc9a8f8d 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectFeature.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectFeature.java
@@ -55,7 +55,7 @@ public interface ObjectFeature extends Specification {
      *
      * @apiNote argument is a {@link Supplier}, because the {@link ManagedObject}
      * is only required when the name is provided imperatively and domain-object
-     * retrievar might be expensive
+     * retrieval might be expensive
      *
      * @see #getFeatureIdentifier()
      */
@@ -103,7 +103,7 @@ public interface ObjectFeature extends Specification {
      *
      * @apiNote argument is a {@link Supplier}, because the {@link ManagedObject}
      * is only required when the description is provided imperatively and domain-object
-     * retrievar might be expensive
+     * retrieval might be expensive
      *
      */
     Optional<String> getDescription(final Supplier<ManagedObject> domainObjectProvider);
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationLoaderDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationLoaderDefault.java
index 94e4eaa1875..4b0958c72c9 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationLoaderDefault.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationLoaderDefault.java
@@ -18,8 +18,10 @@
  */
 package org.apache.causeway.core.metamodel.specloader;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -53,9 +55,8 @@ import org.apache.causeway.commons.collections.Can;
 import org.apache.causeway.commons.internal.assertions._Assert;
 import org.apache.causeway.commons.internal.base._Blackhole;
 import org.apache.causeway.commons.internal.base._Lazy;
+import org.apache.causeway.commons.internal.base._NullSafe;
 import org.apache.causeway.commons.internal.base._Timing;
-import org.apache.causeway.commons.internal.collections._Lists;
-import org.apache.causeway.commons.internal.collections._Maps;
 import org.apache.causeway.commons.internal.exceptions._Exceptions;
 import org.apache.causeway.core.config.CausewayConfiguration;
 import org.apache.causeway.core.config.beans.CausewayBeanMetaData;
@@ -221,6 +222,37 @@ implements
         this.facetProcessor = new FacetProcessor(programmingModel, metaModelContext);
     }
 
+    record SpecCollector(
+            List<ObjectSpecification> knownSpecs,
+            Map<Class<?>, ObjectSpecification> valueSpecs,
+            List<ObjectSpecification> domainServiceSpecs,
+            List<ObjectSpecification> mixinSpecs,
+            List<ObjectSpecification> entitySpecs,
+            List<ObjectSpecification> viewmodelSpecs,
+            List<ObjectSpecification> otherSpecs) {
+
+        SpecCollector() {
+            this(new ArrayList<>(),
+                    new HashMap<>(),
+                    new ArrayList<>(), new ArrayList<>(), new ArrayList<>(),
+                    new ArrayList<>(), new ArrayList<>());
+        }
+
+        public void collect(@Nullable final ObjectSpecification spec) {
+            if(spec==null) return; // might be vetoed
+            knownSpecs.add(spec);
+            switch (spec.getBeanSort()) {
+                case VALUE -> valueSpecs.put(spec.getCorrespondingClass(), spec);
+                case MANAGED_BEAN_CONTRIBUTING -> domainServiceSpecs.add(spec);
+                case MIXIN -> mixinSpecs.add(spec);
+                case ENTITY -> entitySpecs.add(spec);
+                case VIEW_MODEL -> viewmodelSpecs.add(spec);
+                case PROGRAMMATIC, UNKNOWN, COLLECTION, ABSTRACT -> otherSpecs.add(spec);
+                case VETOED, MANAGED_BEAN_NOT_CONTRIBUTING -> {}
+            }
+        }
+    }
+
     /**
      * Initializes and wires up, and primes the cache based on any service
      * classes (provided by the {@link CausewayBeanTypeRegistry}).
@@ -229,94 +261,45 @@ implements
     public void createMetaModel() {
 
         log.info("About to create the Metamodel ...");
+        var stopWatch = _Timing.now();
 
         // initialize subcomponents, only after @PostConstruct has globally completed
         facetProcessor.init();
         postProcessor.init();
 
-        var knownSpecs = _Lists.<ObjectSpecification>newArrayList();
-
-        var stopWatch = _Timing.now();
+        var specs = new SpecCollector();
 
         // preload otherwise not eagerly discovered classes
         var prealoadCount = preloadableTypes.stream()
             .flatMap(PreloadableTypes::stream)
-            .peek(this::loadSpecification)
+            .map(this::loadSpecification)
+            .filter(_NullSafe::isPresent)
             .count();
-
         log.info(" - preloaded {} otherwise not eagerly discovered types", prealoadCount);
 
-        log.info(" - adding value types from from class-path scan and ValueTypeProviders");
-
-        var valueTypeSpecs = _Maps.<Class<?>, ObjectSpecification>newHashMap();
-
+        var valueTypesFromProviders = valueSemanticsResolver.get().streamClassesWithValueSemantics()
+            .map(valueClass->CausewayBeanMetaData.value(LogicalType.infer(valueClass), DiscoveredBy.CAUSEWAY_UPFRONT))
+            .toList();
+        log.info(" - found {} value types via ValueTypeProviders", valueTypesFromProviders.size());
+        
         Stream
             .concat(
-                causewayBeanTypeRegistry.streamValueTypes(),
-                valueSemanticsResolver.get().streamClassesWithValueSemantics())
-            .forEach(valueClass -> {
-                var valueSpec = loadSpecification(valueClass, IntrospectionState.NOT_INTROSPECTED);
-                if(valueSpec!=null) {
-                    knownSpecs.add(valueSpec);
-                    valueTypeSpecs.put(valueClass, valueSpec);
-                }
-            });
-
-        log.info(" - categorizing types from class-path scan");
-
-        var domainObjectSpecs = _Lists.<ObjectSpecification>newArrayList();
-        var mixinSpecs = _Lists.<ObjectSpecification>newArrayList();
-
-        causewayBeanTypeRegistry.streamIntrospectableTypes()
-        .forEach(typeMeta->{
-
-            var spec = primeSpecification(typeMeta);
-            if(spec==null) {
-                //XXX only ever happens when the class substitutor vetoes
-                return;
-            }
-
-            knownSpecs.add(spec);
-
-            var sort = typeMeta.beanSort();
-
-            if(sort.isManagedBeanAny() || sort.isEntity() || sort.isViewModel() ) {
-                domainObjectSpecs.add(spec);
-            } else if(sort.isMixin()) {
-                mixinSpecs.add(spec);
-            }
-
-        });
-
-        //XXX[CAUSEWAY-2382] when parallel introspecting, make sure we have the mixins before their holders
-        // (observation by experiment, no real understanding as to why)
-
-        _LogUtil.logBefore(log, this::snapshotSpecifications, knownSpecs);
-
-        log.info(" - introspecting {} type hierarchies", knownSpecs.size());
-        introspect(Can.ofCollection(knownSpecs), IntrospectionState.TYPE_INTROSPECTED);
-
-        log.info(" - introspecting {} value types", valueTypeSpecs.size());
-        introspect(Can.ofCollection(valueTypeSpecs.values()), IntrospectionState.FULLY_INTROSPECTED);
-
-        log.info(" - introspecting {} mixins", causewayBeanTypeRegistry.mixinTypeCount());
-        introspect(Can.ofCollection(mixinSpecs), IntrospectionState.FULLY_INTROSPECTED);
-
-        log.info(" - introspecting {} managed beans contributing (domain services)",
-                causewayBeanTypeRegistry.managedBeansContributingCount());
-
-        log.info(" - introspecting {} entities ({})",
-                causewayBeanTypeRegistry.entityTypeCount(),
-                causewayBeanTypeRegistry.determineCurrentPersistenceStack().name());
-
-        log.info(" - introspecting {} view models", causewayBeanTypeRegistry.viewmodelTypeCount());
+                valueTypesFromProviders.stream(),
+                causewayBeanTypeRegistry.streamScannedTypes())
+            // prime (up to NOT_INTROSPECTED)
+            .map(this::primeSpecification)
+            .forEach(specs::collect);
+
+        introspectAndLog("type hierarchies", specs.knownSpecs, IntrospectionState.TYPE_INTROSPECTED);
+        introspectAndLog("value types", specs.valueSpecs.values(), IntrospectionState.FULLY_INTROSPECTED);
+        introspectAndLog("mixins", specs.mixinSpecs, IntrospectionState.FULLY_INTROSPECTED);
+        introspectAndLog("domain services", specs.domainServiceSpecs, IntrospectionState.FULLY_INTROSPECTED);
+        introspectAndLog("entities (%s)".formatted(causewayBeanTypeRegistry.persistenceStack().name()),
+                specs.entitySpecs(), IntrospectionState.FULLY_INTROSPECTED);
+        introspectAndLog("view models", specs.viewmodelSpecs(), IntrospectionState.FULLY_INTROSPECTED);
 
         serviceRegistry.lookupServiceElseFail(MenuBarsService.class).menuBars();
 
-        introspect(Can.ofCollection(domainObjectSpecs), IntrospectionState.FULLY_INTROSPECTED);
-
-        _LogUtil.logAfter(log, this::snapshotSpecifications, knownSpecs);
-
         if(isFullIntrospect()) {
             var snapshot = snapshotSpecifications();
             log.info(" - introspecting all {} types eagerly (FullIntrospect=true)", snapshot.size());
@@ -412,7 +395,7 @@ implements
     public ObjectSpecification loadSpecification(
             final @Nullable Class<?> type,
             final @NonNull IntrospectionState upTo) {
-        return _loadSpecification(type, this::classify, upTo);
+        return loadSpecificationNullable(type, this::classify, upTo);
     }
 
     @Override
@@ -511,8 +494,8 @@ implements
     public void addValidationFailure(final ValidationFailure validationFailure) {
 //        if(validationResult.isMemoized()) {
 //            validationResult.clear(); // invalidate
-////            throw _Exceptions.illegalState(
-////                    "Validation result was already created and can no longer be modified.");
+//            throw _Exceptions.illegalState(
+//                    "Validation result was already created and can no longer be modified.");
 //        }
         synchronized(validationFailures) {
             validationFailures.add(validationFailure);
@@ -553,25 +536,42 @@ implements
      * here.
      */
     private CausewayBeanMetaData classify(final @Nullable Class<?> type) {
-        return causewayBeanTypeRegistry
-                .lookupIntrospectableType(type)
+
+        var discoveredBy = isMetamodelFullyIntrospected()
+                ? DiscoveredBy.CAUSEWAY_ONTHEFLY
+                : DiscoveredBy.CAUSEWAY_UPFRONT;
+
+        var typeMeta = causewayBeanTypeRegistry
+                .lookupScannedType(type)
                 .orElseGet(()->
                     valueSemanticsResolver.get().hasValueSemantics(type)
-                        ? CausewayBeanMetaData.value(LogicalType.infer(type), DiscoveredBy.CAUSEWAY)
-                        : causewayBeanTypeClassifier.classify(LogicalType.infer(type), DiscoveredBy.CAUSEWAY)
+                        ? CausewayBeanMetaData.value(LogicalType.infer(type), discoveredBy)
+                        : causewayBeanTypeClassifier.classify(LogicalType.infer(type), discoveredBy)
                 );
+
+        if(isMetamodelFullyIntrospected()) {
+            var warningMessage = ProgrammingModelConstants.MessageTemplate.TYPE_NOT_EAGERLY_DISCOVERED
+                    .builder()
+                    .addVariable("type", type.getName())
+                    .addVariable("beanSort", typeMeta.beanSort().name())
+                    .buildMessage();
+
+            log.warn(warningMessage);
+        }
+
+        return typeMeta;
     }
 
     @Nullable
     private ObjectSpecification primeSpecification(
             final @NonNull CausewayBeanMetaData typeMeta) {
-        return _loadSpecification(
+        return loadSpecificationNullable(
                 typeMeta.getCorrespondingClass(), type->typeMeta, IntrospectionState.NOT_INTROSPECTED);
 
     }
 
     @Nullable
-    private ObjectSpecification _loadSpecification(
+    private ObjectSpecification loadSpecificationNullable(
             final @Nullable Class<?> type,
             final @NonNull Function<Class<?>, CausewayBeanMetaData> beanClassifier,
             final @NonNull IntrospectionState upTo) {
@@ -581,9 +581,7 @@ implements
         }
 
         var substitute = classSubstitutorRegistry.getSubstitution(type);
-        if (substitute.isNeverIntrospect()) {
-            return null; // never inspect
-        }
+        if (substitute.isNeverIntrospect()) return null; // never inspect
 
         var substitutedType = substitute.apply(type);
 
@@ -613,39 +611,16 @@ implements
         return spec;
     }
 
-    private void guardAgainstMetamodelLockedAfterFullIntrospection(final Class<?> cls) {
-        if(isMetamodelFullyIntrospected()
-                && causewayConfiguration.getCore().getMetaModel().getIntrospector().isLockAfterFullIntrospection()) {
-
-            var warningMessage = ProgrammingModelConstants.MessageTemplate.TYPE_NOT_EAGERLY_DISCOVERED
-                    .builder()
-                    .addVariable("type", cls.getName())
-                    .addVariable("beanSort", causewayBeanTypeClassifier
-                            .classify(LogicalType.infer(cls), DiscoveredBy.CAUSEWAY)
-                            .beanSort()
-                            .name())
-                    .buildMessage();
-
-            log.warn(warningMessage);
-        }
-    }
-
     /**
      * Creates the appropriate type of {@link ObjectSpecification}.
      */
     private ObjectSpecification createSpecification(final CausewayBeanMetaData typeMeta) {
-
-        guardAgainstMetamodelLockedAfterFullIntrospection(typeMeta.getCorrespondingClass());
-
-        // ... and create the specs
-
         var objectSpec = new ObjectSpecificationDefault(
                         typeMeta,
                         metaModelContext,
                         facetProcessor,
                         postProcessor,
                         classSubstitutorRegistry);
-
         return objectSpec;
     }
 
@@ -671,6 +646,16 @@ implements
         });
     }
 
+    private void introspectAndLog(
+            final String info,
+            final Iterable<ObjectSpecification> specs,
+            final IntrospectionState upTo) {
+        var stopWatch = _Timing.now();
+        introspect(Can.ofIterable(specs), upTo);
+        stopWatch.stop();
+        log.info(" - introspecting {} {} took {}ms", _NullSafe.sizeAutodetect(specs), info, stopWatch.getMillis());
+    }
+
     private void introspect(
             final Can<ObjectSpecification> specs,
             final IntrospectionState upTo) {
diff --git a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/homepage/HomePageResolverServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/homepage/HomePageResolverServiceDefault.java
index 7b6e0ab51bc..312caffa1bc 100644
--- a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/homepage/HomePageResolverServiceDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/homepage/HomePageResolverServiceDefault.java
@@ -67,14 +67,11 @@ public class HomePageResolverServiceDefault implements HomePageResolverService {
 
     @PostConstruct
     public void init() {
-        viewModelTypeForHomepage = causewayBeanTypeRegistry.streamViewmodelTypes()
-                .filter(viewModelType -> _Annotations.isPresent(viewModelType, HomePage.class))
-                .findFirst();
+        viewModelTypeForHomepage = causewayBeanTypeRegistry.findHomepageViewmodel();
     }
 
     @Override
     public Object getHomePage() {
-
         return viewModelTypeForHomepage
                 .map(ClassExtensions::newInstance)
                 .map(factoryService::viewModel)
diff --git a/extensions/core/commandlog/applib/src/test/java/org/apache/causeway/extensions/commandlog/applib/integtest/CommandLog_IntegTestAbstract.java b/extensions/core/commandlog/applib/src/test/java/org/apache/causeway/extensions/commandlog/applib/integtest/CommandLog_IntegTestAbstract.java
index 39ac348bea9..bb6f842a2fe 100644
--- a/extensions/core/commandlog/applib/src/test/java/org/apache/causeway/extensions/commandlog/applib/integtest/CommandLog_IntegTestAbstract.java
+++ b/extensions/core/commandlog/applib/src/test/java/org/apache/causeway/extensions/commandlog/applib/integtest/CommandLog_IntegTestAbstract.java
@@ -244,7 +244,7 @@ public abstract class CommandLog_IntegTestAbstract extends CausewayIntegrationTe
         assertThat(cleBookmarkIfAny).isPresent();
         Bookmark cleBookmark = cleBookmarkIfAny.get();
         String identifier = cleBookmark.getIdentifier();
-        if (causewayBeanTypeRegistry.determineCurrentPersistenceStack().isJdo()) {
+        if (causewayBeanTypeRegistry.persistenceStack().isJdo()) {
             assertThat(identifier).startsWith("u_");
             UUID.fromString(identifier.substring("u_".length())); // should not fail, ie check the format is as we expect
         } else {
@@ -365,7 +365,7 @@ public abstract class CommandLog_IntegTestAbstract extends CausewayIntegrationTe
         // then
         Assertions.assertThat(notYetReplayed).isEmpty();
 
-        if (causewayBeanTypeRegistry.determineCurrentPersistenceStack().isJdo()) {
+        if (causewayBeanTypeRegistry.persistenceStack().isJdo()) {
 
             // fails in JPA; possibly need to get the agent working for dirty tracking.
 
@@ -447,7 +447,7 @@ public abstract class CommandLog_IntegTestAbstract extends CausewayIntegrationTe
         // then
         Assertions.assertThat(mostRecentReplayedIfAny).isEmpty();
 
-        if (causewayBeanTypeRegistry.determineCurrentPersistenceStack().isJdo()) {
+        if (causewayBeanTypeRegistry.persistenceStack().isJdo()) {
 
             // fails in JPA; possibly need to get the agent working for dirty tracking.
 
diff --git a/extensions/security/secman/applib/src/main/java/org/apache/causeway/extensions/secman/applib/seed/scripts/SeedUsersAndRolesFixtureScript.java b/extensions/security/secman/applib/src/main/java/org/apache/causeway/extensions/secman/applib/seed/scripts/SeedUsersAndRolesFixtureScript.java
index 7ac7527c7cb..743b815a531 100644
--- a/extensions/security/secman/applib/src/main/java/org/apache/causeway/extensions/secman/applib/seed/scripts/SeedUsersAndRolesFixtureScript.java
+++ b/extensions/security/secman/applib/src/main/java/org/apache/causeway/extensions/secman/applib/seed/scripts/SeedUsersAndRolesFixtureScript.java
@@ -85,7 +85,7 @@ public class SeedUsersAndRolesFixtureScript extends FixtureScript {
     protected void execute(final ExecutionContext executionContext) {
 
         var secmanConfig = config.getExtensions().getSecman();
-        var persistenceStack = causewayBeanTypeRegistry.determineCurrentPersistenceStack();
+        var persistenceStack = causewayBeanTypeRegistry.persistenceStack();
 
         // used as log message provider below - assuming file was found and is readable
         final Supplier<String> yamlFilePath = ()->new File(secmanConfig.getSeed().getYamlFile()).getAbsolutePath();
diff --git a/extensions/vw/tabular/applib/src/main/java/org/apache/causeway/tabular/applib/DataTableProvider.java b/extensions/vw/tabular/applib/src/main/java/org/apache/causeway/tabular/applib/DataTableProvider.java
index a4af509ff4c..ef6d10ac57a 100644
--- a/extensions/vw/tabular/applib/src/main/java/org/apache/causeway/tabular/applib/DataTableProvider.java
+++ b/extensions/vw/tabular/applib/src/main/java/org/apache/causeway/tabular/applib/DataTableProvider.java
@@ -59,7 +59,7 @@ public abstract class DataTableProvider {
     }
 
     public Stream<Class<?>> streamEntityClasses() {
-        return beanTypeRegistry.streamEntityTypes()
+        return beanTypeRegistry.streamEntityTypes(beanTypeRegistry.persistenceStack())
             //TODO perhaps externalize sorting
             .sorted((a, b)->a.getSimpleName().compareTo(b.getSimpleName()));
     }
diff --git a/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/CausewayModulePersistenceJdoDatanucleus.java b/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/CausewayModulePersistenceJdoDatanucleus.java
index f9b14acb50c..8fa1069d1ed 100644
--- a/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/CausewayModulePersistenceJdoDatanucleus.java
+++ b/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/CausewayModulePersistenceJdoDatanucleus.java
@@ -20,6 +20,7 @@ package org.apache.causeway.persistence.jdo.datanucleus;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import javax.jdo.JDOException;
 import javax.jdo.PersistenceManagerFactory;
@@ -40,6 +41,7 @@ import org.springframework.transaction.interceptor.TransactionInterceptor;
 import org.apache.causeway.commons.internal.assertions._Assert;
 import org.apache.causeway.commons.internal.base._NullSafe;
 import org.apache.causeway.core.config.CausewayConfiguration;
+import org.apache.causeway.core.config.beans.CausewayBeanMetaData.PersistenceStack;
 import org.apache.causeway.core.config.beans.CausewayBeanTypeRegistry;
 import org.apache.causeway.core.config.beans.aoppatch.TransactionInterceptorFactory;
 import org.apache.causeway.core.metamodel.context.MetaModelContext;
@@ -247,8 +249,9 @@ public class CausewayModulePersistenceJdoDatanucleus {
 
         if(_NullSafe.isEmpty(jdoEntityDiscoveryListeners)) return;
         // assuming, as we instantiate a DN PMF, all entities discovered are JDO entities
-        if(beanTypeRegistry.entityTypeCount()==0) return;
-        var jdoEntityTypes = beanTypeRegistry.entityTypeSet();
+        if(!beanTypeRegistry.persistenceStack().isJdo()) return;
+        var jdoEntityTypes = beanTypeRegistry.streamEntityTypes(PersistenceStack.JDO)
+                .collect(Collectors.toSet());
         var dnProps = Collections.unmodifiableMap(dnSettings.getAsProperties());
         jdoEntityDiscoveryListeners
             .forEach(listener->
@@ -295,9 +298,9 @@ public class CausewayModulePersistenceJdoDatanucleus {
         var pumd = new PersistenceUnitMetaData(
                 "dynamic-unit", "RESOURCE_LOCAL", null);
         pumd.setExcludeUnlistedClasses(false);
-        beanTypeRegistry.streamEntityTypes()
-        .map(Class::getName)
-        .forEach(pumd::addClassName);
+        beanTypeRegistry.streamEntityTypes(PersistenceStack.JDO)
+            .map(Class::getName)
+            .forEach(pumd::addClassName);
         return pumd;
     }
 
diff --git a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/publishing/subscriber/EntityPropertyChangeSubscriberForTesting.java b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/publishing/subscriber/EntityPropertyChangeSubscriberForTesting.java
index ecc53c08bbd..5e8a6af4f7b 100644
--- a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/publishing/subscriber/EntityPropertyChangeSubscriberForTesting.java
+++ b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/publishing/subscriber/EntityPropertyChangeSubscriberForTesting.java
@@ -60,7 +60,7 @@ implements EntityPropertyChangeSubscriber {
     @Override
     public void onChanging(final EntityPropertyChange entityPropertyChange) {
 
-        PersistenceStack persistenceStack = causewayBeanTypeRegistry.determineCurrentPersistenceStack();
+        PersistenceStack persistenceStack = causewayBeanTypeRegistry.persistenceStack();
 
         var target = entityPropertyChange.getTarget();
         var targetLogicalTypeName = target.getLogicalTypeName();
diff --git a/regressiontests/bootstrapping/src/test/java/org/apache/causeway/testdomain/bootstrapping/AutoConfigurationTest.java b/regressiontests/bootstrapping/src/test/java/org/apache/causeway/testdomain/bootstrapping/AutoConfigurationTest.java
index aff46949dab..a2891f9301b 100644
--- a/regressiontests/bootstrapping/src/test/java/org/apache/causeway/testdomain/bootstrapping/AutoConfigurationTest.java
+++ b/regressiontests/bootstrapping/src/test/java/org/apache/causeway/testdomain/bootstrapping/AutoConfigurationTest.java
@@ -97,7 +97,7 @@ class AutoConfigurationTest {
     @Test
     void domainObjects_shouldBeDiscovered() {
         for(var cls : nonManaged()) {
-            var type = causewayBeanTypeRegistry.lookupIntrospectableType(cls);
+            var type = causewayBeanTypeRegistry.lookupScannedType(cls);
             assertTrue(type.isPresent());
         }
     }
diff --git a/regressiontests/cmdexecauditsess/generic/src/main/java/org/apache/causeway/regressiontests/cmdexecauditsess/generic/integtest/CmdExecAuditSessLog_IntegTestAbstract.java b/regressiontests/cmdexecauditsess/generic/src/main/java/org/apache/causeway/regressiontests/cmdexecauditsess/generic/integtest/CmdExecAuditSessLog_IntegTestAbstract.java
index ef97dd2b8fe..3b24b9bc08f 100644
--- a/regressiontests/cmdexecauditsess/generic/src/main/java/org/apache/causeway/regressiontests/cmdexecauditsess/generic/integtest/CmdExecAuditSessLog_IntegTestAbstract.java
+++ b/regressiontests/cmdexecauditsess/generic/src/main/java/org/apache/causeway/regressiontests/cmdexecauditsess/generic/integtest/CmdExecAuditSessLog_IntegTestAbstract.java
@@ -336,7 +336,7 @@ public abstract class CmdExecAuditSessLog_IntegTestAbstract extends CausewayInte
     }
 
     boolean isJpa() {
-        return causewayBeanTypeRegistry.determineCurrentPersistenceStack().isJpa();
+        return causewayBeanTypeRegistry.persistenceStack().isJpa();
     }
 
     @Inject AuditTrailEntryRepository auditTrailEntryRepository;
diff --git a/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingBadDomain.java b/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingBadDomain.java
index d9dcedb1a8c..c705c324c21 100644
--- a/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingBadDomain.java
+++ b/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingBadDomain.java
@@ -118,7 +118,7 @@ class DomainModelTest_usingBadDomain {
     void ambiguousTitle_shouldFail() {
         validator.assertAnyFailuresContaining(
                 Identifier.classIdentifier(LogicalType.fqcn(AmbiguousTitle.class)),
-                "conflict for determining a strategy for retrievar of title");
+                "conflict for determining a strategy for retrieval of title");
     }
 
     @Test