Search code examples
jsfseamconversation-scope

Seam @Scope(ScopeType.CONVERSATION) behaves like request scoped


I am trying to implement a function where an h:commandButton component is used to produce a row of the h:dataTable with each button click. I'm testing this using a string list. When the page is first loaded, the function works fine, with the button click producing a row with value "New Item". however, when I click it the second time, the ArrayList from the ActionBean backbean seems to be reallocated. What am I doing wrong?

Action Bean:

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.ScopeType;

import jp.co.dir.bf.common.AppLogger;
import jp.co.dir.bf.front.common.BaseBean;

@Scope(ScopeType.CONVERSATION)
@Name("ActionBean")
public class ActionBean extends BaseBean {

    private AppLogger appLogger;
    private List<String> list  = new ArrayList<String>(); 
    public ActionBean() {
        
        appLogger = new AppLogger(Logger.getLogger(ActionBean.class));
    }
    public void init(){
        appLogger.showDebug("The Form is loaded");
                appLogger.showDebug("Initial Size: "+ list.size());

        
    }
    public AppLogger getAppLogger() {
        return appLogger;
    }
    public void setAppLogger(AppLogger appLogger) {
        this.appLogger = appLogger;
    }
    
    public List<String> getList(){
        return list;
    }
    
    public void addToList(){
        
        list.add(new String("New Item"));
               /////This is always printing 1 after each add.
        appLogger.showDebug("Item added: "+ list.size());
    }
    public void setList(List<String> list){
        this.list = list;
    }
}

The xhtml:

<h:commandButton value = "Add New" >
<p:ajax listener="#{ActionBean.addToList}" update="table"/>
</h:commandButton>
            

<h:dataTable id = "table" value ="#{ActionBean.list}" var = "item">
    <h:column>
    <h:outputText value ="#{item}"/>
    </h:column>             
</h:dataTable>

Solution

  • I've fixed the issue. It's the silliness on my part. I forgot to add the @Begin(join = true) annotation on init() so init is getting called on each load, instead of being called only once for every conversation. Hope somebody finds this helpful. The new Action Bean code is now:

    import java.util.ArrayList;
    import java.util.List;
    
    import org.apache.log4j.Logger;
    import org.jboss.seam.annotations.In;
    import org.jboss.seam.annotations.Name;
    import org.jboss.seam.annotations.Scope;
    import org.jboss.seam.ScopeType;
    
    import jp.co.dir.bf.common.AppLogger;
    import jp.co.dir.bf.front.common.BaseBean;
    
    @Scope(ScopeType.CONVERSATION)
    @Name("ActionBean")
    public class ActionBean extends BaseBean {
    
        private AppLogger appLogger;
        private List<String> list  = new ArrayList<String>(); 
        public ActionBean() {
            
            appLogger = new AppLogger(Logger.getLogger(ActionBean.class));
        }
    
        @Begin(join = true) ///this is the part that is updated
        public void init(){
            appLogger.showDebug("The Form is loaded");
                    appLogger.showDebug("Initial Size: "+ list.size());
    
            
        }
        public AppLogger getAppLogger() {
            return appLogger;
        }
        public void setAppLogger(AppLogger appLogger) {
            this.appLogger = appLogger;
        }
        
        public List<String> getList(){
            return list;
        }
        
        public void addToList(){
            
            list.add(new String("New Item"));
                   /////This is always printing 1 after each add.
            appLogger.showDebug("Item added: "+ list.size());
        }
        public void setList(List<String> list){
            this.list = list;
        }
    }