Return Response (HttpServletResponse) to HttpServletRequest - java

I always end up with a ClassCastException when trying to cast javax.ws.rs.core.Responseinto ajavax.servlet.http.HttpServletResponse
My Servlet looks like this:
#GET
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Response myResponse = processRequest(request);
//myResponse -> response
}
The servlet is hosted on a a jetty:
context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.addServlet(new ServletHolder(servlet),"/*");
I want to return the content of myResponse (basically some json body if it matters) if this is possible.
Can someone help?

I don't think you can send the response from servlet to upstream in Response(Custom) format.
You need to set the value in HttpServletrequest and HttpServletResponse while sending the response to upstream.
Below is my suggestion for sending the data in json format in servlet.
Put your JSON data as a string in a String object.
Set this object in request.setAttribute(); and use the name of the attribute to fetch the value in your ajax function. use JSON.parse() to convert the string to JSON.

Related

How to eliminate special characters before hitting the controller in Java?

I have a use case where I need to verify if the incoming request body to my controller contains any special characters in a Hybris storefront. Though it can be achieved from the front-end by blocking any special characters, we require back-end validation.
I tried using HandlerIntercepterAdapter to intercept the request and validate for any special characters. But whenever I use request.getReader() or request.getInputStream() and read the data, request body is cleared.
I tried using IOUtils.copy() but this too reads from the original request and makes the body empty.
Even after wrapping the request with HttpServletRequestWrapper or ContentCachingRequestWrapper, the request body gets cleared. I guess internally somewhere it uses the same reference.
I tried following this thread but was unable to solve this issue.
I am looking for a solution where I can extract the request body and validate it without letting it get cleared so it can be used in different controllers [or] any alternative approach which can help in preventing any special characters to hit the controller.
any alternative approach which can help in preventing any special characters to hit the controller.
What if you try to do the following ...
Get the request body
Process it
Set the request body again in your filter by setting the body to the processed version ?
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest originalRequest = (HttpServletRequest) request;
HttpServletResponse originalResponse = (HttpServletResponse) response;
/**
* 2.Read the original request body and change it
*/
String originalRequestBody = ServletUtil.readRequestBody(originalRequest); // Read the original request body
// Body is processed here !
String modifyRequestBody = processBody(originalRequestBody); // Modify request body (clear text)
HttpServletRequest orginalRequest = (HttpServletRequest) request;
ModifyRequestBodyWrapper requestWrapper = new ModifyRequestBodyWrapper(orginalRequest, modifyRequestBody);
/**
* 3. Build a new response object
*/
ModifyResponseBodyWrapper responseWrapper = new ModifyResponseBodyWrapper(originalResponse);
chain.doFilter(requestWrapper, responseWrapper);
String originalResponseBody = responseWrapper.getResponseBody(); // Original response body (clear text)
String modifyResponseBody = this.encryptBody(originalResponseBody); // Modified response volume (ciphertext)
/**
* 4.Output the modified response body with the output stream of the original response object
* To ensure that the response type is consistent with the original request, and reset the response body size
*/
originalResponse.setContentType(requestWrapper.getOrginalRequest().getContentType()); // Be consistent with the request
byte[] responseData = modifyResponseBody.getBytes(responseWrapper.getCharacterEncoding()); // The coding is consistent with the actual response
originalResponse.setContentLength(responseData.length);
#Cleanup ServletOutputStream out = originalResponse.getOutputStream();
out.write(responseData);
}
Here is a code example, which implements this.
The input should be set inside a form.
In your controller, you can use a validator :
#RequestMapping(value = "/process", method = RequestMethod.POST)
public String doValidateAndPost(final MyForm form, final BindingResult bindingResult,
final HttpServletRequest request, final Model model){
getMyValidator().validate(form, bindingResult);
if (bindingResult.hasErrors())
{
return MY_PAGE;
}
The validator will look like this :
#Override
public void validate(final Object object, final Errors errors)
{
final MyForm form = (MyForm ) object;
final String data = form.getMyData();
Pattern p = Pattern.compile("[^a-z0-9 ]", Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(data );
boolean b = m.find();
if (b)
{
errors.rejectValue("myData", "myData.invalid");
}
}
You can also use the #Valid annotation :
public String doValidateAndPost(#Valid final MyForm form ...
And set in your form :
#Pattern(regexp = "[a-z0-9 ]")
private String myData;

Render HTML response from remote call to the client

I have a working servlet wich originates back from this template:
http://www.objectdb.com/tutorial/jpa/eclipse/web/servlet
So the basic rountrip works.
I added a new feature where I POST data to the servlet, construct a call/request out of the data to a remote http server, retrieve the response-html-string (the content of the website I requested) and want to show this HTML String now as response to my original POST call.
I tried it like this:
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
boolean showDetails = Boolean.valueOf(request.getParameter("showDetails"));
if (showDetails) {
String details = detailsLoader.loadDetails(String.valueOf(request.getParameter("value1")),
String.valueOf(request.getParameter("value2")));
response.getWriter().println(details);
response.getWriter().flush();
response.getWriter().close();
return; // <----------------- if showDetails then this is the end of doPost
}
// Display the list of guests:
doGet(request, response);
}
When I press the link that creates the POST event I see in the logfile, that "loadDetails" has succesfully loaded the content from the remote server, but the browser window does not refresh. Why?
PS: a simple redirect to the other side is not possible for technical reasons.
Try making a ajax request to your servlet which gives to html content as string sent it back to ajax call and set it to innerHTML of a div element.
I changed to use GET instead of POST and I used a separate Servlet for this kind of call. This solved my problem.
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String details = detailsLoader.loadDetails(String.valueOf(request.getParameter("value1")),
String.valueOf(request.getParameter("value2")));
response.getWriter().println(details);
response.getWriter().flush();
response.getWriter().close();
}

Aspectj: get Response body (HTML Text) from HttpServletRresponse

I m trying to use aspectJ to intercept HttpServlet.do*(request, response) and get the HTML text ( need to extract the title and maybe store the html to a file).
What is the best way to access the response body (html text) once I have a reference to the HttpServletResponse?
Here is my staring code.
public aspect HttpRequestHandlerAspect {
pointcut getRequest(HttpServletRequest request, HttpServletResponse response)
: execution(protected * javax.servlet.http.HttpServlet.*(HttpServletRequest, HttpServletResponse))
&& args(request, response);
Object around(HttpServletRequest request, HttpServletResponse response) : getRequest(request, response) {
Object ret = proceed(request, response);
// now how do I access the HTML response text ( and get the title of the page) in here?
}
}
This might not be the precise answer for your question, but try extracting the response as suggested here: How can I read an HttpServletReponses output stream?
You don't have to create a filter, only an HttpServletResponseWrapper which you pass to
proceed(request, wrapper).
Object around(HttpServletRequest request, HttpServletResponse response): getRequest(request, response) {
MyHttpServletResponseWrapper wrapper = new MyHttpServletResponseWrapper(response);
Object ret = proceed(request, wrapper);
// The MyHttpServletReponseWrapper class captures everything and doesn't forward to the original stream, so we have to do this
response.getWriter().write(wrapper.toString());
// use wrapper.toString() to access response
}

handle ajax request and send response java servlet

I have an ajax request function (written in JavaScript) and Java Servlet that handles this request. I need to get all request parameters and if it succeeded then send back a confirmation that it has succeeded. How I can send a confirmation message? As an attribute, like {isSuccess: true}. My code:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
Enumeration<?> paramNames = request.getParameterNames();
while (paramNames.hasMoreElements()) {
String paramName = (String) paramNames.nextElement();
// storing data fn
}
// how to send back a message here?
}
Get PrintWriter object by calling HttpServletResponse#getWriter and write your String.
response.getWriter().write("{isSuccess: true}");

reading custom headers in servlets

I have a requirement to set custom headers in http response and read them whenever required. I use the following code to read the header.
servlet1:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.addHeader("cust-header", "cust-value");
RequestDispatcher rd = request.getRequestDispatcher("servlet2");
rd.include(request, response);
}
servlet2:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println(request.getHeader("cust-header"));
}
When I tried to read the custom header value, I got "null" in the console. Why this is happening? How can I read custom headers set in response whenever required?
From the RequestDipatcher include method API doc:
[...]
The ServletResponse object has its path elements and parameters remain
unchanged from the caller's. The included servlet cannot change the
response status code or set headers; any attempt to make a change is
ignored.
[...]
So, if you look at your code, you are setting the header at the response object, but trying to get it from the request.
As they remain unchanged, it won't work.
The most common way to pass values from a servlet to another in a forward or include redirection, is passing it as a request attribute:
servlet1:
//set a request attribute
request.setAttribute("cust-header", "cust-value");
RequestDispatcher rd = request.getRequestDispatcher("servlet2");
rd.include(request, response);
servlet2:
System.out.println(request.getAttribute("cust-header"));

Categories