Get Cookie after its set in doFilter - servlets

I have a CookieFilter class that overrides doFilter method to set a Cookie before my Rest service is invoked:
import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.UUID;
public class CookieFilter implements Filter {
#Override
public void init(FilterConfig config) throws ServletException {}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
if (notPresent("TEST")) {
String uuid = UUID.randomUUID().toString();
httpResponse.addCookie(new Cookie("TEST", uuid));
}
chain.doFilter(request, response);
}
#Override
public void destroy() {}
private boolean notPresent(String cookieName) {
// here are the checks
}
}
Rest service method:
void myRestServiceMethod(#Context HttpServletRequest request) {
Cookie[] cookies = request.getCookies(); // has my cookie inside after second call
// other logic bellow
}
myRestServiceMethod is called after doFilter but Cookie is not present.
However, I am able to read the cookie (using JAX-RS #Context to retrieve HttpServletRequest object) in second client call to myRestServiceMethod where Cookie (set in a first call) is sent from the client and passed to the server.
My question is: is there a way read the Cookie in a first call to myRestServiceMethod after its set in doFilter?

is there a way read the Cookie in a first call to myRestServiceMethod after its set in doFilter?
No.
There are 2 solutions:
Refresh the request after adding cookie.
if (notPresent("TEST")) {
String uuid = UUID.randomUUID().toString();
httpResponse.addCookie(new Cookie("TEST", uuid));
httpRequest.sendRedirect(httpRequest.getRequestURI()); // NOTE: you might want to add query string if necessary.
}
else {
chain.doFilter(request, response);
}
Or, better, store it as request attribute.
String uuid = getCookieValue("TEST");
if (uuid == null) {
uuid = UUID.randomUUID().toString();
httpResponse.addCookie(new Cookie("TEST", uuid));
}
request.setAttribute("TEST", uuid);
chain.doFilter(request, response);
So that you can simply do this.
String uuid = (String) request.getAttribute("TEST");
If CDI is available in the environment, you could populate a #RequestScoped bean instead.
That said, it's strange to have a JAX-RS service to (indirectly) deal with cookies. REST is never intented to be stateful.

Related

How to pass request param from DynamoHttpServletRequest to (ServletRequest or HttpServletRequest)

I have application that is running on ATG. I have added filter servlet also. While login(using ATGForm), I am passing one parameter. I am able to get that param in DynamoHttpServletRequest. But, after I do forward or redirect to some JSP page, I am not able to get that param in the Filter servlet.
Filter Servlet as below:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
I am not able to get the same param in request. Anything I am missing here?
You can follow the doc for more :
https://docs.oracle.com/cd/E35319_01/Platform.10-2/ATGPlatformProgGuide/html/s0704filterexample01.html
import atg.servlet.ServletUtil;
import atg.servlet.DynamoHttpServletRequest;
import atg.servlet.DynamoHttpServletResponse;
import javax.servlet.*;
import javax.servlet.http.*;
public class MyFilter
implements Filter {
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException
{
// Get the Dynamo Request/Response Pair
DynamoHttpServletRequest dRequest =
ServletUtil.getDynamoRequest(request);
// Get param value
String paramValue =
(String)dRequest.resolveName("paramName");
// Pass control on to the next filter
chain.doFilter(request,response);
return;
}
}

how to disable web page cache throughout the servlets

To no-cache web page, in the java controller servlet, I did somthing like this in a method:
public ModelAndView home(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mav = new ModelAndView(ViewConstants.MV_MAIN_HOME);
mav.addObject("testing", "Test this string");
mav.addObject(request);
response.setHeader("Cache-Control", "no-cache, no-store");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
return mav;
}
But this only works for a particular response object. I have many similar methods in a servlet. And I have many servlets too.
If I want to disable cache throughout the application, what should I do?
(I do not want to add above code for every single response object).
Why not do this via a filter?
A filter is an object that can transform the header and content (or both) of a request or response. 
...
The main tasks that a filter can perform are as follows:
...
Modify the response headers and data. You do this by providing a customized version of the response.
Just register your Filter (class implementing the Filter interface) and modify your response within the doFilter method.
EDIT: E.g.
#WebFilter("/*")
public class NoCacheFilter implements javax.servlet.Filter {
#Override
public void init(final FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Cache-Control", "no-cache, no-store");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
filterChain.doFilter(request, response);
}
#Override
public void destroy() {
}
}
Note that the #WebFilter annotation will require Servlet 3.0, otherwise you can register it via your web.xml. This path of "/*", would apply to any path of your application, but could be narrowed in scope.

how to log the request coming from the client in spring

I want to log the json data which is posted from the client. I have written the interceptor also. I am receiving request but I am unable to log the json part of the reuqest. How can I do it?
here is my postdata json:
{"callerId":3456,"sessionId":"1554ba7c-b729-4dc5-9dd2-c48e2b275c3f","uniqueId":"some","courseProgress":{"bookmark":{"contentId":"aec4b2c5-6766-4d51-80ac-8fdc61f465ed","version":1}}}
here is my loggerInterceptor code :
public class LoggerInterceptor extends HandlerInterceptorAdapter {
static Logger logger = Logger.getLogger(LoggerInterceptor.class);
static {
BasicConfigurator.configure();
}
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
logger.info("Before handling the request");
return super.preHandle(request, response, handler);
}
}
So I am getting the request but not able to retreive the json data

Access servlet init parameters from filter

I have a servlet like this:
#WebServlet("/a/path")
#WebInitParam(name="name", value="name_value")
public class MyServlet extends HttpServlet {
//...
On this servlet I have put a filter:
#WebFilter(dispatcherTypes = { DispatcherType.REQUEST }, urlPatterns = { "/a/*" })
public class MyFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//...
HttpServletRequest req = (HttpServletRequest)request;
//problem comes here
System.out.println(req.getServletContext().getInitParameter("name"));
//...
}
The problem is, that even if I set the #WebInitParameter in MyServlet, the programs prints out a null string (see the commented line //problem comes here in MyFilter). I verified and saw that init() method from servlet is executed before of doFilter().
So can anyone light me on this issue? Why the initParameter "name" is null, if it is set up to a value?
Thanks!
I think WebInitParam is defining init parameters for servlet and not for whole application context, so if you want acces parameters through ServletContext object, then define context params in you web.xml deployment descriptor.

In spring mvc 3, how to write a cookie while returning a ModelAndView?

My controller method is returning a ModelAndView, but there is also a requirement to write a cookie back to client. Is it possible to do it in Spring? Thanks.
If you add the response as parameter to your handler method (see flexible signatures of #RequestMapping annotated methods – same section for 3.2.x, 4.0.x, 4.1.x, 4.3.x, 5.x.x), you may add the cookie to the response directly:
Kotlin
#RequestMapping(["/example"])
fun exampleHandler(response: HttpServletResponse): ModelAndView {
response.addCookie(Cookie("COOKIENAME", "The cookie's value"))
return ModelAndView("viewname")
}
Java
#RequestMapping("/example")
private ModelAndView exampleHandler(HttpServletResponse response) {
response.addCookie(new Cookie("COOKIENAME", "The cookie's value"));
return new ModelAndView("viewname");
}
Not as part of the ModelAndView, no, but you can add the cookie directly to the HttpServletResponse object that's passed in to your controller method.
You can write a HandlerInterceptor that will take all Cookie instances from your model and generate the appropriate cookie headers. This way you can keep your controllers clean and free from HttpServletResponse.
#Component
public class ModelCookieInterceptor extends HandlerInterceptorAdapter {
#Override
public void postHandle(HttpServletRequest req, HttpServletResponse res, Object handler, ModelAndView modelAndView) throws Exception {
if (modelAndView != null) {
for (Object value : modelAndView.getModel().values()) {
if (value instanceof Cookie)
res.addCookie((Cookie) value);
}
}
}
}
NB . Don't forget to register the interceptor either with <mvc:interceptors> (XML config) or WebMvcConfigurer.addInterceptors() (Java config).
RustyX's solution in Java 8:
#Component
public class ModelCookieInterceptor extends HandlerInterceptorAdapter {
#Override
public void postHandle(HttpServletRequest req, HttpServletResponse res, Object handler, ModelAndView modelAndView) throws Exception{
if (modelAndView != null) {
modelAndView.getModel().values().stream()
.filter(c -> c instanceof Cookie)
.map(c -> (Cookie) c)
.forEach(res::addCookie);
}
}
}

Resources