4

I'm experimenting with session-scoped beans in Spring 3. I have the following bean definition:

<bean id="userInfo" class="net.sandbox.sessionbeans.UserInfo" scope="session" />

Here is net.sandbox.controllers.RegistrationController, a controller class that needs access to this bean. I've taken out the imports for brevity's sake.

@Controller
@RequestMapping("/register")
public class RegistrationController {
    private UserInfo userInfo;   // This should reference the session-scoped bean

    @RequestMapping(method = RequestMethod.GET)
    public String showRegForm(Model model) {
        RegistrationForm regForm = new RegistrationForm();
        model.addAttribute("regform", regForm);
        return "regform";
    }

    @RequestMapping(method = RequestMethod.POST)
    public String validateForm(@Valid RegistrationForm regForm, BindingResult result, Model model) {
        if (result.hasErrors()) {
            return "regform";
        }

        userInfo.setUserName(regForm.getFirstName());
        model.addAttribute("regform", regForm);
        return "regsuccess";
    }
}

Is there a way to automatically tie the session-scoped bean I defined to the member variable private UserInfo userInfo in RegistrationController?

Pieter
  • 31,619
  • 76
  • 167
  • 242

4 Answers4

8

Yes - see section 3.4.5.4 of the Spring manual, "Scoped beans as dependencies".

Briefly, you can ask Spring to wrap your session-scoped bean in a singleton proxy, which looks up the correct session when you invoke a method on the scoped bean. This is called a "scoped proxy", and uses the <aop:scoped-proxy> config macro. You can then inject the reference as you would any other (e.g. <property>, or @Autowired). See the above link for details.

skaffman
  • 398,947
  • 96
  • 818
  • 769
  • 2
    I tried applying this technique. I put `` inside the bean definition and I `@Autowired`'d `private UserInfo userInfo`. It seems to work, but for some reason the bean's setter function isn't executed properly... http://i.imgur.com/zkxVA.png – Pieter May 08 '11 at 16:02
  • @Pieter Any progress on the above ?, i am facing the same issue – Sudarshan Sep 03 '12 at 12:38
  • @Sudarshan I made this site as part of a short-term school project a while ago and I'm no longer working on it. Sorry! Good luck finding a solution though. – Pieter Sep 03 '12 at 16:08
1

By default, Spring creates a proxy by implementing an interface at run-time. So, the only methods available on the proxy are those defined in any interfaces UserInfo implements (if any). You may have to create a suitable interface that includes the setUserName() method.

Alternatively, you will need to force a CGI based proxy (the proxy is a sub-class of your class created at run-time so it doesn't need an interface). Specify:

<bean id="userInfo" class="net.sandbox.sessionbeans.UserInfo" scope="session" >
   <aop:scoped-proxy proxy-target-class="true"/>
</bean>
takrl
  • 6,356
  • 3
  • 60
  • 69
Paul
  • 11
  • 1
0

If you don't like XML, you can also use ObjectFactory<T> like this :

@RestController
public class MyController {
    private final ObjectFactory<MySessionScopedComponent> OFSession;

    @Autowired
    public MyController(ObjectFactory<MySessionScopedComponent> OFSession) {
        this.OFSession = OFSession;
    }

    @RequestMapping(path = "/path", method = RequestMethod.GET)
    public String myMethod () {
        MySessionScopedComponent sessionBean = OFSession.getObject();
        // Do some stuff
        return bean.myValue();
    }
}

Note: Tested with Spring Boot 1.5.6 (Spring 4.3)

gokan
  • 1,028
  • 1
  • 14
  • 30
0

About this comment:

I tried applying this technique. I put inside the bean definition and I @Autowired'd private UserInfo userInfo. It seems to work, but for some reason the bean's setter function isn't executed properly... i.imgur.com/zkxVA.png – Pieter 1 hour ago

If you use interface-based proxies, the setter method is not available on the Proxy unless the interface has the setter method.

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • 1
    Interface-based proxies? I'm new to Spring, Java web development and design patterns, so I'm afraid that I don't know what you're describing. I only know that I want to access and update the 'userInfo` bean inside that controller class. My apologies if that's less than helpful. :) – Pieter May 08 '11 at 18:15