Results 1 to 7 of 7

Thread: Session-management design-issue with my JSF/Spring application

  1. #1
    Join Date
    Nov 2007
    Posts
    177

    Default 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. #2
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,625

    Default

    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.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  3. #3
    Join Date
    Nov 2007
    Posts
    177

    Default

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

  4. #4
    Join Date
    Nov 2007
    Posts
    177

    Default

    Quote 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.

  5. #5
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,625

    Default

    Don't use a transient field that is never serialized/deserialized.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  6. #6
    Join Date
    Nov 2007
    Posts
    177

    Default

    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.

  7. #7
    Join Date
    Nov 2007
    Posts
    177

    Default

    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;
        }
    
    }

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •