2012-10-22 7 views
9

Esiste un ambito come JSF @ViewScoped in Spring 3.0? Ho un'applicazione che usa JSF + Spring dove i bean di supporto sono gestiti da Spring. In primavera non ho trovato alcun ambito come l'ambito wiew di JSF. Ho visto il blog Porting JSF 2.0’s ViewScope to Spring 3.0, ma non ha funzionato per me.JSF View scope in primavera

Ecco il mio tentativo sulla portata Primavera personalizzato:

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

Questo post può aiutare: http://stackoverflow.com/q/12884822/1055089 – Vrushank

+0

Sì, ma l'implementazione non funziona nel mio codice – khan

+0

potresti inserire il codice? Ho usato lo stesso nella mia app e ha funzionato. Sto usando anche JSF2 + Spring 3 ... – Vrushank

risposta

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

ho fatto qualcosa di simile, senza porting di fagioli alla primavera. Funziona per me.

@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

Questa è una pura soluzione JSF. Funziona bene, ma non ha le caratteristiche di Spring. Ad esempio, non consente la programmazione orientata all'aspetto. –

+0

Non sono molto sicuro di 'Spring AOP'. Però ho provato questo secondo il mio requisito in quel momento. Ma avevo "core di primavera" che funzionava perfettamente per me. – SRy

+0

Ah, capisco. Molto probabilmente hai convertito la tua soluzione JSF in una soluzione Spring aggiungendo SpringBeanFacesELResolver a faces.config. In tal caso, AOP dovrebbe funzionare correttamente. –

-2

ho cercato un lavoro in giro per la vista di fagioli problema di perdita di memoria Jsf sia per Jsf 2.1 & Jsf 2.2. Prova il codice nel seguente link Memory leak with ViewScoped bean?. Cancellerà il bean di visualizzazione in sessione mentre navighi alla pagina successiva.

+1

Di cosa si sta parlando non è specifico per JSF. E totalmente estraneo a questa domanda, BTW. –

4

Recentemente ho creato un artefatto maven che risolverà questo problema.

Vedere il mio repository di github javaplugs/spring-jsf.