2

I had a request-scoped JSF 1.2 managed bean that I needed to refactor to session-scoped bean because it is doing some expensive operation on @PostConstruct and that is being called multiple times which really needs to be done only once. The side effect of changing the scope to session is now I cannot inject FacesContext anymore in faces-config.xml by doing like this:

<managed-property>
 <property-name>context</property-name>
 <value>#{facesContext}</value>
</managed-property>

where I have

setContext(FacesContext ctx) {}

in my managed bean.

In one of my action methods I need the context to access ExternalContext/HttpServletResponse. I don't want to invoke

FacesContext.getCurrentInstance();

inside my action method but somehow call setContext(FacesContext ctx) externally to allow isolation of context injection for ease of mocked testing. I tried putting the setContext() inside the @PostConstruct only to realize later that FacesContext is a per request thing and my ExternalContext was reset to null once a new request is being submitted.

How could I call setContext(FacesContext ctx) auto-magically every time I hit a new request although the managed bean itself is session scoped?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
phewataal
  • 1,107
  • 4
  • 12
  • 23

1 Answers1

1

Keep your request scoped bean and inject the session scoped bean in it instead so that you can pass the FacesContext to it in the @PostConstruct of the request scoped bean. In the session scoped bean, perform lazy loading/executing.

E.g.

public class RequestBean {

    private FacesContext context; // Managed property.
    private SessionBean sessionBean; // Managed property.

    @PostConstruct
    public void init() {
        sessionBean.init(context);
    }

    // ...
}

and

public class SessionBean {

    private SomeObject initializedObject;

    public void init(FacesContext context) {
        if (initializedObject != null) {
            return;
        }

        initializedObject = initializeObject(context);
    }

    // ...
}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Yes, I ended up creating two separate managed beans like you suggested to solve the problem. I was struggling earlier because I tried to fit into a single managed bean. – phewataal Jun 25 '12 at 19:58
  • You're welcome. The only way to inject `FacesContext` in a session scoped bean is using CDI, but that's only available when you're using Java EE 6. As you're using the ancient JSF 1.2, that's clearly completely out of the question. – BalusC Jun 25 '12 at 20:05
  • How would you do it with CDI? – Roger Keays Oct 25 '12 at 06:08
  • ... do you mean via @Provides? – Roger Keays Oct 25 '12 at 06:20