8

I have a very strange problem with a SessionScoped bean in a JSF 2.0 project. Using Netbeans 6.9.1, Glassfish 3 server and PrimeFaces 3 as the JSF component library.

Here is some code:

package com.hia.jsf;

import com.hia.netlabel.jpa.Genre;
import com.hia.netlabel.jpa.Label;
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;

@ManagedBean
@SessionScoped
public class LabelDetailJSF implements Serializable{

@ManagedProperty("#{genreLabelListJSF}")
private GenreLabelListJSF genreLabelListJSF;
private List<Genre> DetailLabelGenreList;
private Label DetailLabel;
/** Creates a new instance of LabelDetailJSF */
public LabelDetailJSF() {
}
@PostConstruct
public void init(){
           System.out.print("Running init LabelDetailJSF");
           if(genreLabelListJSF.getSelectedLabel()!=null)
           {
                System.out.print("genreLabelListJSF was not null");
                this.DetailLabelGenreList=genreLabelListJSF.getSelectedLabel().getGenreList();
                this.DetailLabel= (genreLabelListJSF.getSelectedLabel());
           }
           if(this.DetailLabelGenreList==null){
               System.out.println("Bloody thing became null");

           }
}






/**
 * @return the DetailLabel
 */
public Label getDetailLabel() {
    return DetailLabel;
}

/**
 * @param DetailLabel the DetailLabel to set
 */
public void setDetailLabel(Label DetailLabel) {
    System.out.println("Setting Detail Label For LabelDetailJSF to:"+DetailLabel.getLabelName());
    this.DetailLabel = DetailLabel;

}

/**
 * @return the DetailLabelGenreList
 */
public List<Genre> getDetailLabelGenreList() {
    System.out.println("There is:"+this.DetailLabelGenreList.size()+ " Genres available");
    return DetailLabelGenreList;
}

/**
 * @param DetailLabelGenreList the DetailLabelGenreList to set
 */
public void setDetailLabelGenreList(List<Genre> DetailLabelGenreList) {
    System.out.println("Setting the DetailLabelGenre List to have "+DetailLabelGenreList.size());
    this.DetailLabelGenreList = DetailLabelGenreList;
}

/**
 * @return the genreLabelListJSF
 */
public GenreLabelListJSF getGenreLabelListJSF() {
    return genreLabelListJSF;
}

/**
 * @param genreLabelListJSF the genreLabelListJSF to set
 */
public void setGenreLabelListJSF(GenreLabelListJSF genreLabelListJSF) {
    this.genreLabelListJSF = genreLabelListJSF;
}

}

So basically I have injected another sessionscoped bean called GenreLabelListJSF into the LabelDetailJSF. I want to display the DetailLabelGenreList inside a dataTable. Here is the XHTML snippet used to display the datatable

<p:dataTable  id="detailLabelGenreGrid" value="#    {labelDetailJSF.detailLabelGenreList}" var="genre"  paginator="true"  styleClass="text70" rows="2" >
                            <p:column  style="min-width:196px;">
                                 #{genre.genreName}
                            </p:column> 
             </p:dataTable>

When the page loads I initially get the table with some rows in. When I click on the paging buttons that is where the fun starts.

I checked the output from all the System.out statements and found the following when the page loads initially.

INFO: Running init LabelDetailJSF
INFO: genreLabelListJSF was not null
INFO: There is:29 Genres available
INFO: There is:29 Genres available
INFO: There is:29 Genres available
INFO: There is:29 Genres available
INFO: There is:29 Genres available
INFO: There is:29 Genres available

When I click on the page buttons of the datatable I get the following:

INFO: Running init LabelDetailJSF
INFO: Bloody thing became null
SEVERE: javax.el.ELException: /LabelDetail.xhtml @62,165 value="#    {labelDetailJSF.detailLabelGenreList}": java.lang.NullPointerException
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:107)
    at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:190)
    at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:178)
    at javax.faces.component.UIData.getValue(UIData.java:554)
    at org.primefaces.component.datatable.DataTable.getValue(DataTable.java:731)
    at javax.faces.component.UIData.getDataModel(UIData.java:1248)
    at javax.faces.component.UIData.setRowIndex(UIData.java:447)
    at javax.faces.component.UIData.visitTree(UIData.java:1184)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1457)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1457)
    at javax.faces.component.UIForm.visitTree(UIForm.java:333)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1457)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1457)
    at com.sun.faces.application.view.StateManagementStrategyImpl.restoreView(StateManagementStrategyImpl.java:223)
    at com.sun.faces.application.StateManagerImpl.restoreView(StateManagerImpl.java:177)
    at com.sun.faces.application.view.ViewHandlingStrategy.restoreView(ViewHandlingStrategy.java:131)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.restoreView(FaceletViewHandlingStrategy.java:430)
    at com.sun.faces.application.view.MultiViewHandler.restoreView(MultiViewHandler.java:143)
    at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:199)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:110)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:312)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215)
    at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:277)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
    at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
    at com.sun.grizzly.comet.CometEngine.executeServlet(CometEngine.java:473)
    at com.sun.grizzly.comet.CometEngine.handle(CometEngine.java:341)
    at com.sun.grizzly.comet.CometAsyncFilter.doFilter(CometAsyncFilter.java:84)
    at com.sun.grizzly.arp.DefaultAsyncExecutor.invokeFilters(DefaultAsyncExecutor.java:161)
    at com.sun.grizzly.arp.DefaultAsyncExecutor.interrupt(DefaultAsyncExecutor.java:137)
    at com.sun.grizzly.arp.AsyncProcessorTask.doTask(AsyncProcessorTask.java:88)
    at com.sun.grizzly.http.TaskBase.run(TaskBase.java:189)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
    at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.NullPointerException
    at com.hia.jsf.LabelDetailJSF.getDetailLabelGenreList(LabelDetailJSF.java:72)
    at sun.reflect.GeneratedMethodAccessor951.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at javax.el.BeanELResolver.getValue(BeanELResolver.java:302)
    at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:175)
    at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:72)
    at com.sun.el.parser.AstValue.getValue(AstValue.java:116)
    at com.sun.el.parser.AstValue.getValue(AstValue.java:163)
    at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:219)
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:102)
    ... 48 more

From what I can see it is almost like the bean looses scope and gets recreated all the time. Initially the values are there then when the paging starts the bean looses value. For example I noticed that the @ManagedProperty bean also becomes null when the paging starts. Which is kind of crazy as it is also a session scoped bean.

Still a new hand at JSF so I probably made some noob mistake. Must mention that I did initially create this as a ViewScoped bean by accident, and after changing the bean to SessionScoped I undeployed the application restarted Glassfish and build and deployed it again.

Any ideas?

BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
Namphibian
  • 11,288
  • 6
  • 43
  • 68

1 Answers1

20

You're using the wrong @SessionScoped annotation.

If you've registered the bean with the JSF @ManagedBean annotation, then you need to import the @SessionScoped from the JSF (javax.faces) package as follows:

import javax.faces.bean.SessionScoped;

When you incorrectly use a CDI scope on a JSF managed bean, then there is effectively no JSF scope for the JSF managed bean and it falls back to its default @RequestScoped, which creates a new instance in each HTTP request.

If you've registered the bean with the CDI @Named annotation, then you need to import the @SessionScoped from the CDI (javax.enterprise.context) package as follows:

import javax.enterprise.context.SessionScoped;

When you incorrectly use a JSF scope on a CDI managed bean, then there is effectively no CDI scope for the CDI managed bean and it falls back to its default @Dependent scope, which creates a new instance in each EL expression.

See also:

Community
  • 1
  • 1
BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
  • BalusC I have been reading your Blogs etc and answers but now I have to ask do you actually sleep? So what is the difference and when do I use which one? – Namphibian Feb 27 '12 at 18:50
  • Works perfectly. I knew I was making a complete noob mistake. Thanks BalusC. Hope to see a book on JSF by you soon. I will buy it! – Namphibian Feb 27 '12 at 18:59
  • Yes, I sleep so now and then. CDI is an annotation based dependency injection framework which can be used in combination with any other frameworks than only JSF. It's like as Spring back then in old J2EE ages. Mixing JSF and CDI annotations in one same project is however not always recommended. Use either JSF or CDI. So, use either JSF `@ManagedBean @SessionScoped` or CDI `@Names @SessionScoped`. CDI has imo however one major disadvantage in JSF webapps, it doesn't offer an annotation for the JSF "view scope" as available by `@ViewScoped`. – BalusC Feb 27 '12 at 18:59
  • Cool stuff. That is short and sweet how do I marked this item as closed? – Namphibian Feb 27 '12 at 19:07
  • Need to update this answer as @SessionScoped ....Deprecated ? – Joker Aug 26 '20 at 11:54
  • @Joker: That happens only if you're still using `@ManagedBean` in JSF 2.3 or newer. You'd need to migrate everything to CDI then. This is regardless of the scope being used. See also https://stackoverflow.com/q/4347374 – BalusC Aug 26 '20 at 13:37