Hi All,
Building a Form component by using Form core components. Added Custom Action type in drop down "Custom Action Call " of Form Core container proxy. Now on selection of above custom action in Container component & while Form submission need to call Service/Servlet the back-end for logic execution how to achieve what changes are needed. Any pointers around this on how to & where changes are needed.
Solved! Go to Solution.
Views
Replies
Total Likes
Hi @rsl_lucky, using servlet will be much more complicated due to the way how form component has been design. But of course it is possible. It can be done like this:
You will need to create your own Form container component that will extend /apps/core/wcm/components/form/container/v2/container and do some modification in container.html, e.g.
<!--/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ Copyright 2016 Adobe ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/--> <form data-sly-use.container="com.adobe.cq.wcm.core.components.models.form.Container" data-sly-use.grid="com.day.cq.wcm.foundation.model.responsivegrid.ResponsiveGrid" method="${container.method}" action="${container.action @ addSelectors='formHandler'}" id="${container.id}" name="${container.name}" enctype="${container.enctype}" class="cmp-form ${grid.cssClass}"> <div data-sly-test="${container.errorMessages}" data-sly-list.item="${container.errorMessages}" class="cmp-form-error"> <p class="cmp-form-error__item">${item}</p> </div> <input type="hidden" name=":formstart" value="${resource.path}"/> <input type="hidden" name="_charset_" value="utf-8"/> <input data-sly-test="${container.redirect}" type="hidden" name=":redirect" value="${container.redirect @ extension='html'}"/> <sly data-sly-repeat.paragraph="${grid.paragraphs}" data-sly-resource="${paragraph.path @ resourceType=paragraph.resourceType, decorationTagName='div', cssClassName=paragraph.cssClass}"></sly> <sly data-sly-resource="${resource.path @ resourceType=container.resourceTypeForDropArea, appendPath='/*', decorationTagName='div', cssClassName='new section aem-Grid-newComponent'}" data-sly-test="${wcmmode.edit || wcmmode.preview}"></sly> </form>
The change that has been done is formHandler selector has been added, so it will be included in link set inside action attribute.
Next we have servlet that will consume the request:
package com.mysite.core.servlets; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.SlingHttpServletResponse; import org.apache.sling.api.servlets.HttpConstants; import org.apache.sling.api.servlets.SlingAllMethodsServlet; import org.osgi.service.component.annotations.Component; import javax.servlet.Servlet; import javax.servlet.ServletException; import java.io.IOException; @Component(service = Servlet.class, property = { "sling.servlet.methods=" + HttpConstants.METHOD_POST, "sling.servlet.resourceTypes=sling/servlet/default", "sling.servlet.selectors=formHandler", "sling.servlet.extensions=html" }) public class MyFormServlet extends SlingAllMethodsServlet { @Override protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException { System.out.println("Handling form request via servlet"); } }
and the last thing, you need to disable com.adobe.cq.wcm.core.components.internal.servlets.CoreFormHandlingServlet OSGi component - you can sue component disbaler functinality form ACS Commons. The main reason for that is the fact that CoreFormHandlingServlet is servlet and filter so it is run in filter chain for every request.
I think that the previous solution is a bit better, because you do not need to change what you are getting out of the box. Of course running service from jsp is not a nice solution but I think as long you will keep your business logic in some java class/service this could be acceptable.
Hi @rsl_lucky, please find below very simple implementation of custom action that is handled by OSGi service.
CRX structure:
Code for above structure:
<customAction
jcr:primaryType="sling:Folder"
jcr:title="Custom action"
sling:resourceType="foundation/components/form/action">
<cq:dialog
jcr:primaryType="nt:unstructured"
jcr:title="Form Container"
sling:resourceType="granite/ui/components/coral/foundation/container">
<granite:data
jcr:primaryType="nt:unstructured"
showhidetargetvalue="my-app/components/form/actions/customAction"
usesRedirect="true"/>
</cq:dialog>
</customAction>
post.POST.jsp
<%--
Custom Action example
--%><%
%><%@include file="/libs/foundation/global.jsp"%><%
%><%@page session="false" %><%
%><%@page import="com.myapp.MySampleService"%><%
%><%
final MySampleService mySampleService = sling.getService(MySampleService.class);
mySampleService.handleFormRequest(slingRequest, slingResponse);
%>
OSGi service:
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.osgi.service.component.annotations.Component;
@Component(service = MySampleService.class)
public class MySampleService {
public void handleFormRequest(final SlingHttpServletRequest request, final SlingHttpServletResponse response) {
System.out.println("Custom form action");
// place for your code
}
}
In general post.POST.jsp is handling the request, from this place you can run any logic you like.
Hi lukaszm
Implemented the same code for testing the approach but service was not getting called. Let me try check the issue at service end and is their any other approach to implement to call servlet.
Hi @rsl_lucky, I have checked it one more time and it is working fine on my AEM 6.5.11 - service implementation is called. Do you see any errors in the log, also did you checked stdout.log - this is where the output from above sample code will go.
Hi lukaszm,
Yes could find the updates in log file now, issue with my Service which got resolved. In case to call Servlet in above case instead of Service how can we ? Also any thought's how can we apply styles to each field as they are form core components.
Hi @rsl_lucky, using servlet will be much more complicated due to the way how form component has been design. But of course it is possible. It can be done like this:
You will need to create your own Form container component that will extend /apps/core/wcm/components/form/container/v2/container and do some modification in container.html, e.g.
<!--/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ Copyright 2016 Adobe ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/--> <form data-sly-use.container="com.adobe.cq.wcm.core.components.models.form.Container" data-sly-use.grid="com.day.cq.wcm.foundation.model.responsivegrid.ResponsiveGrid" method="${container.method}" action="${container.action @ addSelectors='formHandler'}" id="${container.id}" name="${container.name}" enctype="${container.enctype}" class="cmp-form ${grid.cssClass}"> <div data-sly-test="${container.errorMessages}" data-sly-list.item="${container.errorMessages}" class="cmp-form-error"> <p class="cmp-form-error__item">${item}</p> </div> <input type="hidden" name=":formstart" value="${resource.path}"/> <input type="hidden" name="_charset_" value="utf-8"/> <input data-sly-test="${container.redirect}" type="hidden" name=":redirect" value="${container.redirect @ extension='html'}"/> <sly data-sly-repeat.paragraph="${grid.paragraphs}" data-sly-resource="${paragraph.path @ resourceType=paragraph.resourceType, decorationTagName='div', cssClassName=paragraph.cssClass}"></sly> <sly data-sly-resource="${resource.path @ resourceType=container.resourceTypeForDropArea, appendPath='/*', decorationTagName='div', cssClassName='new section aem-Grid-newComponent'}" data-sly-test="${wcmmode.edit || wcmmode.preview}"></sly> </form>
The change that has been done is formHandler selector has been added, so it will be included in link set inside action attribute.
Next we have servlet that will consume the request:
package com.mysite.core.servlets; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.SlingHttpServletResponse; import org.apache.sling.api.servlets.HttpConstants; import org.apache.sling.api.servlets.SlingAllMethodsServlet; import org.osgi.service.component.annotations.Component; import javax.servlet.Servlet; import javax.servlet.ServletException; import java.io.IOException; @Component(service = Servlet.class, property = { "sling.servlet.methods=" + HttpConstants.METHOD_POST, "sling.servlet.resourceTypes=sling/servlet/default", "sling.servlet.selectors=formHandler", "sling.servlet.extensions=html" }) public class MyFormServlet extends SlingAllMethodsServlet { @Override protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException { System.out.println("Handling form request via servlet"); } }
and the last thing, you need to disable com.adobe.cq.wcm.core.components.internal.servlets.CoreFormHandlingServlet OSGi component - you can sue component disbaler functinality form ACS Commons. The main reason for that is the fact that CoreFormHandlingServlet is servlet and filter so it is run in filter chain for every request.
I think that the previous solution is a bit better, because you do not need to change what you are getting out of the box. Of course running service from jsp is not a nice solution but I think as long you will keep your business logic in some java class/service this could be acceptable.
Hi @rsl_lucky, I am facing the same issue can you please explain me how to create custom action type in core form container.I want to pass my servlet URL in that custom action type.
Thank you in advance
Views
Replies
Total Likes
Is this approach viable for the ‘Mail’ action in Core Form Container?
Can you send an email using handleFromRequest?
Views
Replies
Total Likes
Views
Likes
Replies
Views
Likes
Replies