How to validate a field using cq.HTTP.post method

2020-05-01 14:58发布

问题:

I am trying to validate a field by sending field value to a servlet and in response i'm getting true or false i.e whether this field is valid or not . here is my dialog file

  <bodytext
            jcr:primaryType="cq:Widget"
            fieldDescription="Type Text Here"
            fieldLabel="Body Text"
            name="./bodytext"
     validator= "function(value) {   
var dialog = this.findParentByType('dialog');  
var postParams = {};
postParams['value'] = value;

CQ.HTTP.post('/bin/feeds/validation.json', function(options, success, response){response.valid ? true : 'Form name already exists on this page.';},postParams);
}" xtype="textarea"/>

and here is my servlet code

import java.io.IOException;

import javax.servlet.ServletException;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.io.JSONWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.day.cq.commons.TidyJSONWriter;

public abstract class AbstractValidatorServlet extends SlingAllMethodsServlet {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private static final Logger LOG = LoggerFactory.getLogger(AbstractValidatorServlet.class);


    @Override
    protected final void doPost(final SlingHttpServletRequest request, final SlingHttpServletResponse response)
        throws ServletException, IOException {
        final String value = request.getRequestParameter("value").getString();
       final boolean valid = isValid(value);      
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");


        try {
            final TidyJSONWriter writer = new TidyJSONWriter(response.getWriter());
            response.setContentType("application/json");
            //JSONWriter writer = new JSONWriter(response.getWriter());
                    try {
                    writer.object();
                    writer.key("valid").value(valid);
                    writer.endObject(); 

                } catch (JSONException e) {

                    e.printStackTrace();
                }
             }  catch (final IOException ioe) {
            LOG.error("error writing JSON response", ioe);
        }
    }

    /**
     * Validate the given value for this request and path.
     *
     * @param request servlet request
     * @param path path to current component being validated
     * @param value input value to validate
     * @return true if value is valid, false otherwise
     */
    protected abstract boolean isValid(final String value);

}



import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.tidy.Tidy;

import com.adobe.granite.xss.XSSAPI;

@Component
@Service
@Properties({
    @Property(name="sling.servlet.paths",value="/bin/feeds/validation"),
    @Property(name = "sling.servlet.extensions", value = "json"),
    @Property(name = "sling.servlet.methods", value = "POST"),
    @Property(name = "sling.servlet.selectors", value = "validator"),
    @Property(name = "service.description", value = "XSS API HTML Validator Servlet")
})
public final class HTMLValidatorServlet extends AbstractValidatorServlet {

    private static final long serialVersionUID = 1L;
    private static final Logger LOG = LoggerFactory.getLogger(HTMLValidatorServlet.class);

    @Reference
    XSSAPI xssapi;

    @Override
    protected boolean isValid(final String value) {
            String data = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
                    + "<html xmlns=\"http://www.w3.org/1999/xhtml\"><title></title><body>"+StringEscapeUtils.unescapeHtml(value)+"</body></html>";

            Tidy tidy=new Tidy();
            tidy.setXmlTags(true); 
            tidy.setXHTML(true);
            StringWriter writer = new StringWriter(); 
            tidy.setErrout(new PrintWriter(writer)); 
            ByteArrayInputStream in = new ByteArrayInputStream(data.getBytes()); 
            ByteArrayOutputStream out = new ByteArrayOutputStream(); 
            tidy.parse(in,out); 
            int numErrors = tidy.getParseErrors();
            if(numErrors > 0) 
            { 
                return false;
            }
            else{
            return true;
            }
    }

}

I'm getting aUnspecified Error in cq5. can anybody where i'm lacking . thanks in advance

回答1:

Since the post doesn't mention the imports , I'm assuming you are using the Citytech Bedrock library's AbstractValidatorServlet. This servlet only overrides the doGet method. The docs say the servlets have to be registered to a resourceType and GET method.

@SlingServlet(resourceTypes = "bedrock/components/content/example", selectors = "validator", extensions = "json", methods = "GET")

The library also have a javascript utility method to call the validator servlet

Bedrock.Utilities.Dialog.validateField(this, value, 'Name is invalid');



回答2:

The problem is actually that the servlet is expecting a json extension and you are sending none. Look closely at the following definition:

@Property(name = "sling.servlet.extensions", value = "json")

and in your JS function you are calling the url /bin/feeds/validation:

CQ.HTTP.post('/bin/feeds/validation', function(options, success, response){}

So change the url to /bin/feeds/validation.json and it should work. Beside this you are expecting json and you are generating a html output. For building json response, you can use the class com.day.cq.commons.TidyJSONWriter as follows:

@Override
protected void doGet(final SlingHttpServletRequest request, final SlingHttpServletResponse response) throws ServletException, IOException {
    final TidyJSONWriter writer = new TidyJSONWriter(response.getWriter());
    response.setContentType("application/json");

    try {
        writer.object();
        writer.key("mykey").value("myvalue");
        writer.endObject();

    } catch(Exception e) {
      //handle the exceptions
    }
}