2012-10-22 9 views
9

Gibt es einen Bereich wie JSF @ViewScoped in Spring 3.0? Ich habe eine Anwendung mit JSF + Spring, wo Backing-Beans von Spring verwaltet werden. Ich habe im Frühjahr keinen Bereich wie JSF gesehen. Ich sah den Blog Porting JSF 2.0’s ViewScope to Spring 3.0, aber es hat nicht für mich funktioniert.JSF View scope in Spring

Hier ist mein Versuch, auf dem benutzerdefinierten Frühling -umfang:

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

Dieser Beitrag von mir kann helfen: http://StackOverflow.com/q/12884822/1055089 – Vrushank

+0

Ja, aber die Implementierung funktioniert nicht in meinem Code – khan

+0

können Sie bitte den Code eingeben ?? Ich habe das gleiche in meiner App verwendet und es hat funktioniert. Ich benutze JSF2 + Spring 3 auch ... – Vrushank

Antwort

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

Ich habe so etwas wie dies ohne Spring Portierungs Bohne. Es funktioniert für mich.

@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

Das ist eine reine JSF-Lösung. Es funktioniert gut, aber es fehlen die Funktionen von Spring. Zum Beispiel erlaubt es keine aspektorientierte Programmierung. –

+0

Ich bin nicht sicher über 'Spring AOP'. Weil ich das damals gemäß meiner Anforderung getestet habe. Aber ich hatte 'Spring core', was perfekt für mich funktionierte. – SRy

+0

Ah, ich verstehe. Sehr wahrscheinlich haben Sie Ihre JSF-Lösung in eine Spring-Lösung konvertiert, indem Sie den SpringBeanFacesELResolver zu faces.config hinzugefügt haben. Wenn ja, sollte AOP gut funktionieren. –

-2

Ich habe für beide Jsf 2.1 & Jsf 2.2 eine Arbeit um für die Jsf Ansicht Bohnenspeicherverlust Problem versucht. Probieren Sie den Code im folgenden Link Memory leak with ViewScoped bean?. Während der Navigation zur nächsten Seite wird die View-Bean gelöscht.

+1

Worüber Sie sprechen, ist nicht JSF-spezifisch. Und völlig unabhängig von dieser Frage, BTW. –