i am getting data from action class to servlet by adding data to session.whenever i am clicking the item in select list onchange event is fired that function is invoked the our servlet up to now OK,whenever we send second time request that servlet is not called why? and also comparsion is failed it will maintain previous values only.here i am sending request from ajax.pls can any one provide solution ?
AjaX code
function verify_details()
{
var resourceId=document.getElementById("res").value
var url="/EIS10/ResourceTest?resourceId="+resourceId;
ajax(url);
}
Action class Code:
listResource=taskService.getUserList(taskId);
System.out.println("The list Of Resources are::"+listResource);
HttpSession session=request.getSession();
session.setAttribute("listResource", listResource);
ServletCode
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
System.out.println("Servlet is Called...........");
String resourceId=request.getParameter("resourceId");
boolean t=false;
System.out.println("Your Clicked Id::"+resourceId);
HttpSession session=request.getSession();
List l=(List)session.getAttribute("listResource");
System.out.println("Resource List in Servlet:"+l);
if(l!=null)
{
System.out.println("The Size of List::"+l.size());
Iterator itr=l.iterator();
while(itr.hasNext())
{
String s=itr.next().toString();
System.out.println("Elements in List:"+s);
if(s.equals(resourceId))
t=true;
}
response.setContentType("text/html");
if (t) {
response.getWriter().write("Y");
} else {
response.getWriter().write("N");
}
}
}
}
It's probably because the browser returns the contents from its cache at the second request. See http://spacebug.com/solving_browser_caching_problem_of_ajax-html/ for a solution, or use an AJAX library (jQuery for example) which can handle this for you.
Besides, if you're using Struts, why do you use a bare servlet to handle your AJAX call? Why don't you use a Struts action?
Related
We are moving from struts 1.3 framework to spring mvc. In struts framework, we used forms which is of type ActionForm. And we maintain it in session scope. When we navigate through screens(A->B->C), we reset certain properties of form. If we navigate from screen A to B, we pass param x=1, and the same is populated in the form's property 'x'. But before navigating from B to C, we reset x=null, as the screen B doesn't pass the param x and we wouldn't want x to maintain the value collected from screen A.
In Struts, the reset method in the form is called automatically every time before populating parameter.In Spring,the model that we pass to the controller's method needs to be reset before it is populated from request parameters. Do we have anyway to implement similar to this in Spring MVC?
protected void processPopulate(HttpServletRequest request,
HttpServletResponse response, ActionForm form, ActionMapping mapping)
throws ServletException {
if (form == null) {
return;
}
// Populate the bean properties of this ActionForm instance
if (log.isDebugEnabled()) {
log.debug(" Populating bean properties from this request");
}
form.setServlet(this.servlet);
form.reset(mapping, request);
if (mapping.getMultipartClass() != null) {
request.setAttribute(Globals.MULTIPART_KEY,
mapping.getMultipartClass());
}
RequestUtils.populate(form, mapping.getPrefix(), mapping.getSuffix(),
request);
At last, i found the option to call my own reset method in the model before it gets populated with request values.
I extended ServletModelAttributeMethodProcessor and overriden the method bindRequestParameters where i called reset method on model and then routed to method in super class.
And more over, i registered my implementation class in RequestMappingHandlerAdapter as one of the argument resolver. I collected all the resolvers first, then added mine in the first place in order to avoid the existing resolver to be skipped for ModelAttribute processing.
public class ResetArgumentResolver extends ServletModelAttributeMethodProcessor {
#Autowired
RequestMappingHandlerAdapter requestMappingHandlerAdapter;
ResetArgumentResolver(boolean annotationNotRequired) {
super(annotationNotRequired);
}
ResetArgumentResolver(){
this(false);
}
#PostConstruct
public void afterPropertiesSet() {
List<HandlerMethodArgumentResolver> argumentResolvers = requestMappingHandlerAdapter.getArgumentResolvers();
List<HandlerMethodArgumentResolver> newArgResolvers = new ArrayList<>();
newArgResolvers.add(this);
newArgResolvers.addAll(argumentResolvers);
requestMappingHandlerAdapter.setArgumentResolvers(Collections.unmodifiableList(newArgResolvers));
}
#Override
protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest request) {
Object attribute = binder.getTarget();
if (xxxx.class.isAssignableFrom(attribute.getClass())) {
((xxxx) attribute).reset();
}
super.bindRequestParameters(binder,request);
}
}
I'm using an architetture that has: AJAX, Liferay 6.2, Spring 4.3.18.RELEASE;
From AJAX i make a call to the backend, that pass throu liferay and reach my controller;
Now, I want to generete an exception in the controller in order to reach the the failure of the ajax call; I've googled a lot but I wasn't able to find the solution.
my controller:
#Controller("movemementCon")
#RequestMapping("VIEW")
public class movemementCon {
#ResourceMapping("getDis")
#ResponseBody
public ResponseEntity<BenException> getImp(ResourceRequest request, ResourceResponse response, Model model) throws BenException{
return new ResponseEntity<BenException>(HttpStatus.NOT_ACCEPTABLE);
}
But when i reach the code in javascript (the AJAX call) it ignored definitively that I've throw an exception;
The desidered behaviur is that i force to go to the error statment in the AJAX call.
In web browser you can't catch java errors on client side, because client doesn't know anything about backend. You have to catch that error in spring controller method and then return ResponseEntity with some status, response body, custom response headers, so you can notify client that something went wrong and handle it correctly there.
#Controller("movemementCon")
#RequestMapping("VIEW")
public class movemementCon {
#ResourceMapping("getDis")
#ResponseBody
public ResponseEntity<SomeClass> getImp(ResourceRequest request, ResourceResponse response, Model model) {
try{
deleteFromDatabase(model);
} catch(BenException e) {
return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE);
}
return new ResponseEntity<>(HttpStatus.OK);
}
}
Then in your JS read the status and execute right action.
I am using Spring Session 1.2.0.RELEASE on a Spring Boot Project. This is packaged as a war and deployed on Tomcat 8.
I have followed Spring Session documentation and configured it properly. The problem is that the entry point to the application is a controller that sets some value on session but the SESSION cookie is not sent to the browser.
Debugging I see that:
org.springframework.session.web.http.CookieHttpSessionStrategy.onNewSession() tries to write the cookie:
this.cookieSerializer
.writeCookieValue(new CookieValue(request, response, cookieValue));
org.springframework.session.web.http.DefaultCookieSerializer.writeCookieValue() sets the cookie in the response:
response.addCookie(sessionCookie);
The cookie isn't actually written. The underlying response object is org.apache.catalina.core.ApplicationHttpResponse. Its addCookie() method is:
/**
* Disallow <code>addCookie()</code> calls on an included response.
* #param cookie The new cookie
*/
#Override
public void addCookie(Cookie cookie) {
if (!included)
((HttpServletResponse) getResponse()).addCookie(cookie);
}
The problem is that included attribute, which at some point is set true, preventing the cookie from being added.
This happens when the jsp (using tiles) is being serviced:
UPDATE:
This is the moment when the response is being marked as included (when standard.jsp tiles layout is inserting an attribute:
<tiles:insertAttribute name="header" ignore="false"/>
To work around this problem I ended up creating a filter to enforce the creation of the session.
As seen, the first call to the controller didn't add the cookie because during the Tiles-JSP rendering the response was already marked as included. What I do is forcing the creation of the session in the filter and redirecting asking the very same requestURI. This way, since the call doesn't involve a tiles rendering the cookie is created and can be used right away in the next calls.
#Bean
#ConditionalOnExpression("${sessionEnforcerFilter.enabled:true}")
public FilterRegistrationBean sessionEnforcerFilter(){
logger.info("Registering sessionEnforcerFilter");
FilterRegistrationBean frb = new FilterRegistrationBean();
frb.setName("sessionEnforcerFilter");
frb.setFilter(new SessionEnforcerFilter());
frb.setUrlPatterns(Arrays.asList(new String[]{"/*"}));
return frb;
}
public class SessionEnforcerFilter implements Filter{
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest)request;
HttpServletResponse httpServletResponse = (HttpServletResponse)response;
if(httpServletRequest.getSession(false)==null){
logger.debug("sessionEnforcerFilter.doFilter () - Session is null - forcing its creation");
httpServletRequest.getSession();
String requestURI = httpServletRequest.getRequestURI();
logger.debug("sessionEnforcerFilter.doFilter () - Repeating request [{}]", requestURI);
httpServletResponse.sendRedirect(requestURI);
}else{
chain.doFilter(httpServletRequest, response);
}
}
#Override
public void destroy() {}
}
summary
Hold breakPoint in SessionRepositoryResponseWrapper.onResponseCommitted().
Check that the response object inside the SessionRepositoryRequestWrapper is a non-wrapped response. (included = false)
If it is a wrapped response object, make sure that the sessionRepositoryFilter comes first.
================
Spring-session is already handling the problem when 'DispatcherType.INCLUDE (included = true)'.
SessionRepositoryResponseWrapper.onResponseCommitted() is trying to addCookie to the original response object.
The sessionRepositoryFilter must be in the first position to wrap the original applicationHttpResponse passed by tomcat.
Problem Situation
The SessionRepositoryRequestWrapper receives the wrapped response and holds it.
When executing doInclude() in the servlet container, find the original reponse and wrap it with ApplicationHttpResponse (included = true).
Then, SetResponse (new wrapping response) to the innermost wrapper.
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat.embed/tomcat-embed-core/8.0.24/org/apache/catalina/core/ApplicationDispatcher.java#ApplicationDispatcher.doInclude%28javax.servlet.ServletRequest%2Cjavax.servlet.ServletResponse%29
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat.embed/tomcat-embed-core/8.0.24/org/apache/catalina/core/ApplicationDispatcher.java#ApplicationDispatcher.wrapResponse%28org.apache.catalina.core.ApplicationDispatcher.State%29
Spring-session does an addCookie on the response (expecting the original response) stored in SessionRepositoryResponseWrapper.onResponseCommitted(), but it can not because it is set to 'included = true'.
I would like to block the access of some page even if the user knows the url of some pages.
For example, /localhost:8080/user/home.xhtml (need to do the login first) if not logged then redirect to /index.xhtml.
How do that in JSF ? I read in the Google that's needed a filter, but I don't know how to do that.
You need to implement the javax.servlet.Filter class, do the desired job in doFilter() method and map it on an URL pattern covering the restricted pages, /user/* maybe? Inside the doFilter() you should check the presence of the logged-in user in the session somehow. Further you also need to take JSF ajax and resource requests into account. JSF ajax requests require a special XML response to let JavaScript perform a redirect. JSF resource requests need to be skipped otherwise your login page won't have any CSS/JS/images anymore.
Assuming that you've a /login.xhtml page which stores the logged-in user in a JSF managed bean via externalContext.getSessionMap().put("user", user), then you could get it via session.getAttribute("user") the usual way like below:
#WebFilter("/user/*")
public class AuthorizationFilter implements Filter {
private static final String AJAX_REDIRECT_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<partial-response><redirect url=\"%s\"></redirect></partial-response>";
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
String loginURL = request.getContextPath() + "/login.xhtml";
boolean loggedIn = (session != null) && (session.getAttribute("user") != null);
boolean loginRequest = request.getRequestURI().equals(loginURL);
boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER + "/");
boolean ajaxRequest = "partial/ajax".equals(request.getHeader("Faces-Request"));
if (loggedIn || loginRequest || resourceRequest) {
if (!resourceRequest) { // Prevent browser from caching restricted resources. See also https://stackoverflow.com/q/4194207/157882
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.
}
chain.doFilter(request, response); // So, just continue request.
}
else if (ajaxRequest) {
response.setContentType("text/xml");
response.setCharacterEncoding("UTF-8");
response.getWriter().printf(AJAX_REDIRECT_XML, loginURL); // So, return special XML response instructing JSF ajax to send a redirect.
}
else {
response.sendRedirect(loginURL); // So, just perform standard synchronous redirect.
}
}
// You need to override init() and destroy() as well, but they can be kept empty.
}
Additionally, the filter also disabled browser cache on secured page, so the browser back button won't show up them anymore.
In case you happen to use JSF utility library OmniFaces, above code could be reduced as below:
#WebFilter("/user/*")
public class AuthorizationFilter extends HttpFilter {
#Override
public void doFilter(HttpServletRequest request, HttpServletResponse response, HttpSession session, FilterChain chain) throws ServletException, IOException {
String loginURL = request.getContextPath() + "/login.xhtml";
boolean loggedIn = (session != null) && (session.getAttribute("user") != null);
boolean loginRequest = request.getRequestURI().equals(loginURL);
boolean resourceRequest = Servlets.isFacesResourceRequest(request);
if (loggedIn || loginRequest || resourceRequest) {
if (!resourceRequest) { // Prevent browser from caching restricted resources. See also https://stackoverflow.com/q/4194207/157882
Servlets.setNoCacheHeaders(response);
}
chain.doFilter(request, response); // So, just continue request.
}
else {
Servlets.facesRedirect(request, response, loginURL);
}
}
}
See also:
Our Servlet Filters wiki page
How to handle authentication/authorization with users in a database?
Using JSF 2.0 / Facelets, is there a way to attach a global listener to all AJAX calls?
Avoid back button on JSF web application
JSF: How control access and rights in JSF?
While it's of course legitimate to use a simple Servlet filter, there are alternatives like
Spring Security
Java EE Security
Apache Shiro
I have one requirement to fulfill.
Actually when ever user Login into my application , i will save the logged in user name in session attribute like .
session.setAttribute("LOGIN_USER", userName);
So that, if user tries to access my method links directly with out coming from Login page i can check in controller method whether this session has the specific attributive value as below and i can restrict user to access that page and redirect him to login page.
if(request.getSession(false).getAttribute("LOGIN_USER")==null)
//redirect to login page
Now,my requirement is if i have 50 methods in controller i can't add this condition in each method.I think there is a way we can add some sort of filters or any method in controller class like ex #preExecuteMethod to first execute this method and proceed for the actual call if success.
Yes, you can use a HandlerInterceptor for this. See the docs here and here.
Interceptor is the solution. It has methods preHandler which will be called before each request. You can hook into each HTTPServletRequest object and do the nnecessary stuff.
here is a sample code:
#Component
public class AuthCodeInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
// set few parameters to handle ajax request from different host
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
response.addHeader("Access-Control-Max-Age", "1000");
response.addHeader("Access-Control-Allow-Headers", "Content-Type");
response.addHeader("Cache-Control", "private");
String reqUri = request.getRequestURI();
String serviceName = reqUri.substring(reqUri.lastIndexOf("/") + 1,
reqUri.length());
if(request.getSession(false).getAttribute("LOGIN_USER")==null) {
//redirect to login page
}
return super.preHandle(request, response, handler);
}
#Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
}
}
Maybe you could use an AOP #Before aspect giving the pointcut to the methods in your handler class ? See the reference here or you could create a normal filter via the delegatingFilterProxy explained here . I think overall #skaffman gives a better idea .