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
commit 5e0854443e737d54ed448b39252cbd007a9bb126 Author: andi-huber <[email protected]> AuthorDate: Sun Feb 4 18:14:14 2024 +0100 CAUSEWAY-3404: improved error message on action returning non-bookmarkable object --- .../core/config/progmodel/ProgrammingModelConstants.java | 11 +++++++++++ .../executor/MemberExecutorServiceDefault.java | 13 +++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) 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 f5601fc23a..0153c06cae 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 @@ -466,6 +466,14 @@ public final class ProgrammingModelConstants { 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}"), + ACTION_METHOD_RETURNING_TRANSIENT_ENTITY_NOT_ALLOWED("Action methods are not allowed to return transient entities, " + + "yet ${type} has action ${memberId}, which did return a transient entity of type ${returnTypeSpec}. " + + "To correct this issue either persist the entity within above method before returning it, " + + "or don't have the method invocation managed by the framework, e.g. " + + "mark the method @Programmatic."), + ACTION_METHOD_RETURNING_NON_BOOKMARKABLE_OBJECT_NOT_ALLOWED("Action methods are not allowed to return objects, " + + "for which no bookmark can be created, " + + "yet ${type} has action ${memberId}, which did return such an object of type ${returnTypeSpec}."), PARAMETER_HAS_NO_CHOICES_NOR_AUTOCOMPLETE("${paramId} has no choices nor autoComplete, " + "yet represents a domain-object or is a plural."), PARAMETER_TUPLE_INVALID_USE_OF_ANNOTATION("${type}#${member}: " @@ -509,6 +517,9 @@ public final class ProgrammingModelConstants { vars.put(name, ""+value); return this; } + /** + * Populates 'type' and 'member' keys (for template variable resolution). + */ public ViolationBuilder addVariablesFor(final Identifier featureIdentifier) { addVariable("type", featureIdentifier.getLogicalType().getClassName()); addVariable("member", featureIdentifier.getMemberLogicalName()); diff --git a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/executor/MemberExecutorServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/executor/MemberExecutorServiceDefault.java index 9604353aeb..dadf8c71de 100644 --- a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/executor/MemberExecutorServiceDefault.java +++ b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/executor/MemberExecutorServiceDefault.java @@ -44,6 +44,7 @@ import org.apache.causeway.commons.internal.assertions._Assert; import org.apache.causeway.commons.internal.collections._Lists; import org.apache.causeway.commons.internal.reflection._MethodFacades.MethodFacade; import org.apache.causeway.core.config.CausewayConfiguration; +import org.apache.causeway.core.config.progmodel.ProgrammingModelConstants.Violation; import org.apache.causeway.core.metamodel.commons.CanonicalInvoker; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.execution.ActionExecutor; @@ -184,8 +185,16 @@ implements MemberExecutorService { return true; }) .ifPresent(scalarNonEmpty->{ - _Assert.assertTrue(scalarNonEmpty.getBookmark().isPresent(), ()->String.format( - "bookmark required for non-empty scalars %s", scalarNonEmpty.getSpecification())); + _Assert.assertTrue(scalarNonEmpty.getBookmark().isPresent(), ()->{ + var returnTypeSpec = scalarNonEmpty.getSpecification(); + var violation = returnTypeSpec.isEntity() + ? Violation.ACTION_METHOD_RETURNING_TRANSIENT_ENTITY_NOT_ALLOWED + : Violation.ACTION_METHOD_RETURNING_NON_BOOKMARKABLE_OBJECT_NOT_ALLOWED; + return violation.builder() + .addVariablesFor(actionId) + .addVariable("returnTypeSpec", returnTypeSpec.toString()) + .buildMessage(); + }); }); // sync DTO with result
