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/causeway.git
The following commit(s) were added to refs/heads/master by this push:
new 135526f23e CAUSEWAY-3687: adds MM validation when UI contributing
proxy is detected
135526f23e is described below
commit 135526f23e708cab7f1f301808d2850fd1e4a08d
Author: Andi Huber <[email protected]>
AuthorDate: Tue Feb 27 19:37:40 2024 +0100
CAUSEWAY-3687: adds MM validation when UI contributing proxy is detected
---
.../org/apache/causeway/applib/id/LogicalType.java | 4 ++
.../progmodel/ProgrammingModelConstants.java | 4 ++
.../DomainObjectAnnotationFacetFactory.java | 48 ++++++++++++++++++----
.../services/registry/ServiceRegistryDefault.java | 17 +++++---
4 files changed, 59 insertions(+), 14 deletions(-)
diff --git
a/api/applib/src/main/java/org/apache/causeway/applib/id/LogicalType.java
b/api/applib/src/main/java/org/apache/causeway/applib/id/LogicalType.java
index 67faa63f6d..590deb7d67 100644
--- a/api/applib/src/main/java/org/apache/causeway/applib/id/LogicalType.java
+++ b/api/applib/src/main/java/org/apache/causeway/applib/id/LogicalType.java
@@ -155,6 +155,8 @@ implements
final @NonNull Class<?> correspondingClass,
final @NonNull Supplier<String> logicalNameProvider) {
+ //[CAUSEWAY-3687] would allow CGLIB proxies to be added, but we
decided to not allow this for UI contributing beans
+ //this.correspondingClass =
ClassUtils.getUserClass(correspondingClass);
this.correspondingClass = correspondingClass;
this.logicalNameProvider = logicalNameProvider;
}
@@ -163,6 +165,8 @@ implements
final @NonNull Class<?> correspondingClass,
final String logicalName) {
+ //[CAUSEWAY-3687] would allow CGLIB proxies to be added, but we
decided to not allow this for UI contributing beans
+ //this.correspondingClass =
ClassUtils.getUserClass(correspondingClass);
this.correspondingClass = correspondingClass;
this.logicalName = requireNonEmpty(logicalName);
this.logicalNameProvider = null;
diff --git
a/core/config/src/main/java/org/apache/causeway/core/config/progmodel/ProgrammingModelConstants.java
b/core/config/src/main/java/org/apache/causeway/core/config/progmodel/ProgrammingModelConstants.java
index 0153c06cae..4d5efd7ac3 100644
---
a/core/config/src/main/java/org/apache/causeway/core/config/progmodel/ProgrammingModelConstants.java
+++
b/core/config/src/main/java/org/apache/causeway/core/config/progmodel/ProgrammingModelConstants.java
@@ -463,6 +463,10 @@ public final class ProgrammingModelConstants {
NON_UNIQUE_LOGICAL_TYPE_NAME_OR_ALIAS("Logical type name (or alias)
${logicalTypeName} "
+ "mapped to multiple non-abstract classes:\n"
+ "${csv}"),
+ PROXIED_SERVICE_BEAN_NOT_ALLOWED_TO_CONTRIBUTE_TO_UI("Logical type
name (or alias) ${logicalTypeName} "
+ + "mapped to at least one proxied class:\n"
+ + "${csv}. Proxied service beans are not allowed to contribute
to the UI. "
+ + "E.g. don't mix @Transactional with
@DomainService(nature=VIEW)"),
UNKNONW_SORT_WITH_ACTION("${type}: is a (concrete) but UNKNOWN sort,
yet has ${actionCount} actions: ${actions}"),
ACTION_METHOD_OVERLOADING_NOT_ALLOWED("Action method overloading is
not allowed, "
+ "yet ${type} has action(s) that have a the same member name:
${overloadedNames}"),
diff --git
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java
index 3fbe85e74a..19a7d102e1 100644
---
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java
+++
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java
@@ -26,6 +26,9 @@ import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Named;
+import org.springframework.lang.Nullable;
+import org.springframework.util.ClassUtils;
+
import org.apache.causeway.applib.Identifier;
import org.apache.causeway.applib.annotation.Action;
import org.apache.causeway.applib.annotation.Collection;
@@ -41,6 +44,7 @@ import
org.apache.causeway.applib.events.lifecycle.ObjectRemovingEvent;
import org.apache.causeway.applib.events.lifecycle.ObjectUpdatedEvent;
import org.apache.causeway.applib.events.lifecycle.ObjectUpdatingEvent;
import org.apache.causeway.applib.id.LogicalType;
+import org.apache.causeway.commons.collections.Can;
import org.apache.causeway.commons.internal.collections._Multimaps;
import
org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod;
import org.apache.causeway.core.config.progmodel.ProgrammingModelConstants;
@@ -78,6 +82,7 @@ import
org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure
import static org.apache.causeway.commons.internal.base._NullSafe.stream;
+import lombok.NonNull;
import lombok.val;
import lombok.extern.log4j.Log4j2;
@@ -587,17 +592,35 @@ implements
specsByLogicalTypeName.forEach((logicalTypeName,
collidingSpecs)->{
if(isObjectTypeCollision(collidingSpecs)) {
- val csv = asCsv(collidingSpecs);
- collidingSpecs.stream()
-
.filter(this::logicalTypeNameIsNotIncludedInAliased)
- .forEach(spec->{
- ValidationFailure.raiseFormatted(spec,
+
+ // assuming, a check for proxies is only required
when there is also a bean name collision
+ // where the plain class and the proxied class
collide having the same logical-type-name
+ val proxies = proxiesIn(collidingSpecs);
+ if(proxies.isNotEmpty()) {
+
+ proxies.forEach(spec->{
+ ValidationFailure.raiseFormatted(spec,
+
ProgrammingModelConstants.Violation.PROXIED_SERVICE_BEAN_NOT_ALLOWED_TO_CONTRIBUTE_TO_UI
+ .builder()
+ .addVariable("logicalTypeName",
spec.getLogicalTypeName())
+ .addVariable("csv",
asCsv(proxies.toList()))
+ .buildMessage());
+ });
+
+ } else {
+
+ collidingSpecs.stream()
+
.filter(this::logicalTypeNameIsNotIncludedInAliased)
+ .forEach(spec->{
+ ValidationFailure.raiseFormatted(spec,
ProgrammingModelConstants.Violation.NON_UNIQUE_LOGICAL_TYPE_NAME_OR_ALIAS
.builder()
.addVariable("logicalTypeName",
spec.getLogicalTypeName())
- .addVariable("csv", csv)
+ .addVariable("csv",
asCsv(collidingSpecs))
.buildMessage());
- });
+ });
+
+ }
}
});
@@ -605,7 +628,16 @@ implements
specsByLogicalTypeName.clear();
}
- private boolean
logicalTypeNameIsNotIncludedInAliased(ObjectSpecification objectSpecification) {
+ private boolean isProxy(final @NonNull ObjectSpecification
spec) {
+ val cls = spec.getCorrespondingClass();
+ return !ClassUtils.getUserClass(cls).equals(cls);
+ }
+
+ private Can<ObjectSpecification> proxiesIn(final @Nullable
List<ObjectSpecification> specs) {
+ return
stream(specs).filter(this::isProxy).collect(Can.toCan());
+ }
+
+ private boolean logicalTypeNameIsNotIncludedInAliased(final
ObjectSpecification objectSpecification) {
if
(getConfiguration().getCore().getMetaModel().getValidator().isAllowLogicalTypeNameAsAlias())
{
return objectSpecification.getAliases()
.map(LogicalType::getLogicalTypeName).stream()
diff --git
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/registry/ServiceRegistryDefault.java
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/registry/ServiceRegistryDefault.java
index e7a1fff85b..7ba8e1ab31 100644
---
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/registry/ServiceRegistryDefault.java
+++
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/registry/ServiceRegistryDefault.java
@@ -21,6 +21,7 @@ package org.apache.causeway.core.metamodel.services.registry;
import java.lang.annotation.Annotation;
import java.util.Map;
import java.util.Optional;
+import java.util.function.Predicate;
import java.util.stream.Stream;
import javax.annotation.Priority;
@@ -35,7 +36,6 @@ import org.apache.causeway.applib.id.LogicalType;
import org.apache.causeway.applib.services.registry.ServiceRegistry;
import org.apache.causeway.commons.collections.Can;
import org.apache.causeway.commons.internal.base._Lazy;
-import org.apache.causeway.commons.internal.base._NullSafe;
import org.apache.causeway.commons.internal.collections._Maps;
import org.apache.causeway.commons.internal.ioc._SingletonBeanProvider;
import org.apache.causeway.core.config.beans.CausewayBeanTypeRegistry;
@@ -88,16 +88,21 @@ public final class ServiceRegistryDefault implements
ServiceRegistry {
private Map<String, _SingletonBeanProvider>
enumerateContributingDomainServices() {
val managedBeanAdapterByName = _Maps.<String,
_SingletonBeanProvider>newHashMap();
- val managedBeansContributing =
causewayBeanTypeRegistry.getManagedBeansContributing().keySet();
causewaySystemEnvironment.getIocContainer()
.streamAllBeans()
- .filter(_NullSafe::isPresent)
- .filter(bean->managedBeansContributing.contains(bean.getBeanClass()))
// do not register unknown sort
- .forEach(bean->
- managedBeanAdapterByName.put(bean.getId(), bean));
+ .filter(contributes())
+ .forEach(singletonProvider->
+ managedBeanAdapterByName.put(singletonProvider.getId(),
singletonProvider));
return managedBeanAdapterByName;
}
+ private Predicate<_SingletonBeanProvider> contributes() {
+ var managedBeansContributing =
causewayBeanTypeRegistry.getManagedBeansContributing().keySet();
+ return singletonProvider->singletonProvider!=null
+ ?
managedBeansContributing.contains(singletonProvider.getBeanClass()) // do not
register unknown sort
+ : false;
+ }
+
}