2012-10-22 3 views
9

Есть ли какой-либо объем, например, JSF @ViewScoped весной 3.0? У меня есть приложение, использующее JSF + Spring, где backs beans управляется Spring. Весной я не нашел такой возможности, как область видимости JSF. Я видел блог Porting JSF 2.0’s ViewScope to Spring 3.0, но это не сработало для меня.JSF View scope in Spring

Вот моя попытка пользовательского Spring рамки:

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

Этот пост может помочь: http://stackoverflow.com/q/12884822/1055089 – Vrushank

+0

Yea Но реализация не работает в моем коде – khan

+0

не могли бы вы разместить код? Я использовал то же самое в своем приложении, и это сработало. Я использую JSF2 + Spring 3, а также ... – Vrushank

ответ

1
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(); 
} 

} 
2
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; 
} 

} 
3

я сделал что-то вроде этого без Портирования боба до весны. Это работает для меня.

@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); 
     } 
} 
+0

Это чистое решение JSF. Он отлично работает, но ему не хватает функций Spring. Например, это не позволяет аспектно-ориентированное программирование. –

+0

Я не очень уверен в 'Spring AOP'. Безусловно, я тестировал это согласно моим требованиям в то время. Но у меня была «Весенняя яма», которая отлично работала для меня. – SRy

+0

А, я вижу. Скорее всего, вы преобразовали решение JSF в решение Spring, добавив SpringBeanFacesELResolver в faces.config. Если это так, АОП должна работать нормально. –

-2

Я попробовал работу вокруг для зрения боба проблемы утечки памяти Jsf как для JSF 2.1 & JSF 2.2. Попробуйте код в следующей ссылке Memory leak with ViewScoped bean?. Он очистит компонент вида во время сеанса, перейдя на следующую страницу.

+1

. О чем вы говорите, это не специфический JSF. И совершенно не связанный с этим вопросом, BTW. –