Announcement Announcement Module
Collapse
No announcement yet.
Session-management design-issue with my JSF/Spring application Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Session-management design-issue with my JSF/Spring application

    Hello,

    I have a session-scoped spring bean that uses a singleton-scoped spring service bean in my application.

    The problem is when a user close his/her browser and reopens it: the session-scoped bean is correctly deserialized but the dependency (the spring service bean) is null, resulting in a NullPointerException when the dependency is used...

    Can anyone please provide design advice on how to prevent this?

    Regards,

    J.

  • #2
    In general you shouldn't be doing something like this you can end up with multiple instances of the singleton (try deserializing and serializing a singleton and you will have 2 instances).

    In general you want to use a lazy proxy of some kind to retrieve/use the singleton from the context.

    Comment


    • #3
      Thanks Marten,
      I think I found some relevant documentation here:
      LazyInitTargetSource
      for those interested in this topic.

      Comment


      • #4
        Originally posted by Marten Deinum View Post
        In general you shouldn't be doing something like this you can end up with multiple instances of the singleton (try deserializing and serializing a singleton and you will have 2 instances).

        In general you want to use a lazy proxy of some kind to retrieve/use the singleton from the context.
        Hi Marten,

        I changed my config to this:
        Code:
        	<bean id="mainService" class="com.jeanbaptistemartin.service.MainServiceImpl" lazy-init="true"/>
        	
        	<bean id="service" class="org.springframework.aop.framework.ProxyFactoryBean">
        		<property name="targetSource">
        			<bean class="org.springframework.aop.target.LazyInitTargetSource">
        				<property name="targetBeanName">
        					<idref local="mainService" />
        				</property>
        			</bean>
        		</property>
        	</bean>
        Code:
        private transient MainService mainService;
        
            public SuggestionOeuvreView() {
                log.debug("SuggestionOeuvreView()");
            }
        
            @Autowired
            public SuggestionOeuvreView(MainService mainService) {
                log.debug("SuggestionOeuvreView(MainService mainService)");
                this.mainService = mainService;
                this.sculpturesNonVisitees = recupererSculpturesNonVisitees();
            }

        I still get the same NPE...

        Any other idea?

        J.

        Comment


        • #5
          Don't use a transient field that is never serialized/deserialized.

          Comment


          • #6
            Marten,
            The trouble is that despite the lazy-init, it still attempts to serialize my MainService bean...
            I am not sure what I got wrong.
            Julien.

            Comment


            • #7
              Here is also the code for my session-scoped bean:

              Code:
              package com.jeanbaptistemartin.view;
              
              import java.io.Serializable;
              import java.util.LinkedList;
              import java.util.List;
              
              import javax.faces.event.ActionEvent;
              
              import org.apache.log4j.Logger;
              import org.springframework.beans.factory.annotation.Autowired;
              import org.springframework.context.annotation.Scope;
              import org.springframework.stereotype.Component;
              
              import com.jeanbaptistemartin.domain.Sculpture;
              import com.jeanbaptistemartin.service.MainService;
              
              @Component("suggestionOeuvreView")
              @Scope("session")
              public class SuggestionOeuvreView implements Serializable {
              
              	private static final long serialVersionUID = 1L;
              	private static transient Logger log = Logger.getLogger("com.jeanbaptistemartin.view");
                  private final static int NB_SCULPTURES_SUGGEREES = 4;
                  private LinkedList<Integer> sculpturesNonVisitees;
                  private List<Sculpture> sculpturesSuggerees;
                  private MainService mainService;
                  private boolean enabled = true;
              
                  public SuggestionOeuvreView() {
                      log.debug("SuggestionOeuvreView()");
                  }
              
                  @Autowired
                  public SuggestionOeuvreView(MainService mainService) {
                      log.debug("SuggestionOeuvreView(MainService mainService)");
                      this.mainService = mainService;
                      this.sculpturesNonVisitees = recupererSculpturesNonVisitees();
                  }
              
                  @Autowired
                  public void setMainService(MainService mainService) {
                      this.mainService = mainService;
                  }
              
                  public Sculpture suggererSculpture() {
                      log.debug("suggererSculpture");
                      return _suggererSculpture();
                  }
              
                  private Sculpture _suggererSculpture() {
                      log.debug("_suggererSculpture");
                      log.debug("Etat de la liste: " + this.sculpturesNonVisitees);
                      if (!this.sculpturesNonVisitees.isEmpty() && this.sculpturesNonVisitees.peek() != null) {
                          Integer idSculptureSuggeree = this.sculpturesNonVisitees.pollFirst();
                          this.sculpturesNonVisitees.addLast(idSculptureSuggeree);
                          log.debug("jbmService: " + mainService);
                          return mainService.findByID(idSculptureSuggeree);//NPE HERE!!
                      } else {
                          log.error("Probleme dans _suggererSculpture");
                          return null;//todo
                      }
                  }
              
                  public List<Sculpture> suggererSculptures() {
                      log.debug("suggererSculptures");
                      return _suggererSculptures();
                  }
              
                  private List<Sculpture> _suggererSculptures() {
                      log.debug("_suggererSculptures");
                      if (!this.sculpturesNonVisitees.isEmpty() && this.sculpturesNonVisitees.peek() != null) {
                          if (this.sculpturesNonVisitees.size() > NB_SCULPTURES_SUGGEREES) {
                              return mainService.findByIDs(this.sculpturesNonVisitees.subList(0, NB_SCULPTURES_SUGGEREES));//TODO: est null quand la session existe déjà!
                          } else {
                              return mainService.findByIDs(this.sculpturesNonVisitees.subList(0, this.sculpturesNonVisitees.size()));
                          }
                      } else {
                          log.error("Probleme dans _suggererSculptures");
                          return null;//todo
                      }
                  }
              
                  public void enable(ActionEvent evt) {
                      log.debug("enable");
                      this.enabled = true;
                  }
              
                  public void disable(ActionEvent evt) {
                      log.debug("disable");
                      this.enabled = false;
                  }
              
                  public Sculpture sculpturePrecedente() {
                      log.debug("sculpturePrecedente");
                      return _sculpturePrecedente();
              
                  }
              
                  private Sculpture _sculpturePrecedente() {
                      log.debug("_sculpturePrecedente");
                      this.enabled = false;
                      if (!this.sculpturesNonVisitees.isEmpty() && this.sculpturesNonVisitees.peek() != null) {
                          Integer idSculpturePrecedente = this.sculpturesNonVisitees.pollLast();
                          this.sculpturesNonVisitees.addFirst(idSculpturePrecedente);
                          return mainService.findByID(idSculpturePrecedente);
                      } else {
                          return null;
                      }
              
                  }
              
                  public Sculpture sculptureSuivante() {
                      log.debug("sculptureSuivante");
                      return _sculptureSuivante();
                  }
              
                  private Sculpture _sculptureSuivante() {
                      log.debug("_sculpturePrecedente");
                      this.enabled = false;
                      if (!this.sculpturesNonVisitees.isEmpty() && this.sculpturesNonVisitees.peek() != null) {
                          Integer idSculptureSuivante = this.sculpturesNonVisitees.pollFirst();
                          this.sculpturesNonVisitees.addLast(idSculptureSuivante);
                          return mainService.findByID(idSculptureSuivante);
                      } else {
                          return null;
                      }
              
                  }
              
                  public LinkedList<Integer> recupererSculpturesNonVisitees() {
                      log.debug("recupererSculpturesNonVisitees() ");
                      return mainService.findAllSculptureIDs();
                  }
              
                  public synchronized void enleverSculptureDeListeNonVisitees(Integer sculptureId) {
                      log.debug("enleverSculptureDeListeNonVisitees");
                      this.sculpturesNonVisitees.remove(sculptureId);
                  }
              
                  public boolean isEnabled() {
                      log.debug("isEnabled");
                      return this.enabled;
                  }
              
                  public void setEnabled(boolean enabled) {
                      log.debug("setEnabled");
                      this.enabled = enabled;
                  }
              
                  public void setSculpturesNonVisitees(LinkedList<Integer> sculpturesNonVisitees) {
                      log.debug("setSculpturesNonVisitees");
                      this.sculpturesNonVisitees = sculpturesNonVisitees;
                  }
              
                  public LinkedList<Integer> getSculpturesNonVisitees() {
                      log.debug("getSculpturesNonVisitees");
                      return sculpturesNonVisitees;
                  }
              
                  public List<Sculpture> getSculpturesSuggerees() {
                      log.debug("getSculpturesSuggerees");
                      return sculpturesSuggerees;
                  }
              
                  public void setSculpturesSuggerees(List<Sculpture> sculpturesSuggerees) {
                      log.debug("setSculpturesSuggereess");
                      this.sculpturesSuggerees = sculpturesSuggerees;
                  }
              
              }

              Comment

              Working...
              X