Expand my Community achievements bar.

Dive into Adobe Summit 2024! Explore curated list of AEM sessions & labs, register, connect with experts, ask questions, engage, and share insights. Don't miss the excitement.
SOLVED

POST from 3rd party client to SlingServlet registered using resourceTypes

Avatar

Level 3

I am trying to create a servlet, registered using resourceType, that can accept an HTTP POST from a client external to the AEM site. Here's is my current code:

 

 

package com.ab.mysite.core.servlets;

import org.osgi.service.component.annotations.Component;
import java.io.IOException;
import javax.servlet.Servlet;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(
	service=Servlet.class,
	property= {			
		"sling.servlet.resourceTypes="+ "mysite/components/structure/page",
		"sling.servlet.selectors=" + "biosync",
		"sling.servlet.extensions=" + "html",
		"sling.servlet.methods="+"POST",
		"sling.servlet.methods="+"GET"
	}	
)
public class BioSyncServlet extends SlingAllMethodsServlet {

	private static final long serialVersionUID = 1L;
	private static final Logger log = LoggerFactory.getLogger(BioSyncServlet.class);
		
	@Override
	protected void doPost(
			SlingHttpServletRequest request, 
			SlingHttpServletResponse response)	
	{
		try {
			addCorsHeader(response);
			response.setContentType("text/plain");
			response.getWriter().write(getResponse(request));
			response.getWriter().close();
		} 
		catch (Exception ex) {
			log.error(ex.getMessage());
		}
	}
	
	@Override
	protected void doGet(
			SlingHttpServletRequest request, 
			SlingHttpServletResponse response) 
			throws IOException, ServletException
	{		
			try {
			addCorsHeader(response);
			response.setContentType("text/plain");
			response.getWriter().write(getResponse(request));	
			response.getWriter().close();
		} 
		catch (Exception ex) {
			log.error(ex.getMessage());
		}
	}
	
	private void addCorsHeader(SlingHttpServletResponse response){        
		response.setHeader("Access-Control-Allow-Origin", "*");        
		response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, HEAD");
        response.setHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Origin, X-Requested-With, Content-Type, Accept");
        response.setHeader("Access-Control-Max-Age", "1728000");
    }
	
	private String getResponse(SlingHttpServletRequest request)
	{		
		String fName = request.getParameter("fname");
		String lName = request.getParameter("lname");
		
		String responseText = "Your first name is " + fName + " and your last name is " + lName;
		return responseText;
	}
}

 

 

If I make an HTTP GET request to any page on my site (they all have resourceType "mysite/components/structure/page") with the selector, credentials in the headers, and a querystring of "?fname=Marvin&lname=Palmer", it returns "Your first name is Marvin and your last name is Palmer" as expected.

 

But if I make an HTTP POST to this servlet with (same page, selector, credentials) and pass the params in the post body, I get a 500 error and "java.lang.IllegalArgumentException" saying value for key 'fname' can't be put into node: Marvin.

 

Interestingly, if I HTTP POST (with credentials) using the same url + "/jcr:content", then I get a 200 response, and lname and fname are written with values "Marvin" and "Palmer" to the JCR at that node path. 

 

But I can't figure out how to get the request to result in execution of my doPost() method. I was able to get this doPost() to work when I registered the servlet using a "bin/biosync" path instead of using resourceType, but I've read that's a discouraged practice. 

 

What am I doing wrong?

1 Accepted Solution

Avatar

Correct answer by
Level 8

Hi @mpalme1 

Whenever we register servlet using resourceType, then the request url for that servlet will be "${resource.path}.extension" here path value will be path where this component is added in any page. so, try to add this in data-attribute in your component html, inspect the page source of the page where this component is added & check the path. you need access this value in javascript to pass this url as ajax request url.

 

Component html :

<div id="compname-resource-path" data-resource-path="${resource.path}.extension">

 

</div>

 

$('#compname-resource-path').data('resource-path'); //request url

View solution in original post

5 Replies

Avatar

Correct answer by
Level 8

Hi @mpalme1 

Whenever we register servlet using resourceType, then the request url for that servlet will be "${resource.path}.extension" here path value will be path where this component is added in any page. so, try to add this in data-attribute in your component html, inspect the page source of the page where this component is added & check the path. you need access this value in javascript to pass this url as ajax request url.

 

Component html :

<div id="compname-resource-path" data-resource-path="${resource.path}.extension">

 

</div>

 

$('#compname-resource-path').data('resource-path'); //request url

Avatar

Level 3
Except I'm not trying to call the servlet from a component. I actually need to be able to call the servlet from a program running outside of AEM.

Avatar

Level 8

@mpalme1 

If you want access this servlet outside AEM then register this servlet as path based & use that path as request url. ideally we should not share resource based servlet path to 3rd party/to access outside AEM since this path is not constant value, it will be a dynamic path as resource path will be different as & when we move this component within page/site.

Avatar

Level 3
So, that being the case, I think I'd want to create a least privileged account in http://localhost:4502/useradmin that would be used for the auth headers of the request and only allow it to post to that path, but it seems like I can't assign permissions to an account for anything under path /bin. How would I go about that?