I've seen many answers on this topic but still can't find a clean solution.
public class ProcessScheduler {
static {
Timer timer=new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
LogProcessorServiceImpl.processPageRequestsLogs();
}
}, 0, 120);
}
}
How do I make this execute and be happy with quality solution? My application is based on Spring (unfortunately) and I know I can reference this class in one of my controllers and it'd probably work. But that's silly. There just must be a better way. I'm on Tomcat with no EJB support, so timer annotation will not work for me. Also, I don't want to do CRON. I want to schedule all my maintenance tasks within this scheduler class.
Servlet classes can be loaded via web.xml (1). Can we do something similar on non-servlet classes?
Instead of writing this in a static block, I would prefer to
write an event listener that extends javax.servlet.ServletContextListener
move that piece of code into the contextInitialized method
define the contextDestroyed method to cancel the timer
configure the class as <listener> in web.xml file for my application.
<listener>
<listener-class>
com.vikdor.webapps.ProcessSchedulerListener
</listener-class>
</listener>
Related
I am trying Vaadin. I developed two classes. In both classes, I extended its servlet with the code similar to below:
#VaadinServletConfiguration(productionMode = false, ui = <CurrentClassName>.class)
public static class Servlet extends VaadinServlet {
}
When I run the second class, it always show UI from first one. I tried restarting Tomcat but its still the same.
e.g.
http://localhost:8080/hms/servlet/com.test.ui.TestClass2$Servlet
I tried creating a new class and when I run that, even that shows the UI of first one.
Please help to understand and resolve the issue.
Thank you!
Create class MyUIProvider that extends basic UIProvider and override getUIClass method.
For instance:
public class MyUIProvider extends UIProvider
{
#Override
public Class extends UI> getUIClass(UIClassSelectionEvent event)
{
// imlement UI class choosing logic here
return MyUI.class;
}
Than add init-param to your VaadinServlet in web.xml:
...
<servlet>
<servlet-name>VAADIN</servlet-name>
<servlet-class>com.vaadin.server.VaadinServlet</servlet-class>
<init-param>
<param-name>UIProvider</param-name>
<param-value>your.package.MyUIProvider</param-value>
<description>Your custom UIProvider</description>
</init-param>
</servlet>
...
[New to Spring]
There is a service that is Spring enabled and does some stuff. When this service starts up, it loads the Spring Application context and everyone is happy.
Now, I need to create a library that will be used by the above mentioned service and I want to Springify this library package as well. But then, when/how does this library's application context get initialized? Am stumped!
I assume many people must have done this. What is the best practice?
I was thinking, may be a static block in the library's entry point interface is the right place to initialize the application context? (so, it gets init only once)
Is that the right approach? Is it even going to work or am missing I something? Appreciate your help.
You can give as many applicatoin context xml files as you want, If you are using the library in a web application,
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:context1.xml
classpath:context2.xml
...
</param-value>
</context-param>
basically you need to provide the relative path classpath:<relativepathofcontextfile>.
If it is inside a jar file and your jar is in classpath the above one works.
If it is for standalone, You can use ClassPathXmlApplicationContext.
public class SomeClass {
private static final ApplicationContext ac=
new ClassPathXmlApplicationContext("classpath:context1.xml");
public static void main(String[] args) {
MyIntf bean= (MyIntf) ac.getBean("myBean");
bean.myMethod();
}
}
No, with using static block you are enforcing Spring context to load disregard the fact that it might be loaded yet in another classloader. So the good approach would be to provide some factory method to get business objects, which will track if the context is loaded yet and create one if necessary. Or use pre-existing context.
Also it might be a good idea to review Service Locator pattern and http://docs.oracle.com/javase/1.4.2/docs/guide/jar/jar.html#Service%20Provider
I have a Spring web application with two contexts: one (applicationContext) built by ContextLoaderListener and a second (webContext) built by DispatcherServlet.
Within the applicationContext is a bean (org.springframework.security.authentication.DefaultAuthenticationEventPublisher) that fires spring context events.
But the receiver for the event is defined in the webContext. And that receiver did not get the event. (If put the receiver for test purpose in the applicationContext then it get the event, but I can not do this, because I need the webContexts for its functionality.)
So my question is, how to bridges the events from the applicationContext to webContext?
I had the same problem, solved mine by moving the beans creating the event to web-context. However you can solve your problem by manually wiring your event listener, something like this (this code is not compiled therefore it is untested):
#Component
public class BeanInWebContext implements ApplicationListener<SomeEvent> {
#Autowired
private ApplicationContext webContext;
#PostConstruct
public void registerAsListener() {
// get parent context
AbstractApplicationContext appContext = (AbstractApplicationContext) webContext.getParent();
// register self as a listener, this method is in AbstractApplicationContext
appContext.addApplicationListener(this);
}
#Override
public void onApplicationEvent(SomeEvent event) {
}
}
I think the actual answer is that you may want to configure your app differently (so that you only have one context)
I think in your web.xml you need to do something like this :
<servlet>
<servlet-name>example</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/META-INF/applicationSpringConfig.xml
</param-value>
</init-param>
</servlet>
But to answer the deeper question. Someone else points out that you can use includes in your spring file (indeed in the above you can have more than one springconfig specified in your dispatcher servlet).
But when you include other context files you do not share instances of beans, only definitions.
Modularising Spring applications has been the only real downside of spring in comparison with EJB etc. That led spring into using OSGi.
And the answer to your underlying question of how to share spring context, officially you share spring bean instances between contexts using OSGi (spring dm)
Try moving the event publisher to the web context file, where it should have visibility over the whole application context. A similar issue occurs when configuring method security in the parent application context. The parent application context (loaded by ContextLoaderListener) isn't aware of the child (web) context.
You can also use a single application context for the entire application if you don't really need the parent-child relationship between the two. Often it just gets in the way and it is easier if all beans were defined in the same space.
As stated in documentation for the spring framework the simple ApplicationEvent mechanism is only designed to be used within the same application context, I am not aware that it is possible to propagate events to child contexts.
If you need a more advanced solution you might look into using a more enhanced solution like Java Message Service or Spring Integration.
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#context-functionality-events
We can use the import tag to import/bridge the 2 different contexts created in a way the visibility of the events/beans are available and shared.
<import resource="applicationContext_name.xml"/>
In this import the context xml which is configured to be created from ContextLoaderListener in the context xml of the DispatcherServlet.
This question already has an answer here:
Using special auto start servlet to initialize on startup and share application data
(1 answer)
Closed 7 years ago.
I would like to perform some action as soon as my application (Enterprise Application with Business Logic, EJB, and a Client, Web) is deployed.
For example I would like to make some entity in a persistent state, or otherwise create a file.
How can I do that?
Thanks.
Configure SerlvetContextListener and override contextInitilized()
in your web application description , web.xml
<web-app ...>
<listener>
<listener-class>com.someCompany.AppNameServletContextListener</listener-class>
</listener>
</web-app
package com.someCompany;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class AppNameServletContextListener implements ServletContextListener{
#Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("ServletContextListener destroyed");
}
#Override
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("ServletContextListener started");
// do the things here
}
}
The "default" way is to have a servlet with an init() method. Then in the servlet-descriptor you mark this servlet as load-on-startup 1:
Example:
<servlet-name>Seam Resource Servlet</servlet-name>
<servlet-class>org.jboss.seam.servlet.SeamResourceServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
As soon as the servlet is deployed (which happens after the EJBs are deployed), that init() method is called and you can execute the task you want.
With present web application in your ear, the easiest and simplest would be to use ServletContextListener, otherwise in EJB 3.1 you could use automatic timers or startup singleton session beans.
This question already has an answer here:
Using special auto start servlet to initialize on startup and share application data
(1 answer)
Closed 7 years ago.
The reason I'm asking this is that I want to write code that initializes the application once it starts and cleans up later on.
I dont want to use a servlet init() method since it is per servlet.
There is no main() method in Servlet.
If
The reason I'm asking this is that I want to write code that initializes the application once it starts and cleans up later on.
You can use ServletContextListener implemented
public class MyServletContext implements ServletContextListener{
ServletContext context;
public void contextInitialized(ServletContextEvent contextEvent) {
System.out.println("Context Created");
}
public void contextDestroyed(ServletContextEvent contextEvent) {
System.out.println("Context Destroyed");
}
}
web.xml
<listener>
<listener-class>
com.yourpackage.MyServletContext
</listener-class>
</listener>
There is no main() method, because the components are managed and the container invokes other methods - like the init() on servlets and filters. The container itself is started through a main method, but even that's hidden from you.
For per-application and initialization you can use a ServletContextListener
You have to map it in web.xml using <listener><listener-class>...</listener-class></listener>. In contextInitialized(..) and contextDestroyed(..) you can do initialization and cleanup respectively.