Porting JSF 2.0’s ViewScope to Spring 3.0

If you are using JSF&Spring and decided upgrading to JSF 2.0, one thing you would probably like to have is the JSF 2.0’s built-in viewscope. Core Spring doesn’t provide this scope as it is more specific to JSF. No worries, using Spring’s custom scope feature it is straightforward to port JSF 2.0’s viewscope as a Spring bean scope.

package org.primefaces.spring.scope;

import java.util.Map;

import javax.faces.context.FacesContext;

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;

public class ViewScope implements Scope {

	public Object get(String name, ObjectFactory objectFactory) {
		Map<String,Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap();

		if(viewMap.containsKey(name)) {
			return viewMap.get(name);
		} else {
			Object object = objectFactory.getObject();
			viewMap.put(name, object);

			return object;
		}
	}

	public Object remove(String name) {
		return FacesContext.getCurrentInstance().getViewRoot().getViewMap().remove(name);
	}

	public String getConversationId() {
		return null;
	}

	public void registerDestructionCallback(String name, Runnable callback) {
		//Not supported
	}

	public Object resolveContextualObject(String key) {
		return null;
	}
}

And register this scope in Spring configuration;

<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
        <property name="scopes">
            <map>
                <entry key="view">
                    <bean class="org.primefaces.spring.scope.ViewScope"/>
                </entry>
            </map>
        </property>
    </bean>

That’s it, now you can use ViewScope for JSF beans that are managed by Spring. As an example to test, assume there’s a simple counter page, each click increments the counter, as long as you stay on the same page, counter state is preserved but when you leave the page the counter is destroyed. If you access counter page again, counter will be reset.

package org.primefaces.spring.view;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("view")
public class CounterBean {

	private int counter = 0;

	public int getCounter() {
		return counter;
	}
	public void setCounter(int counter) {
		this.counter = counter;
	}

	public void increment() {
		counter++;
	}
}
<h:form>
	<h:outputText id="counter" value="#{counterBean.counter}" />

	<p:commandButton value="Count" actionListener="#{counterBean.increment}" update="counter"/>
</h:form>

By making JSF2’s ViewScope as an available scope to your Spring powered JSF backing beans, you can still take advantage of Spring Container and at the same time have this very handy scope. Similary FlashScope can be ported as well.

About these ads

7 Responses to Porting JSF 2.0’s ViewScope to Spring 3.0

  1. rainwebs says:

    Cool. Will you implement a complete implementation for the community?

  2. Hi Rainer,

    Do you mean implementation of flash scope?

  3. Turjakas says:

    You did not implement support for destruction callbacks, which in my opinion is quite important to handle the lifecycle of the Spring beans properly.

    I’ve implemented a similar Spring integration to JSF 2.0 ViewScope and I also implemented a proof-of-concept support for destruction callbacks by storing the callbacks in a map, which uses a combination of session ID and JSF view ID (filename) as the map key. This is needed to uniquely identify the view to run the correct destruction callbacks. I’m just wondering whether there is a better way to implement destruction callback support.

    Then I register the Spring scope implementation as a listener to PreDestroyViewMapEvent system event and get the session and view ID from FacesContext as the event gets fired. The only weird thing seems to be related to page reloads, which trigger creation of new JSF view scope instance, but it does not fire the PreDestroyViewMapEvent, so this might cause some sort of memory leaks because of callbacks getting stored in the map. Any subsequent POST request will cause the event to be fired, however.

    I’d also like to see an implementation of Flash scope with ideas of supporting destruction callbacks for it.

    In addition to that, have you thought about implementing support for custom conversation/flow scope that could be controlled in some easy and clean way by the application?

  4. rainwebs says:

    I did not have a look at all the JSF 2 details. But, it seems to me that there’s more to implement to have full support for all JSF 2 features in Spring. Maybe you have time to complete what you already started ;-).

  5. Time? That is something I don’t have :) But yes, why not.

  6. John says:

    Looks like great info)))) Add to bookmarks. Thanks.

Follow

Get every new post delivered to your Inbox.

Join 108 other followers

%d bloggers like this: