복붙노트

[SPRING] Spring의 JSF 뷰 범위

SPRING

Spring의 JSF 뷰 범위

스프링 3.0에서 JSF @ViewScoped와 같은 범위가 있습니까? JSF + Spring을 사용하는 애플리케이션은 Spring에 의해 backing beans가 관리되는 곳입니다. 스프링에서 JSF 뷰 범위와 같은 범위를 찾지 못했습니다. 블로그에서 JSF 2.0의 ViewScope를 Spring 3.0으로 이식하는 것을 보았지만 나에게 도움이되지 못했습니다.

다음은 커스텀 스프링 범위에 대한 나의 시도이다.

import java.util.Map;

import javax.faces.context.FacesContext;

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

/**
 * Implements the JSF View Scope for use by Spring. This class is registered as a Spring bean with the CustomScopeConfigurer.
*/
public class ViewScope implements Scope {

    public Object get(String name, ObjectFactory<?> objectFactory) {

        System.out.println("**************************************************");
        System.out.println("-------------------- Getting objects For View Scope ----------");
        System.out.println("**************************************************");
        if (FacesContext.getCurrentInstance().getViewRoot() != null) {
            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;
            }
        } else {
            return null;
        }
    }

    public Object remove(String name) {
        System.out.println("**************************************************");
        System.out.println("-------------------- View Scope object Removed ----------");
        System.out.println("**************************************************");

        if (FacesContext.getCurrentInstance().getViewRoot() != null) {
            return FacesContext.getCurrentInstance().getViewRoot().getViewMap().remove(name);
        } else {
            return null;
        }
    }

    public void registerDestructionCallback(String name, Runnable callback) {
        // Do nothing
    }

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

    public String getConversationId() {
        return null;
    }

}

application-context.xml :

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

해결법

  1. ==============================

    1.최근에이 문제를 해결할 maven artifact를 만들었습니다.

    최근에이 문제를 해결할 maven artifact를 만들었습니다.

    내 github javaplugs / spring-jsf 저장소를 참조하십시오.

  2. ==============================

    2.저는 Spring에 Porting Bean없이 이런 식으로했습니다. 그것은 나를 위해 일하고있다.

    저는 Spring에 Porting Bean없이 이런 식으로했습니다. 그것은 나를 위해 일하고있다.

    @ManagedBean(name="bean")
    @ViewScoped  // actual jsf viewscoped only with javax.faces.viewscoped import
    public class Bean implements
    Serializable {
    
    
    @ManagedProperty(value="#{appService}")   // Spring Manged Bean and singleton
    private transient AppService appService;
    
      // Getting AppService Object which is singleton in the application during deserialization 
     private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
              stream.defaultReadObject();
              FacesContext context = FacesContext.getCurrentInstance();
              appService = (AppService)context.getApplication()
                    .evaluateExpressionGet(context, "#{appService}", AppService.class);
           }
    }
    
  3. ==============================

    3.

    public class ViewScopeCallbackRegistrer implements ViewMapListener {
    
    @SuppressWarnings("unchecked")
    @Override
    public void processEvent(SystemEvent event) throws AbortProcessingException {
    if (event instanceof PostConstructViewMapEvent) {
    PostConstructViewMapEvent viewMapEvent = (PostConstructViewMapEvent) event;
    UIViewRoot viewRoot = (UIViewRoot) viewMapEvent.getComponent();
    viewRoot.getViewMap().put(ViewScope.VIEW_SCOPE_CALLBACKS,
    new HashMap<String, Runnable>());
    } else if (event instanceof PreDestroyViewMapEvent) {
    PreDestroyViewMapEvent viewMapEvent = (PreDestroyViewMapEvent) event;
    UIViewRoot viewRoot = (UIViewRoot) viewMapEvent.getComponent();
    Map<String, Runnable> callbacks = (Map<String, Runnable>) viewRoot
    .getViewMap().get(ViewScope.VIEW_SCOPE_CALLBACKS);
    if (callbacks != null) {
    for (Runnable c : callbacks.values()) {
    c.run();
    }
    callbacks.clear();
    }
    }
    }
    
    @Override
    public boolean isListenerForSource(Object source) {
    return source instanceof UIViewRoot;
    }
    
    }
    
  4. ==============================

    4.

    public class ViewScope implements Scope {
    
    public static final String VIEW_SCOPE_CALLBACKS = "viewScope.callbacks";
    
    @Override
    public synchronized Object get(String name, ObjectFactory<?> objectFactory) {
    Object instance = this.getViewMap().get(name);
    if(instance == null){
    instance = objectFactory.getObject();
    this.getViewMap().put(name, instance);
    }
    return instance;
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public Object remove(String name) {
    Object instance = this.getViewMap().remove(name);
    if(instance == null){
    Map<String, Runnable> callbacks = (Map<String, Runnable>) this.getViewMap().get(VIEW_SCOPE_CALLBACKS);
    if(callbacks != null)
    callbacks.remove(name);
    }
    return instance;
    }
    
    /**
    * Responsável por registrar uma chamada de destruição ao bean
    * que será armazenadano [b]viewMap[/b] da [b]ViewRoot[/b](nossa página que será mostrada)
    * @see #getViewMap()
    * @param name - nome do bean
    * @param runnable
    */  
    @SuppressWarnings("unchecked")
    @Override
    public void registerDestructionCallback(String name, Runnable runnable) {
    Map<String, Runnable> callbacks = (Map<String, Runnable>) this.getViewMap().get(VIEW_SCOPE_CALLBACKS);
    if(callbacks != null)
    callbacks.put(name, runnable);
    }
    
    @Override
    public Object resolveContextualObject(String key) {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    FacesRequestAttributes facesResquestAttributes = new FacesRequestAttributes(facesContext);
    return facesResquestAttributes.resolveReference(key);
    }
    
    @Override
    public String getConversationId() {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    FacesRequestAttributes facesResquestAttributes = new FacesRequestAttributes(facesContext);  
    return facesResquestAttributes.getSessionId() + "-" + facesContext.getViewRoot().getViewId();
    }
    
    private Map<String, Object> getViewMap(){
    return FacesContext.getCurrentInstance().getViewRoot().getViewMap();
    }
    
    }
    
  5. ==============================

    5.Jsf 2.1 및 Jsf 2.2 모두에 대한 Jsf 뷰 빈 메모리 누수 문제를 해결하기 위해 노력했습니다. ViewScoped 빈을 사용하여 메모리 누수 링크로 다음 코드를 시도해보십시오. 다음 페이지로 이동하는 동안 세션에서보기 빈을 지울 것입니다.

    Jsf 2.1 및 Jsf 2.2 모두에 대한 Jsf 뷰 빈 메모리 누수 문제를 해결하기 위해 노력했습니다. ViewScoped 빈을 사용하여 메모리 누수 링크로 다음 코드를 시도해보십시오. 다음 페이지로 이동하는 동안 세션에서보기 빈을 지울 것입니다.

  6. from https://stackoverflow.com/questions/13005421/jsf-view-scope-in-spring by cc-by-sa and MIT license