I was trying to migrate from payara/micro:4.181 to payara/micro:5.2022.3 and I noticed that the initialization method with observer [@initialized(ApplicationScoped.class) ServletContext init] is not invoked inside Jar files.
public void init(@Observes @Initialized(ApplicationScoped.class) ServletContext init)
It is invoked correctly when using payara/micro:4.181 though.
To reproduce the described behaviour:
- download the attached reproduce_observer_issue.zip from github_link_to_illustration_files
- unzip the files into "current_dir" the unzipped files contains a Dockerfile with following content:
#FROM payara/micro:5.2022.3
FROM payara/micro:4.181
COPY app.war $DEPLOY_DIR
uncomment the line corresponding to the version of payara/micro you want to run the app with.
- Run the following docker commands to deploy the app :
- docker build -t repissue:v1 .
- docker run repissue:v1
- If you check the path "current_dir\sources\libs\lib\src\main\java\mylib\Library.java" you can see that it contains two init methods, however when deploying on payara/micro:5.2022.3 init(@observes @initialized(ApplicationScoped.class) ServletContext init) won't be invoked (check logs)
package mylib;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Initialized;
import javax.enterprise.event.Observes;
import javax.servlet.ServletContext;
@ApplicationScoped
public class Library {
public boolean someLibraryMethod() {
return true;
}
public void init(@Observes @Initialized(ApplicationScoped.class) Object init) {
System.out.println(" ### log-1 mylib.Library.init(java.lang.Object) called ###");
}
public void init(@Observes @Initialized(ApplicationScoped.class) ServletContext init) {
System.out.println(" ### log-2 mylib.Library.init(javax.servlet.ServletContext) invoked ###");
}
}
Thanks in advance for any eventual reply/hint
I think there is a misunderstanding about what to expect from
@Observes @Initialized(ApplicationScoped.class). The JakartaEE specs (8) say:And "context" here is meant in the sense of CDI context, which
ServletContextis definitely not.Also I found no documentation whatsoever about what the type of the event message will be. Hence this is totally implementation specific and there should be made no assumptions about it (if you want to keep your code portable).
If your
Libraryobject received that event twice (once withObjectand once withServletContext) in Payara 4, then this can be considered a mistake (not to say bug) of that platform.I'd recommend to either implement a
javax.servlet.ServletContainerInitializeror ajavax.servlet.ServletContextListener, if you want to be notified about server startup and get hold ofServletContextduring that phase. The big advantage ofServletContextListener(over the other) is that you can easily interact with CDI beans (@ApplicationScopedor@Singleton).Here is an example:
(tested with your Docker project)
Hope this helps.
Update
I also found the following Gist which seems to be exactly what you want to achieve: https://gist.github.com/mojavelinux/637959
Note that here
@Initializedand@Destroyedare custom qualifiers and not the ones from packagejavax.enterprise.context.Additionally here is an updated version of that Gist using the qualifiers from
javax.enterprise.context: https://gist.github.com/nineninesevenfour/d9c643ff5a7f98302f89687720d0a138. With that your original code ofLibrarycan to stay unchanged.With the updated Gist however these two methods are called twice (once from Payara and once triggered from
ServletContextLifecycleNotifier: