Calling Servlet From GWT FormPanel - gwt

How can I Pass parameter from FormPanel of GWT to Servlet?
FormPanel formPanel = new FormPanel();
formPanel.setAction(GWT.getModuleBaseURL()
+ "ntPdfDownload?myParam=" + String.valueOf(document.getId())+ "&myValue="+ConstantName.IS_REQUIRED.toString()+"");
formPanel.setMethod(FormPanel.METHOD_GET);
formPanel.setEncoding(FormPanel.ENCODING_MULTIPART);
formPanel.submit();
This is what I have done.. But I am not able to get parameters at Servelt.

If you want to use ENCODING_MULTIPART. Your method has to be POST. This is generally required when you want to upload files to server.
I guess you are passing simple parameters to your servlet.So, It should work without formPanel.setEncoding(FormPanel.ENCODING_MULTIPART);.

If you have changed the method from GET to POST, make sure that in the servlet you're also implementing
public void doPost(HttpServletRequest req, HttpServletResponse resp){...}
instead of just the doGet(...)

Related

How to access suffixes using HTL/Sightly?

TLDR: Create a new AEM page called "mypage.html". Supply suffixes in the URL. Pass this suffixes to an Sling servlet. The suffixes act as URL parameters.
sample desired URL: http://localhost:4502/mypage.html/john/smith
So I created a servlet (used this guide: http://www.aemcq5tutorials.com/tutorials/sling-servlet-in-aem/) that can read a suffix.
#SuppressWarnings("serial")
#SlingServlet(paths="geometrixx/components/hompepage", selectors="name", extensions="html",methods="GET", metatype=true)
public class StaffProfileServlet extends SlingAllMethodsServlet {
private static final Logger log = LoggerFactory.getLogger(CourseBookmarkServlet.class);
#Override
protected void doGet(final SlingHttpServletRequest request,
final SlingHttpServletResponse response) throws ServletException, IOException {
RequestPathInfo rpi = request.getRequestPathInfo();
String[] suffixes = rpi.getSuffix().split("/");
and it working fine if I access it via http://localhost:4502/content/geometrixx/en.name.html/first/last
What I want to do next is create a new page called "mypage.html" and supply first and last as suffixes.
mypage will display information relevant to the person in a properly formatted page. With code above, all I get is JSON response.
Some assumptions/changes which I think is needed to achieve my goal:
I will be using paths and using request parameters (i.e. using request.getParameter("myparameter") on servlet code
I will be using AJAX to access the servlet
If my assumptions are correct, how do I access suffixes from HTL/Sightly? I understand I can get the URI via ${request.requestURI} or even Javascript. And using this value, I can then use this in my AJAX call.
But is this the AEM/Sling way of doing it? Or perhaps there is a better way to do what I want?
Thanks a lot!
You can use RequestPathInfo interface from HTL to access suffix's. ${request.requestPathInfo.suffix}
Global objects accessible through HTL -> here.
Methods accessible through request object -> here.

How to produce rendered output from a Sling POST in AEM?

It seems like Sling expects every form POST to modify the JCR. So the expected/standard behavior would be a POST-redirect-GET, which is fine for most things. However, I need to be able to POST to AEM and then use the data in that POST to create a rendered result. Our use of AEM is stateless and so I don't want to carry the POST'd data in Session in order to utilize it in a subsequent GET.
Some have recommended putting the POST'd data in Browser sessionStorage, but that doesn't have broad enough support to be sufficient.
As far as I can tell there is no way for Sling in AEM to take a POST and produce a rendered result.
Here is a screenshot of what a POST produces in the page/resourceType component and in any Sling included jsp's that happen to be involved in the rendering.
I have tried things like using the "nop" operation.
<input type="hidden" name=":operation" value="nop" />
But either way all servlets think a POST is happening and don't render properly.
There is the option of creating a custom servlet, to handle the POST, but then how do you render the templated output and change the request so that all the components think they are serving a GET?
UPDATED:
Here is a screenshot of the "nop" POST.jsp result.
What you can do is create a POST.jsp file in the appropiate resourceType.
If your POST request go to /content/yourapp/something, which has a resourceType: your/app/example. Then you can create a file /apps/your/app/example/POST.jsp with whatever render you wish. You can even include your default rendering script in the POST.jsp file if you need it to be rendered the same as the GET requests.
The other option is to use a servlet registered for POST requests and internally use the SlingRequestProcessor service. That service allow you to programmatically process a request through Sling. You can use a SlingRequestWrapper to wrap your request and override getMethod() to return "GET". That should process the request as if it was a GET request.
This sounds like a somewhat funky use case, IIUC you are using a large request parameter P to drive the rendering?
Using a custom POST servlet should work, if you use something like
slingRequest.getRequestDispatcher(resource).forward(request, response) where request is a wrapper around the actual request, where request.getMethod() returns GET. You can then store your P data in request attributes.
The SlingHttpServletRequestWrapper class can be used to create such wrappers.
Creating a custom servlet to handle a post could be an idea. After successfull write you could redirect to the modified resource - simple 302.
The other solution that comes to my mind is a custom Filter that would do the same. However, since AEM expects to get 200 instead of 302, it would be good to tell by atrribute or parameter that this POST needs to be redirected. Otherwise some of the AEM UI functionalities could brake. This is a quick example of an idea. You would probably need to write something more sophisticated.
#Component(immediate = true)
#Service
#Properties({
#Property(name = Constants.SERVICE_DESCRIPTION, value = "Desc"),
#Property(name = Constants.SERVICE_VENDOR, value = "Company name"),
#Property(name = Constants.SERVICE_RANKING, intValue = RedirectFilter.RANKING),
#Property(name = "filter.scope", value = "request") })
public class RedirectFilter implements Filter {
public static final int RANKING = -1000; // low ranking
#Override
public void init(final FilterConfig filterConfig) throws ServletException {
}
#Override
public void destroy() {
}
#Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
throws IOException, ServletException {
if (request.getParameter("redirect").equals("true")) {
((SlingHttpServletResponse) response).sendRedirect(((SlingHttpServletRequest)request).getRequestURI());
}
}
}

Local request context in GWT

In Java, there is ThreadLocal, which can be used to carry some data from one object to another without explicit passing as method argument.
I need to intercept GWT request and extract custom HTTP header from it, then I need to store the header value somehow to be processed later.
The problem is that the place to extract the header belongs to RequestBuilder, and there is no way (?) to pass the variable from within RequestBuilder to the custom code actually handling the request/response from server. And it is not possible to pass some variable from client code to that request builder.
ThreadLocal could be the solution, however it is not available in GWT. Is there something I can use?
You can use RequestBuilder.setHeader to set header values for your HTTP request.
On the backend you can use HttpServletRequest of your servlet to retrieve the header values from your HTTP request.
Update:
Some class with a static instance variable:
public class SomeClass {
public static String myVar;
}
And in the RequestBuilder code you can do following:
RequestBuilder request = new RequestBuilder(url);
request.setCallback(new RequestCallback() {
#Override
public void onResponseReceived(Request request, Response response) {
SomeClass.myVar = response.getHeader("someheader");
}
});

Communicating between an HttpServlet and the client side of a GWT application

I have a simple GWT application that consists of a FormPanel that contains a single FileUpload field. The action on this form is to send it to GWT.getModuleBaseURL() + "process", which web.xml in turn tells GWT is the FileProcessServlet.
FileProcessServlet is a class that I made that extends HttpServlet and overrides doPost(HttpServletRequest req, HttpServletResponse resp) to parse the uploaded file and turn it into a Base64 string using Base64Utils. Now, I would like to pass the client side a single string that is the Base64 encoding of the file just sent it.
For the life of me, I just cannot figure out how to do this. The GWT documentation on Communicating with the Server doesn't say anything about receiving information back from a FormPanel.submit(). There is no callback function associated with such a request, as is the case with GWT RPC. At the same time, I need to use a servlet, since I want to parse a file, and that can't be done by the client. Any suggestions?
~~~~
PS: One option is that I can write directly to the html page from the servlet using java.io's PrintWriter (as this suggests). This may present a kind of solution where I store the Base64 string in a div with a special ID and then use DOM to get this content on the client end. However, I have not yet gotten PrintWriter to cooperate with me. Anytime I use it, with varying content types and character encodings, I still see nothing printed on the page. What I currently have attempting to print this out is:
String base64 = Base64Utils.toBase64(file);
resp.setContentType("text/html; charset=UTF-8");
resp.setCharacterEncoding("UTF-8");
PrintWriter out = resp.getWriter();
out.print(base64);
out.flush(); out.close();
But nothing comes out. The debugger has confirmed that the string base64 is not null nor empty on the penultimate line. Any help on this related front would also be appreciated. Nonetheless, I sincerely hope there is a better way.
form.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() {
public void onSubmitComplete(SubmitCompleteEvent event) {
// When the form submission is successfully completed, this event is
// fired. Assuming the service returned a response of type text/html,
// we can get the result text here (see the FormPanel documentation for
// further explanation).
Window.alert(event.getResults());
}
});
Whatever you write out from the servlet, will be in the event.getResults(), in your case the base64 String
Well I'm not 100% sure if your problem is on client or server side.
For the client:
formPanel.setAction("/[urlMappingOfYourServlet]");
formPanel.setEncoding(FormPanel.[CORRECT_ENCODING]);
formPanel.setMethod(FormPanel.METHOD_POST);
And to start the submission:
formPanel.submit();
Don't forget the mapping of your servlet in your web.xml. E.g.:
<servlet>
<servlet-name>nameOfYourServlet</servlet-name>
<servlet-class>your.package.server.YourServletClass</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>nameOfYourServlet</servlet-name>
<url-pattern>/urlMappingOfYourServlet</url-pattern>
</servlet-mapping>
On the server side you get the parsed data:
String data = request.getParameter("[NameOfYourFormPanelItem]");
You could use a javax.servlet.ServletOutputStream instead of PrintWriter.
ServletOutputStream out = resp.getOutputStream();
out.write(base64);
out.flush();
Another possibility is to use a RequestBuilder on the client side:
RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.POST, "/urlMappingOfYourServlet");
requestBuilder.sendRequest(someData, new RequestCallback() {
#Override
public void onResponseReceived(Request request,
Response response) {
// ToDo: Get your String here
response.getText();
}
#Override
public void onError(Request request, Throwable exception) {
// ToDo
}
});

making a servlet in netbeans and index.jsp

i am trying to make a servlet in netbeans. It has to be called from an html form and take some data from it.
i overwrite doget and dopost putting just some testing outs in them.
when i try to run the servlet it only shows a hello word jsp page i found out that this was the index.jsp page that the servlet had by default.
How can i make the servlet run and actually make some output? other than the index welcome page?
Which url mast i use in order to call the servlet from the form?
th doget and dopost methods look like this
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
ResourceBundle rb =
ResourceBundle.getBundle("LocalStrings",request.getLocale());
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
String title = rb.getString("helloworld.title");
out.println("<title>" + title + "this is my anser</title>");
out.println("</head>");
out.println("</html>");
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);}
How can i make the servlet run and actually make some output? other than the index welcome page?
You should dispatch the request into the desired JSP page. You can do this with RequestDispatcher.
request.getRequestDispatcher("page.jsp").forward(request, response);
Which url mast i use in order to call the servlet from the form?
The one which you've mapped in web.xml.
You should also be putting HTML in JSP page only, not in servlet. It's also not a good practice to let doGet() and doPost() do the same. The doGet() is merely there to preprocess the data before displaying in JSP. The doPost() is merely there to postprocess the data after a HTML form submit.
In the tag info about [servlets] tag here you can find a hello world example and more links about starting with JSP/servlets.