This is an automated email from the ASF dual-hosted git repository. nmalin pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git
The following commit(s) were added to refs/heads/trunk by this push: new e12c98ac5b Implemented: Define return user message from controller (OFBIZ-12652) e12c98ac5b is described below commit e12c98ac5b1fcd58a8143707b5a80a333964b7ab Author: Nicolas Malin <nicolas.ma...@nereide.fr> AuthorDate: Fri Jul 15 15:59:09 2022 +0200 Implemented: Define return user message from controller (OFBIZ-12652) Currently, when you wish return a message to a user after an event request, you need to set it ine the called event. for a service in java : ServiceUtil.returnSuccess("Your service is a success") for a service in groovy : return success("Your service is a success") for a Java class : request.setAttribute("_EVENT_MESSAGE_", "Your service is a success"); If during an integration, you want to use standard service like createProduct, createPartyRelationship, and need a specific message for users, you need to define your own service. For escape this case and increase the service usability, I propose to implement a new system to override the event return by a definition depending on the buisness context. For that two improvement : 1. Add new child element to request-map->response on the controller With given the exact value: <response name="success" type="request" value="json"> <return-user-message value="Your service is a success"/> </response> With a flexible expander: <response name="success" type="request" value="json"> <return-user-message value="Your service to change is a success"/> </response> With a property: <response name="success" type="request" value="json"> <return-user-message ressource="CommonUiLabels" value="CommonSuccessfullyCreated"/> </response> From a context field: <response name="success" type="request" value="json"> <return-user-message from-field="mySpecificReturnMessage"/> </response> 2. From the context directly sent from the form <form name="CallEvent" target="MyEvent" .. > <field name="_CUSTOM_EVENT_MESSAGE_"> <hidden value="Your service to change is a success"/> <field name="_CUSTOM_ERROR_MESSAGE_"> <hidden value="Your service failed"/> Thanks to Florian Motteau for the implementation help --- framework/webapp/dtd/site-conf.xsd | 35 +++++++++++++ .../ofbiz/webapp/control/ConfigXMLReader.java | 60 ++++++++++++++++++++++ .../ofbiz/webapp/control/RequestHandler.java | 52 +++++++++++++++++++ 3 files changed, 147 insertions(+) diff --git a/framework/webapp/dtd/site-conf.xsd b/framework/webapp/dtd/site-conf.xsd index b02d6e46ce..f6912fa9ce 100644 --- a/framework/webapp/dtd/site-conf.xsd +++ b/framework/webapp/dtd/site-conf.xsd @@ -382,6 +382,40 @@ under the License. </xs:attribute> </xs:complexType> </xs:element> + <xs:element name="return-user-message"> + <xs:annotation> + <xs:documentation> + Before return a response to the end user, we can override the event message from different origin. + Hard coded, from the labelling system or from a given field + </xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:attribute name="ressource" type="xs:string"> + <xs:annotation> + <xs:documentation> + Properties ressource to use for resolve the message, if you set a value here, indicate the key on value attribute + otherwise this attribute will be ignored. + 'like: CommonUiLabels' + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="value" type="xs:string"> + <xs:annotation> + <xs:documentation> + Value to use to display the response user message. + You can set a plain text, a flexible string or use a key from the property file give in ressource attribute. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="from-field" type="xs:string"> + <xs:annotation> + <xs:documentation> + Set from what field in context we can found the response user message. This field can contain a flexible string + </xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:complexType> + </xs:element> <xs:element name="event"> <xs:annotation> <xs:documentation> @@ -469,6 +503,7 @@ under the License. </xs:documentation> </xs:annotation> </xs:element> + <xs:element minOccurs="0" ref="return-user-message"/> </xs:sequence> <xs:attributeGroup ref="attlist.response"/> </xs:complexType> diff --git a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ConfigXMLReader.java b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ConfigXMLReader.java index 4d76e2283c..ab3b267e23 100644 --- a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ConfigXMLReader.java +++ b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ConfigXMLReader.java @@ -876,6 +876,7 @@ public final class ConfigXMLReader { private boolean saveHomeView = false; private Map<String, String> redirectParameterMap = new HashMap<>(); private Map<String, String> redirectParameterValueMap = new HashMap<>(); + private RequestResponseUserMessage responseMessage = null; /** * Gets status code. @@ -901,6 +902,14 @@ public final class ConfigXMLReader { return redirectParameterValueMap; } + /** + * return the response user message element linked to this + * @return + */ + public RequestResponseUserMessage getResponseMessage() { + return responseMessage; + } + /** * Gets type. * @return the type @@ -938,6 +947,57 @@ public final class ConfigXMLReader { this.redirectParameterMap.put(redirectParameterElement.getAttribute("name"), from); } } + Element messageElement = UtilXml.firstChildElement(responseElement, "return-user-message"); + if (messageElement != null) { + this.responseMessage = new RequestResponseUserMessage(this, messageElement); + } + } + } + + public static class RequestResponseUserMessage { + private RequestResponse requestResponse; + private String ressource; + private String value; + private String fromField; + + public RequestResponseUserMessage() { + } + + public RequestResponseUserMessage(RequestResponse requestResponse, Element responseElement) { + this.requestResponse = requestResponse; + ressource = UtilValidate.isNotEmpty(responseElement.getAttribute("ressource")) + ? responseElement.getAttribute("ressource") + : null; + value = UtilValidate.isNotEmpty(responseElement.getAttribute("value")) + ? responseElement.getAttribute("value") + : null; + fromField = UtilValidate.isNotEmpty(responseElement.getAttribute("from-field")) + ? responseElement.getAttribute("from-field") + : null; + } + + /** + * Return the ressource to use + * @return + */ + public String getRessource() { + return ressource; + } + + /** + * Return the value + * @return + */ + public String getValue(Map<String, Object> context) { + return value; + } + + /** + * Return the fromField + * @return + */ + public String getFromField() { + return fromField; } } diff --git a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/RequestHandler.java b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/RequestHandler.java index 877a5de387..18ec08d8d5 100644 --- a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/RequestHandler.java +++ b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/RequestHandler.java @@ -56,6 +56,7 @@ import org.apache.ofbiz.base.util.UtilMisc; import org.apache.ofbiz.base.util.UtilObject; import org.apache.ofbiz.base.util.UtilProperties; import org.apache.ofbiz.base.util.UtilValidate; +import org.apache.ofbiz.base.util.string.FlexibleStringExpander; import org.apache.ofbiz.entity.Delegator; import org.apache.ofbiz.entity.GenericEntityException; import org.apache.ofbiz.entity.GenericValue; @@ -825,6 +826,9 @@ public final class RequestHandler { + eventReturn + "]."); } + // before follow, analyze if a have a specific event message to return on the request. + setUserMessageResponseToRequest(request, nextRequestResponse); + if (Debug.verboseOn()) { Debug.logVerbose("[Event Response Selected] type=" + nextRequestResponse.getType() + ", value=" + nextRequestResponse.getValue() + ". " + showSessionId(request), MODULE); @@ -1017,6 +1021,54 @@ public final class RequestHandler { } } + /** + * Before return to end user the response, analyse if in this place we need override the event message + * 1. Check if the request response have a dedicated response user message + * 2. Check if a custom message is present on the context like _CUSTOM_ERROR_MESSAGE_ and _CUSTOM_EVENT_MESSAGE_ + * @param request + * @param requestResponse + */ + private void setUserMessageResponseToRequest(HttpServletRequest request, ConfigXMLReader.RequestResponse requestResponse) { + final String fieldMessageName = requestResponse.getName() == "error" + ? "_ERROR_MESSAGE_" + : "_EVENT_MESSAGE_"; + final String customMessageField = "_CUSTOM" + fieldMessageName; + Map<String, Object> context = UtilHttp.getCombinedMap(request); + String userMessage = null; + + if (requestResponse.getResponseMessage() != null) { + ConfigXMLReader.RequestResponseUserMessage responseMessage = requestResponse.getResponseMessage(); + + // Check if the response user message come from labelling ressource + String value = responseMessage.getValue(context); + if (UtilValidate.isNotEmpty(value)) { + userMessage = responseMessage.getRessource() != null + ? UtilProperties.getMessage( + responseMessage.getRessource(), value, + context, UtilHttp.getLocale(request)) + : value; + } else if (responseMessage.getFromField() != null + && context.containsKey(responseMessage.getFromField())) { + + // now analyze each field to found a flexible string to expand + userMessage = FlexibleStringExpander.getInstance( + (String) context.get(responseMessage.getFromField())) + .expandString(context); + } + + if (UtilValidate.isNotEmpty(userMessage)) { + request.setAttribute(fieldMessageName, userMessage); + return; + } + + if (context.containsKey(customMessageField)) { + + //This field from the request so for security reason do not expand it to exclude any code injection + request.setAttribute(fieldMessageName, context.get(customMessageField)); + } + } + } + /** * Find the event handler and invoke an event. */