@Documented @Retention(value=RUNTIME) @Target(value=TYPE) public @interface Eager
The CDI annotation @
Eager
specifies that a scoped bean is to be eagerly instantiated.
JSF's own native managed beans are being deprecated in favor of CDI managed beans. One feature that those native JSF managed beans had that's not directly available for CDI managed beans is the ability to eagerly instantiate application scoped beans.
OmniFaces fills this void and even goes one step further by introducing the @Eager
annotation
that can be applied to @RequestScoped
, @ViewScoped
,
@SessionScoped
and @ApplicationScoped
beans. This causes these beans to be instantiated
automatically at the start of each such scope instead of on demand when a bean is first referenced.
In case of @RequestScoped
and @ViewScoped
beans instantiation happens per request URI / view
and an extra attribute is required for specifying this.
Currently supported scopes:
RequestScoped
ViewScoped
ViewScoped
SessionScoped
ApplicationScoped
E.g. The following bean will be instantiated during application's startup:
@Eager @ApplicationScoped public class MyEagerApplicationScopedBean { @PostConstruct public void init() { System.out.println("Application scoped init!"); } }
Note: you can also use the stereotype @
Startup
for this instead.
The following bean will be instantiated whenever a session is created:
@Eager @SessionScoped public class MyEagerSessionScopedBean implements Serializable { private static final long serialVersionUID = 1L; @PostConstruct public void init() { System.out.println("Session scoped init!"); } }
The following bean will be instantiated whenever the URI /components/cache
(relatively to the
application root) is requested, i.e. when an app is deployed to /myapp
at localhost this will correspond to
a URL like http://localhost:8080/myapp/components/cache
:
@Eager(requestURI = "/components/cache") @RequestScoped public class MyEagerRequestScopedBean { @PostConstruct public void init() { System.out.println("/components/cache requested"); } }
FacesContext
in @PostConstruct
When using @Eager
or @Eager(requestURI)
, be aware that the FacesContext
is
not available in the @PostConstruct
. Reason is, the FacesServlet
isn't
invoked yet at the moment @Eager
bean is constructed. Only in @Eager(viewId)
, the
FacesContext
is available in the @PostConstruct
.
In case you need information from HttpServletRequest
, HttpSession
and/or ServletContext
, then
you can just @Inject
it right away. Also, all other CDI managed beans are available the usual way
via @Inject
, as long as they do also not depend on FacesContext
in their
@PostConstruct
.
In some (older) containers, most notably GlassFish 3, the CDI request scope is not available in a ServletRequestListener
(this is actually not spec complicant, as CDI demands this scope to be active then, but it is what it is).
Additionally in some containers, most notably GlassFish 3 again, instantiating session scoped beans from a HttpSessionListener
will corrupt "something" in the container. The instantiating of the beans will succeed, but if the session is later accessed an
exception like the following will be thrown:
java.lang.IllegalArgumentException: Should never reach here at org.apache.catalina.connector.SessionTracker.track(SessionTracker.java:168) at org.apache.catalina.connector.Request.doGetSession(Request.java:2939) at org.apache.catalina.connector.Request.getSession(Request.java:2583) at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:920) at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:259) at com.sun.faces.context.ExternalContextImpl.getSession(ExternalContextImpl.java:155) at javax.faces.context.ExternalContextWrapper.getSession(ExternalContextWrapper.java:396) at javax.faces.context.ExternalContextWrapper.getSession(ExternalContextWrapper.java:396) ...If any or both of those problems occur, a filter needs to be installed instead in
web.xml
as follows:
<filter> <filter-name>eagerBeansFilter</filter-name> <filter-class>org.omnifaces.cdi.eager.EagerBeansFilter</filter-class> </filter> <filter-mapping> <filter-name>eagerBeansFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
Note that the EagerBeansFilter
will automatically disable the EagerBeansWebListener
.
EagerExtension
,
EagerBeansRepository
,
EagerBeansPhaseListener
,
EagerBeansWebListener
,
EagerBeansFilter
Modifier and Type | Optional Element and Description |
---|---|
String |
requestURI
(Required when combined with
RequestScoped ) The URI (relative to the root of the web app) for which a
request scoped bean should be instantiated. |
String |
viewId
(Required when combined with
RequestScoped or ViewScoped ) The id of the view for which a request or view scoped bean
should be instantiated. |
public abstract String requestURI
RequestScoped
) The URI (relative to the root of the web app) for which a
request scoped bean should be instantiated. When this attribute is specified the bean will be instantiated very
early during request processing, namely just before the first Servlet Filter is invoked, but after a SAM.
JSF services will not be available (yet) when the bean is instantiated this way.
If both this attribute and viewId()
is specified, this attribute takes precedence for RequestScoped
.
This attribute can not be used for ViewScoped
beans.
public abstract String viewId
RequestScoped
or ViewScoped
) The id of the view for which a request or view scoped bean
should be instantiated. When this attribute is specified the bean will be instantiated during invocation of the
FacesServlet
, namely right after the RESTORE_VIEW phase (see PhaseId.RESTORE_VIEW
).
JSF services are available when the bean is instantiated this way.
If both this attribute and requestURI()
is specified and the scope is RequestScoped
, the
requestURI
attribute takes precedence. If the scope is ViewScoped
requestURI
is ignored and only
this attribute is considered.
Copyright © 2012–2018 OmniFaces. All rights reserved.