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

dklco pushed a commit to branch forms-enhancements
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-app-cms.git


The following commit(s) were added to refs/heads/forms-enhancements by this 
push:
     new 3bafb4b  Improve the handling of the error page
3bafb4b is described below

commit 3bafb4b162acf28a06759dba27f5d5403aae3e22
Author: Dan Klco <[email protected]>
AuthorDate: Tue Jan 19 17:30:28 2021 -0500

    Improve the handling of the error page
---
 .../cms/reference/forms/impl/FormHandler.java      | 96 ++++++++++++++--------
 .../cms/reference/forms/impl/FormRequestImpl.java  | 27 ++++--
 .../forms/impl/fields/TextfieldHandler.java        |  1 -
 .../apps/reference/components/forms/form/edit.json |  6 ++
 .../cms/reference/forms/impl/FormHandlerTest.java  | 12 +--
 reference/src/test/resources/form.json             |  1 -
 6 files changed, 91 insertions(+), 52 deletions(-)

diff --git 
a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/FormHandler.java
 
b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/FormHandler.java
index 0b8de5b..66feb4f 100644
--- 
a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/FormHandler.java
+++ 
b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/FormHandler.java
@@ -30,6 +30,7 @@ import org.apache.jackrabbit.JcrConstants;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
 import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.api.servlets.SlingAllMethodsServlet;
 import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
 import org.apache.sling.cms.Page;
@@ -64,41 +65,38 @@ public class FormHandler extends SlingAllMethodsServlet {
     @Override
     protected void doPost(SlingHttpServletRequest request, 
SlingHttpServletResponse response)
             throws ServletException, IOException {
+        ValueMap properties = request.getResource().getValueMap();
 
         String pagePath = 
Optional.ofNullable(request.getResource().adaptTo(PageManager.class))
                 .map(PageManager::getPage).map(Page::getPath)
                 
.orElse(StringUtils.substringBefore(request.getResource().getPath(), "/" + 
JcrConstants.JCR_CONTENT));
+        String successPage = null;
+        String errorPage = pagePath;
 
         StringSubstitutor sub = null;
         try {
-            if (request.getResource().getChild("actions") == null) {
-                throw new FormException("No actions provided to handle this 
form submission");
-            }
-            List<Resource> actionResources = 
ResourceTree.stream(request.getResource().getChild("actions"))
-                    
.map(ResourceTree::getResource).collect(Collectors.toList());
-
-            FormRequest formRequest = getFormRequest(request);
+            log.debug("Extracting form request...");
+            FormRequest formRequest = request.adaptTo(FormRequest.class);
             if (formRequest == null) {
                 log.warn("Unable to create form request");
-                
response.sendRedirect(request.getResourceResolver().map(request, pagePath) + 
".html?error=fields");
+                response.sendRedirect(this.resolveUrl(request, errorPage, 
"error=init"));
                 return;
             }
+
+            log.debug("Loading fields...");
+            boolean fieldsLoadSucceeded = ((FormRequestImpl) 
formRequest).initFields();
             sub = new StringSubstitutor(formRequest.getFormData());
-            request.getSession().setAttribute(formRequest.getSessionId(), 
formRequest.getFormData());
-            for (Resource actionResource : actionResources) {
-                log.debug("Finding action handler for: {}", actionResource);
-                FormAction action = formActions.stream().filter(fa -> 
fa.handles(actionResource)).findFirst()
-                        .orElse(null);
-                if (action != null) {
-                    FormActionResult result = 
action.handleForm(actionResource, formRequest);
-                    if (!result.isSucceeded()) {
-                        throw new FormException(
-                                "Failed to invoke action: " + action + " with 
message: " + result.getMessage());
-                    } else {
-                        log.debug("Successfully invoked action: {}", 
result.getMessage());
-                    }
-                }
+            successPage = sub.replace(properties.get("successPage", pagePath));
+            errorPage = sub.replace(properties.get("errorPage", pagePath));
+            if (!fieldsLoadSucceeded) {
+                log.warn("Field initialization failed, check logs");
+                response.sendRedirect(this.resolveUrl(request, errorPage, 
"error=fields"));
+                return;
             }
+            request.getSession().setAttribute(formRequest.getSessionId(), 
formRequest.getFormData());
+
+            log.debug("Calling actions...");
+            callActions(request, formRequest);
             request.getSession().removeAttribute(formRequest.getSessionId());
         } catch (FormException e) {
             log.warn("Exception executing actions", e);
@@ -106,31 +104,61 @@ public class FormHandler extends SlingAllMethodsServlet {
             return;
         }
 
-        String thankYouPage = 
sub.replace(request.getResource().getValueMap().get("successPage", pagePath));
-        if (StringUtils.isNotBlank(thankYouPage)) {
-            if 
("forward".equals(request.getResource().getValueMap().get("successAction", 
String.class))) {
+        if (StringUtils.isNotBlank(successPage)) {
+            if ("forward".equals(properties.get("successAction", 
String.class))) {
                 SlingHttpServletRequestWrapper requestWrapper = new 
SlingHttpServletRequestWrapper(request) {
                     @Override
                     public String getMethod() {
                         return "GET";
                     }
                 };
-
-                
request.getRequestDispatcher(thankYouPage).forward(requestWrapper, response);
+                
request.getRequestDispatcher(successPage).forward(requestWrapper, response);
             } else {
-                response.sendRedirect(resolveThankYouPage(request, 
thankYouPage));
+                response.sendRedirect(resolveUrl(request, successPage, 
"message=success"));
             }
         } else {
-            response.sendRedirect(resolveThankYouPage(request, thankYouPage));
+            response.sendRedirect(resolveUrl(request, successPage, 
"message=success"));
         }
     }
 
-    private String resolveThankYouPage(SlingHttpServletRequest request, String 
thankYouPage) {
-        if (!thankYouPage.contains(".html")) {
-            thankYouPage += ".html";
+    private void callActions(SlingHttpServletRequest request, FormRequest 
formRequest) throws FormException {
+        Resource actions = request.getResource().getChild("actions");
+        if (actions == null) {
+            throw new FormException("No actions provided to handle this form 
submission");
+        }
+        List<Resource> actionResources = 
ResourceTree.stream(actions).map(ResourceTree::getResource)
+                .collect(Collectors.toList());
+
+        for (Resource actionResource : actionResources) {
+            log.debug("Finding action handler for: {}", actionResource);
+            FormAction action = formActions.stream().filter(fa -> 
fa.handles(actionResource)).findFirst().orElse(null);
+            if (action != null) {
+                FormActionResult result = action.handleForm(actionResource, 
formRequest);
+                if (!result.isSucceeded()) {
+                    throw new FormException(
+                            "Failed to invoke action: " + action + " with 
message: " + result.getMessage());
+                } else {
+                    log.debug("Successfully invoked action: {}", 
result.getMessage());
+                }
+            }
+        }
+    }
+
+    private String resolveUrl(SlingHttpServletRequest request, String url, 
String qs) {
+        if (url.contains("?")) {
+            qs = "&" + qs;
+        } else {
+            qs = "?" + qs;
+        }
+        if (url.startsWith("/")) {
+            if (!url.contains(".html")) {
+                url += ".html";
+            }
+            url += qs;
+            return request.getResourceResolver().map(request, url);
+        } else {
+            return url + qs;
         }
-        thankYouPage += "?message=success";
-        return request.getResourceResolver().map(request, thankYouPage);
     }
 
     protected FormRequest getFormRequest(SlingHttpServletRequest request) 
throws FormException {
diff --git 
a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/FormRequestImpl.java
 
b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/FormRequestImpl.java
index 396d388..2ab4b7d 100644
--- 
a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/FormRequestImpl.java
+++ 
b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/FormRequestImpl.java
@@ -101,19 +101,32 @@ public class FormRequestImpl implements FormRequest {
         return request;
     }
 
-    public void initFields() throws FormException {
+    public boolean initFields() {
         List<Resource> fields = 
ResourceTree.stream(getFormResource().getChild("fields")).map(ResourceTree::getResource)
                 .collect(Collectors.toList());
+        boolean successful = true;
         for (Resource field : fields) {
-            log.debug("Looking for handler for: {}", field);
-            for (FieldHandler fieldHandler : fieldHandlers) {
-                if (fieldHandler.handles(field)) {
-                    log.debug("Invoking field handler: {}", 
fieldHandler.getClass());
-                    fieldHandler.handleField(request, field, formData);
-                    break;
+            formData.remove(getErrorKey(field));
+            try {
+                log.debug("Looking for handler for: {}", field);
+                for (FieldHandler fieldHandler : fieldHandlers) {
+                    if (fieldHandler.handles(field)) {
+                        log.debug("Invoking field handler: {}", 
fieldHandler.getClass());
+                        fieldHandler.handleField(request, field, formData);
+                        break;
+                    }
                 }
+            } catch (FormException fe) {
+                log.warn("Failed to populate field {} due to exception", 
field, fe);
+                successful = false;
+                formData.put(getErrorKey(field), fe.getMessage());
             }
         }
+        return successful;
+    }
+
+    private String getErrorKey(Resource field) {
+        return "fielderror-" + field.getValueMap().get("name", String.class);
     }
 
     @Override
diff --git 
a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/fields/TextfieldHandler.java
 
b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/fields/TextfieldHandler.java
index d3150a6..f498586 100644
--- 
a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/fields/TextfieldHandler.java
+++ 
b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/fields/TextfieldHandler.java
@@ -110,7 +110,6 @@ public class TextfieldHandler implements FieldHandler {
                     formData.put(name + ".contentType", 
param.getContentType());
                 }
             } else if ("date".equals(saveAs)) {
-
                 if (!dateFormats.containsKey(type)) {
                     throw new FormException("Field " + name + " is not a date 
type");
                 }
diff --git 
a/reference/src/main/resources/jcr_root/apps/reference/components/forms/form/edit.json
 
b/reference/src/main/resources/jcr_root/apps/reference/components/forms/form/edit.json
index aa98ccd..422d9d3 100644
--- 
a/reference/src/main/resources/jcr_root/apps/reference/components/forms/form/edit.json
+++ 
b/reference/src/main/resources/jcr_root/apps/reference/components/forms/form/edit.json
@@ -19,6 +19,12 @@
             "name": "submitText",
             "required": true
         },
+        "errorPage": {
+            "jcr:primaryType": "nt:unstructured",
+            "sling:resourceType": "sling-cms/components/editor/fields/path",
+            "label": "Error Page",
+            "name": "errorPage"
+        },
         "successPage": {
             "jcr:primaryType": "nt:unstructured",
             "sling:resourceType": "sling-cms/components/editor/fields/path",
diff --git 
a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/FormHandlerTest.java
 
b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/FormHandlerTest.java
index 70106fc..ab0e2ab 100644
--- 
a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/FormHandlerTest.java
+++ 
b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/FormHandlerTest.java
@@ -17,7 +17,6 @@
 package org.apache.sling.cms.reference.forms.impl;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.never;
 
 import java.io.IOException;
@@ -100,17 +99,12 @@ public class FormHandlerTest {
                     }
 
                 })));
+        context.registerAdapter(SlingHttpServletRequest.class, 
FormRequest.class, formRequest);
 
         mailService = Mockito.mock(MailService.class);
         Mockito.when(mailService.getMessageBuilder()).thenReturn(new 
MockMessageBuilder());
         final SendEmailAction sendEmailAction = new 
SendEmailAction(mailService);
-        formHandler = new FormHandler(Arrays.asList(sendEmailAction)) {
-            private static final long serialVersionUID = 1L;
-
-            protected FormRequest getFormRequest(final SlingHttpServletRequest 
request) {
-                return formRequest;
-            }
-        };
+        formHandler = new FormHandler(Arrays.asList(sendEmailAction));
     }
 
     @Test
@@ -130,7 +124,7 @@ public class FormHandlerTest {
 
         formHandler.service(context.request(), context.response());
 
-        assertTrue(HttpServletResponse.SC_MOVED_TEMPORARILY == 
context.response().getStatus());
+        assertEquals(HttpServletResponse.SC_MOVED_TEMPORARILY, 
context.response().getStatus());
         assertEquals("/form-no-actions.html?error=actions", 
context.response().getHeader("Location"));
         Mockito.verify(mailService, never()).sendMessage(Mockito.any());
     }
diff --git a/reference/src/test/resources/form.json 
b/reference/src/test/resources/form.json
index 1d558c8..2021c1a 100644
--- a/reference/src/test/resources/form.json
+++ b/reference/src/test/resources/form.json
@@ -119,7 +119,6 @@
                             },
                             "file": {
                                 "jcr:primaryType": "nt:unstructured",
-                                "required": true,
                                 "name": "file",
                                 "type": "file",
                                 "label": "File",

Reply via email to