I have an app built with Jersey.I need to do some initialization on startup of the webapp/war in the Tomcat 7 container by running an application specific login/code.
What is the best way to do this with Jersey ? I have used ContextListener with contextInitialized()before in a Servlet environment. I need to make sure the Jersey resources are loaded before I make this call.
Not sure what you mean by "Jersey resources are loaded before", but if you want to really plug in into Jersey init process.. Jersey has several "monitoring" plugin points (not widely advertised or documented) and what I'm going to describe is being called after initialization of AbstractResourceModel - so right after app startup.
Try this:
#Provider
public class Listener implements AbstractResourceModelListener {
#Override
public void onLoaded(AbstractResourceModelContext modelContext) {
System.out.println("##### resource model initiated");
}
}
It should happen only once per app lifecycle, I'm not very sure about reloading, but you don't need to bother by it if you are not using that feature (anyway, you should put some check there to avoid multiple invocation if could cause some issues).
For Jersey 2.x you can do the following:
#Provider
private static class MyFeature implements Feature {
#Override
public boolean configure(FeatureContext context) {
//code goes here
return true;
}
}
Related
Requirement
For Cloud, datastore needs to change namespace dynamically. (example store kind as per company Name)
Used Spring cloud DataRepository with Springboot for same
Issue
We need to declare spring.cloud.gcp.datastore.namespace in application.properties which is static.
Is there any way to change this dynamically with CRUDReposity of spring cloud
Thanks in advance
You can change anything you want in your application.properties at runtime using Spring Cloud Config.
Spring Cloud Config provides server-side and client-side support for externalized configuration in a distributed system. With the Config Server, you have a central place to manage external properties for applications across all environments. The concepts on both client and server map identically to the Spring Environment and PropertySource abstractions, so they fit very well with Spring applications but can be used with any application running in any language.
Just as a quick example on how you can use this , you should firstly add the dependency : eg gradlecompile group: 'org.springframework.cloud', name: 'spring-cloud-starter', version: '1.1.1.RELEASE', then you need to add the #RefreshScope on the desired configuration bean.
You will be able to view your current config at a certain endpoint, like "applicationConfig: [classpath:/application.properties]": {
"my.property": "value1",
etc
And then you can change the properties as you wish doing a POST request like :
curl -X POST http://localhost:8080 -d my.property=value2
There is also a nice article about dynamically reloading the properties in a Spring application here. It is nice because they actually display more ways that you can achieve that.
You can use DatastoreNamespaceProvider which can dynamically return needed namespace.
Was added in this PR PR
Also see this discussion here and this recommendation
#Component
#RequiredArgsConstructor
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public class HeaderValueProvider implements Supplier<String>, DatastoreNamespaceProvider {
private final HttpServletRequest httpServletRequest;
#Override
public String get() {
return httpServletRequest.getHeader("someHeader");
}
}
And this
#Component
public class UserContextProvider implements DatastoreNamespaceProvider, Consumer<UUID> {
private static final ThreadLocal<UUID> USER_CONTEXT = new ThreadLocal<>();
#Override
public String get() {
return ofNullable(USER_CONTEXT.get())
.map(UUID::toString)
.orElse(null);
}
#Override
public void accept(UUID uuid) {
USER_CONTEXT.set(uuid);
}
}
I have to create a class that implements ServletContextListener to add an event during the initialization or the shutdown of Tomcat. However, the class has to be located in a jar file inside WEB-INF/lib. After doing some readings, I found out that this is not possible, and the alternative is to use ServletContainerInitializer. However, only onStartup() method is available.
Is there any other alternatives where I can also add an event during the shutdown or destruction of the web application?
I am using Tomcat 8 and Java 8 btw.
Let your ServletContainerInitializer programmatically add a ServletContextListener which in turn does the desired job in its contextDestroyed().
servletContext.addListener(YourServletContextListener.class);
Not sure how you tested your code. But this the ServletContextListener works fine for me on Tomcat 8.5.5. Just try this code, no need to put this to separate JAR file.
#WebListener
public class AppContextListener implements ServletContextListener{
Logger log = LoggerFactory.getLogger(AppContextListener.class);
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
log.info("### Context is destroyed ###");
}
}
I need to get some configuration and connect to external resources/objects/systems somewhere and store it in application scope.
I can see two ways to setup my application:
Overriding the init() in the existing servlets and required code there and keeping all constructed objects inside that same servlet.
Having some kind of an initialisation servlet and using its init() to do the work. Then storing created objects in ServletContext to share it with my other servlets.
Which out of above is better approach? Is there any better way to share objects between servlets? Calling them directly from one another or so...?
None of both is the better approach. Servlets are intended to listen on HTTP events (HTTP requests), not on deployment events (startup/shutdown).
CDI/EJB unavailable? Use ServletContextListener
#WebListener
public class Config implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
// Do stuff during webapp's startup.
}
public void contextDestroyed(ServletContextEvent event) {
// Do stuff during webapp's shutdown.
}
}
If you're not on Servlet 3.0 yet and can't upgrade (it would be about time because Servlet 3.0 was introduced more than a decade ago), and thus can't use #WebListener annotation, then you need to manually register it in /WEB-INF/web.xml like below:
<listener>
<listener-class>com.example.Config</listener-class>
</listener>
To store and obtain objects in the application scope (so that all servlets can access them), use ServletContext#setAttribute() and #getAttribute().
Here's an example which lets the listener store itself in the application scope:
public void contextInitialized(ServletContextEvent event) {
event.getServletContext().setAttribute("config", this);
// ...
}
and then obtain it in a servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
Config config = (Config) getServletContext().getAttribute("config");
// ...
}
It's also available in JSP EL by ${config}. So you could make it a simple bean as well.
CDI available? Use #Observes on ApplicationScoped.class
import jakarta.enterprise.context.ApplicationScoped; // And thus NOT e.g. jakarta.faces.bean.ApplicationScoped
#ApplicationScoped
public class Config {
public void init(#Observes #Initialized(ApplicationScoped.class) ServletContext context) {
// Do stuff during webapp's startup.
}
public void destroy(#Observes #Destroyed(ApplicationScoped.class) ServletContext context) {
// Do stuff during webapp's shutdown.
}
}
This is available in a servlet via #Inject. Make it if necessary also #Named so it's available via #{config} in EL as well.
Noted should be that this is new since CDI 1.1. If you're still on CDI 1.0 and can't upgrade, then pick another approach.
In case you're curious how to install CDI on a non-JEE server such as Tomcat, head to: How to install and use CDI on Tomcat?
EJB available? Consider #Startup#Singleton
#Startup
#Singleton
public class Config {
#PostConstruct
public void init() {
// Do stuff during webapp's startup.
}
#PreDestroy
public void destroy() {
// Do stuff during webapp's shutdown.
}
}
This is available in a servlet via #EJB. The difference with other approaches is that it's by default transactional and in case of #Singleton also read/write locked. So if you would ever need to inject a random EJB (e.g. #Stateless) into a #WebListener or an #ApplicationScoped then you could basically as good merge both into a single #Startup #Singleton.
See also:
How to run a background task in a servlet based web application?
ServletContainerInitializer vs ServletContextListener
How do I force an application-scoped bean to instantiate at application startup?
I have an EJB (coded using Java EE 6 annotations) that is defined as follows:
#Stateless
#WebService
public class SecurityWebService {
public void registerUser(RegistrationRequest request) {
...
}
}
Note that this EJB is also exposed as a web service. However, I am running into an issue with the generated web service. The WSDL generated by my container (GlassFish) contains WS-Atomic Transaction policies because a stateless session bean by default is transactional (see details here). Unfortunately my .NET client is choking on the WSDL because it does not understand WS-AT policies.
So what I really want is a nice-clean web service that is not transactional, but the associated EJB should be transactional (it has to insert records in the database). How do I do this? The only approach I can think of is to create a "normal" web service that passes all its calls to an EJB like this - not elegant at all:
#WebService
public class SecurityWebService {
#Inject
private SecurityService securityService;
public void registerUser(RegistrationRequest request) {
securityService.registerUser(request);
}
}
#Stateless
public class SecurityService {
public void registerUser(RegistrationRequest request) {
...
}
}
Is there a better way?
Thanks.
Naresh
You can try annotating the method:
#TransactionAttribute(TransactionAttributeType.NEVER)
or
#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
Dunno if the web service will pick that up or not, but it's worth a shot.
Edit for comment:
Did you try REQUIRES_NEW? They may well not propagate back out to the web service.
Otherwise, yea, you'll be stuck facading the transactional part with the non-transactional web service.
I need to get some configuration and connect to external resources/objects/systems somewhere and store it in application scope.
I can see two ways to setup my application:
Overriding the init() in the existing servlets and required code there and keeping all constructed objects inside that same servlet.
Having some kind of an initialisation servlet and using its init() to do the work. Then storing created objects in ServletContext to share it with my other servlets.
Which out of above is better approach? Is there any better way to share objects between servlets? Calling them directly from one another or so...?
None of both is the better approach. Servlets are intended to listen on HTTP events (HTTP requests), not on deployment events (startup/shutdown).
CDI/EJB unavailable? Use ServletContextListener
#WebListener
public class Config implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
// Do stuff during webapp's startup.
}
public void contextDestroyed(ServletContextEvent event) {
// Do stuff during webapp's shutdown.
}
}
If you're not on Servlet 3.0 yet and can't upgrade (it would be about time because Servlet 3.0 was introduced more than a decade ago), and thus can't use #WebListener annotation, then you need to manually register it in /WEB-INF/web.xml like below:
<listener>
<listener-class>com.example.Config</listener-class>
</listener>
To store and obtain objects in the application scope (so that all servlets can access them), use ServletContext#setAttribute() and #getAttribute().
Here's an example which lets the listener store itself in the application scope:
public void contextInitialized(ServletContextEvent event) {
event.getServletContext().setAttribute("config", this);
// ...
}
and then obtain it in a servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
Config config = (Config) getServletContext().getAttribute("config");
// ...
}
It's also available in JSP EL by ${config}. So you could make it a simple bean as well.
CDI available? Use #Observes on ApplicationScoped.class
import jakarta.enterprise.context.ApplicationScoped; // And thus NOT e.g. jakarta.faces.bean.ApplicationScoped
#ApplicationScoped
public class Config {
public void init(#Observes #Initialized(ApplicationScoped.class) ServletContext context) {
// Do stuff during webapp's startup.
}
public void destroy(#Observes #Destroyed(ApplicationScoped.class) ServletContext context) {
// Do stuff during webapp's shutdown.
}
}
This is available in a servlet via #Inject. Make it if necessary also #Named so it's available via #{config} in EL as well.
Noted should be that this is new since CDI 1.1. If you're still on CDI 1.0 and can't upgrade, then pick another approach.
In case you're curious how to install CDI on a non-JEE server such as Tomcat, head to: How to install and use CDI on Tomcat?
EJB available? Consider #Startup#Singleton
#Startup
#Singleton
public class Config {
#PostConstruct
public void init() {
// Do stuff during webapp's startup.
}
#PreDestroy
public void destroy() {
// Do stuff during webapp's shutdown.
}
}
This is available in a servlet via #EJB. The difference with other approaches is that it's by default transactional and in case of #Singleton also read/write locked. So if you would ever need to inject a random EJB (e.g. #Stateless) into a #WebListener or an #ApplicationScoped then you could basically as good merge both into a single #Startup #Singleton.
See also:
How to run a background task in a servlet based web application?
ServletContainerInitializer vs ServletContextListener
How do I force an application-scoped bean to instantiate at application startup?