Search code examples
javaspringspring-mvcspring-beansession-scope

How to create a Spring session scoped bean based on user properties


I've developed a Spring Web-MVC application. I have some offices in my project. Each user belongs to an office. user.getOfficeType() returns an integer representing the user's office type. If the office type is 1, the user belongs to Office1 and etc. However I want to inject the authenticated user's office into my service classes:

class MyService{
   @Autowired
   Office currentOffice;
   ...
}

I read the Spring docs. I need a session scoped bean to inject it into my service classes.

applicationContext.xml:

<mvc:annotation-driven />
<tx:annotation-driven transaction-manager="hibernateTransactionManager"/>
<context:annotation-config />
<context:component-scan base-package="com.package.controller" />
<context:component-scan base-package="com.package.service" />
...
<bean id="office" class="com.package.beans.Office" scope="session">
    <aop:scoped-proxy/>
</bean>

enter image description here

I have three implementations of the Office interface. Once a user requests a resource, I want to be aware of his Office. So I need to inject his session-scoped Office into my service classes. But I don't know how to instantiate it according to the user's office. please help!


Solution

  • I found a solution! I declared an OfficeContext that wraps the Office and also implements it.

    @Component
    @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
    public class OfficeContext implements InitializingBean, Office {
    
       private Office office;
    
       @Autowired
       private UserDao userDao;
    
       @Autowired
       private NoneOffice noneOffice;
       @Autowired
       private AllOffice allOffice;
       @Autowired
       private TariffOffice tariffOffice;
       @Autowired
       private ArzeshOffice arzeshOffice;
    
        public Office getOffice() {
           return this.office;
        }
    
       @Override
       public void afterPropertiesSet() throws Exception {
          Authentication auth = SecurityContextHolder.getContext().getAuthentication();
           if (auth.isAuthenticated()) {
               String name = auth.getName(); //get logged in username
               JUser user = userDao.findByUsername(name);
               if (user != null) {
                   this.office = noneOffice;
               } else {
                   OfficeType type = user.getOfficeType();
                   switch (type) {
                       case ALL:
                           this.office = allOffice;
                           break;
                       case TARIFF:
                           this.office = tariffOffice;
                           break;
                       case ARZESH:
                           this.office = arzeshOffice;
                           break;
                       default:
                           this.office = noneOffice;
                   }
               }
           } else {
               this.office = noneOffice;
           }
    
       }
    
       @Override
       public OfficeType getType() {
           return office.getType();
       }
    
       @Override
       public String getDisplayName() {
           return office.getDisplayName();
       }
    
    }
    

    and in my service classes I injected the OfficeContext.

    @Service
    public class UserService {
    
       @Autowired
       UserDao userDao;
    
       @Autowired
       OfficeContext office;
    
       public void persist(JUser user) {
           userDao.persist(user);
       }
    
       public void save(JUser user) {
           userDao.save(user);
       }
    
    
    }