Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting JSF ServletContext in non-request environment in a CDI bean

I am using TomEE+ 1.7.1. With JSF managed beans this code was working well:

@ManagedBean( eager = true )
@ApplicationScoped
public class AppBean {

    @PostConstruct
    public void init() {
        ServletContext sc = (ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext();
        if (GlobalSettings.TESTMODE) {
            sc.getSessionCookieConfig().setDomain("." + GlobalSettings.APP_DOMAIN_TEST);
        } else {
            sc.getSessionCookieConfig().setDomain("." + GlobalSettings.APP_DOMAIN);
        }
    }
}

The init function ran at application startup and ServletContext was available.

I read everywhere that it's time to migrate to CDI beans instead of JSF beans. So I wanted to change @ManagedBean( eager = true ) to @Named @Eager (@Eager is from Omnifaces). Init function is running at application startup, but there is no FacesContext so I can't get ServletContext.

General question: How to get ServletContext in a non-request environment in CDI beans? (ServletContext is not a 'per request' object, so it should exist before the first request.)

Specific question: how to set the domain for the session cookies dynamically from code but before the first request occurs?

like image 535
GregTom Avatar asked Nov 22 '25 01:11

GregTom


2 Answers

You should be using a ServletContextListener for the purpose of performing programmatic configuration on a servlet based application.

@WebListener
public class Config implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent event) {
        ServletContext servletContext = event.getServletContext(); 
        // ...
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        ServletContext servletContext = event.getServletContext(); 
        // ...
    }

}

A @WebListener is inherently also CDI managed and thus you can just use @Inject and friends in there.

An application scoped managed bean is intented for holding application scoped data/state which can be used/shared across requests/views/sessions.

like image 77
BalusC Avatar answered Nov 24 '25 14:11

BalusC


Per the CDI spec, you can @Inject the ServletContext into a CDI bean. Just be sure to do it in a @PostConstruct, as injected fields are available only after construction:

@Inject ServletContext extCtxt;

@PostConstruct
public void doSomething(){
  // do something with your injected field
}
like image 26
kolossus Avatar answered Nov 24 '25 13:11

kolossus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!