Faces, Spring, Servlets and The Session Scope – Mea Cup O' Jo
Skip to content


Faces, Spring, Servlets and The Session Scope

In my current webapp I need to share my faces backing bean(s) between regular faces processing (embedded in XHTML) and servlet-based AJAX calls. Why? Here’s a scenario: I have a large form backed by session-scoped facelet bean. Now I’m going to make an AJAX call to update part of that form which means I need to access the information stored in the backing bean. But since my AJAX is calling a servlet I don’t have direct access to FacesContext and I also don’t want to dork with it while in servlet. Spring to the rescue!

Put your backing bean into Spring context

Before you can do that you need to modify web.xml and add these two listeners (you may already have ContextLoaderListener)



org.springframework.web.context.request.RequestContextListener




org.springframework.web.context.ContextLoaderListener


And this to the faces-config.xml


com.sun.facelets.FaceletViewHandler
org.springframework.web.jsf.el.SpringBeanFacesELResolver

Now, automagically you will have ability in your XHTML to refer to the beans in Spring context simply by bean’s id, e.g. #{mySpringBean.foo}
But wait there’s more! Simply remove the backing bean in question form faces-config.xml (managed-bean) and declare it in the Spring context (e.g. applicationContext.xml) instead.


    

Now – there are couple of caveats. First of all notice that scope=session attribute. It is only available in Spring v.2 +. Second thing: <aop:scoped-proxy /> tag. You need that if you are autowiring your bean as a property to some other beans in the context. If you don’t do that, then since your session does not yet exists at the context loading time your startup process will fail with an ugly message and recommendation to use “scoped-proxy”.
Another “gotcha” as I found out – if you define any propertes with the bean declaration these will be null when you’ll attempt to use your bean. That, I guess makes sence since the properties are wired in at the startup, however your actual bean is created by CGLIB proxy at run time, and (is this a bug?) these are not repopulated from the context.

Accessing backing bean from servlet

The easiest way is to declare your servlet in Spring context as well, You can do it by making your servlet implement org.springframework.web.HttpRequestHandler. Then in your web.xml you configure it like so

	
		Handles AJAX requests
		AjaxHandler
		AjaxHandler
		
			org.springframework.web.context.support.HttpRequestHandlerServlet
		2
	
	
		AjaxHandler
		/ajax
	

Then in the Java code of your servlet simply autowire the backing bean. When you are ready to use it it’ll be properly injected

public class AjaxHandler implements HttpRequestHandler {
	@Autowired
	private UserSupportBean userSupportBean;
	@Override
	public void handleRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
				this.userSupportBean.setFoo(request.getProperty("FOO"));
	}
}

Posted in Java, Web stuff.


0 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.



Some HTML is OK

or, reply to this post via trackback.