I currently have an EJB that has an # schedule that runs every 5 minutes, but I only run after the ejb initialized.
the question is whether you can make the timer starts running after deployment and do not wait until there is an invocation to the EJB for starting.
Here is my code:
#Remote(ServiceRemote.class)
#Stateless(mappedName = "ejb/ServiceEJBSL")
public class ServiceBean implements ServiceRemote {
#Schedule(second="*", minute="*/5", hour="*", dayOfWeek="0-6")
public void autmaticTimer() throws Exception, RemoteException{
System.out.println("do something");
}
}
I did this in glasfish server but it seems doesnt work the same way.
Thanks in advance.
You'll need GlassFish v3.+ because this feature was added in EJB 3.1
Automatic timers are created by the EJB container when an enterprise
bean that contains methods annotated with the #Schedule or
#Schedules annotations is deployed.
#Schedule(minute="*/5", hour="*")
public void automaticTimer() throws Exception, RemoteException{
System.out.println("do something");
}
Addition
Try to add
#Schedule(minute="*/5", hour="*", persistent=false)
Because persistent timers are not re-created if already existing when keepstate is set to true.
See
Automatic Timers
Related
My java web application that uses spring for dependency injection is packaged in an EAR and is deployed in Jboss 7, but has no EJB. The application is installed on two load balancing machines. I need to schedule a method to run daily, but that method can't run at the same time on both instances.
I tried to use Spring's Scheduling annotations, but the problem is that, as there is load balancing, the scheduled method runs twice (once in each cluster).
What is the best way to do this in Jboss 7? Can someone help me ?
The method to be scheduled looks like the one below.
public synchronized void processor() {
LOGGER.info("start");
//processing logic
LOGGER.info("the end");
}
Thanks a lot!!!
Well, considering the requirements: two or more apps and they need to be synchronized, you need either #Singleton or #Stateless EJB, described here.
Invoking it via the timer service, then it needs to be an EJB with #Timer on some method and if you use #Scheduled or such on a method, then it will invoke that method
On this case a Singleton is recommended, otherwise, you might end up with multiple instances of the same timer running.
Example
#Example
private void init()
{
ScheduleExpression Expression = new ScheduleExpression();
#This means twice per hour {0,2,4, ... 22} ~ since it ends on 23h:
expression.second(0).minute(0).hour(*/2).month(*).dayOfWeek(*);
stopTimer();
Timer timer = service.createCalendarTimer(exp);
}
Any other suggestion seems to add too much complexity.
I am following the Using the Timer Service tutorial to build a simple scheduled execution. Trying the automatic approach and using WildFly 8.1.0 Final for it.
Session Bean
#Singleton
#Startup
public class HelloJob {
private static final Logger logger = Logger.getLogger(HelloJob.class);
public HelloJob() {
logger.error(">>> Hello Job Created.");
}
#Schedule(second="*")
public void sayHello() {
logger.error(">>> Server Hello!");
}
}
On deploy the class is properly instantiated printing the >>> Hello Job Created. message, but the method sayHello() is never called.
According to the tutorial the #Schedule(second="*") means that it should execute every second.
Setting an attribute to an asterisk symbol (*) represents all
allowable values for the attribute.
Also only stateful session beans are not allowed for timers, and I am using a singleton, which is also used in the example.
The timer service of the enterprise bean container enables you to
schedule timed notifications for all types of enterprise beans except
for stateful session beans.
Use #Schedule(second="*", minute="*", hour="*").
the default values for hour and minute are "0" which can be quite irritating and effectively forces you to set these.
I'm doing my graduation project, and have run into a dilemma here.
I need to make an application that generates PDFs and emails them to people on a schedule defined by data in the database.
I'm working for a company with this project, and we already have a GlassFish application server that we use. It would be best if the entire solution is delivered in one package, as it is now.
Client with webstart
Web Application etc. is all in one package
My new service needs to run on a separate thread, generate reports and send them out on emails. From what I can read on the web, running your own threads in an application server as GlassFish is highly discouraged, so it sounds like I need to make my own separate application.
Can this really be? What are your comments, and what are the best practices for this?
#Schedule
If you are using Ejb 3.1 (glassfish 3.x), you may use the #Schedule annotation to have the container invoke a method in a specified interval or at a given calendar time. Allowing you to avoid handling threads in your own code
Read about ejb 3.1 timer
#Stateless
public class LabbBean {
#EJB
WorkerEjb workerEjb;
#Schedule(second="*/5", minute="*",hour="*", persistent=false)
public void myMethod() {
for (all jobs found in db){
workerEjb.workerMethod(job);
}
}
}
#Stateless
public class WorkerEjb {
#Asynchronous
public void workerMethod(job) {
//Send emails
}
}
If you wanted to do the work in separate threads, the #Schedule annotated method could call a worker-ejb with the worker-method annotated as #Asynchronous
#Timeout
I just realised you wanted the schedule to be initiated from the database. An option the would be to initiate a bunch of timers programmatically using a #Singleton ejb with #Startup annotation. The timeout annotated method would be called in separate threads if some timers run out at the same time.
#Singleton
#Startup
public class LabbBean {
#Resource
protected TimerService timerService;
#PostConstruct
public void init() {
//Init your timers from the data in the database here
for (all your timers) {
TimerConfig config = new TimerConfig();
config.setInfo("timer1");
config.setPersistent(false);
ScheduleExpression schedule = new ScheduleExpression();
schedule.dayOfMonth(10);
schedule.minute(2);
timerService.createCalendarTimer(schedule, config);
}
}
//method called when timeout occurs
#Timeout
public void timeoutHandler(Timer timer) {
String name = timer.getInfo().toString();
System.out.println("Timer name=" + name);
}
}
I have webproject on Java EE 5 and Websphere 7.0
I need to create scheduler and start it after deploy application.
What I tried:
I create EJB with interface:
#Local
public interface ISchedulerBean {
public void executeTimer(Timer timer);
public void createTimer();
}
stateless session bean implements this interface. Method createTimer creates timer instance from TimerService. This part of code work fine.
Also I need to call method createTimer() after application deploy.
I tried:
Add listener servletContext:
public class SchedulerInitialiserContextListener implements ServletContextListener {
//service to lookup ejb
private WebServiceLocator webServiceLocator;
private SchedulerService schedulerService;
public SchedulerInitialiserContextListener() {
webServiceLocator = new WebServiceLocator();
schedulerService = webServiceLocator.getSchedulerService();
}
public void contextDestroyed(ServletContextEvent ctx) {
}
public void contextInitialized(ServletContextEvent ctx) {
schedulerService.createTimer();
}
}
create Servlet with 1 where inject SchedulerBean in init() method and call createTimer.
But this does not work, because at first webspere deploy web application, call listeners, initialize servlets, and only then deploy ejb.jar in which all ejb are located. I can see that in webshpere log file. So when I try get ejb throw #EJB annotation or lookup I get Exception, beacause ejb has not been found.
May be is other approach to start timer after deploy ejb module or change deploy order?
You can set the startup order of your modules.
Assuming you develop with Rational Application Developer do the following:
Right click your ear project and click Java EE -> Open WebSphere Application Server Deployment.
Look for the Application section, you will see all the modules and you can set the Start weight for each one.
Make sure your web project containing the Context Listener has the largest value an you should be fine.
This operation creates an ibmconfig directory under your ear project's META-INF, make sure you package it in your build process
This question already has answers here:
Eager / auto loading of EJB / load EJB on startup (on JBoss)
(2 answers)
Closed 6 years ago.
I'm looking for an entry point in an EJB deployed on JBoss.
Servlets have the load-on-startup tag to use in its web.xml.
I'm searching for similar init() functionality for an EJB.
That didn't exist for EJB until 3.1. With EJB 3.1 you can use a singleton bean to simulate that:
From Application Startup / Shutdown Callbacks:
#Startup
#Singleton
public class FooBean {
#PostConstruct
void atStartup() { ... }
#PreDestroy
void atShutdown() { ... }
}
Otherwise, you will need to rely on the good old trick to use a ServletContextInitializer.
There are some application-specific extension, e.g. lifecycle listener for Glassfish. Maybe there's such a thing for JBoss.
But if I were you I would try to rely on standard features as much as possible. The problem with non-standard extension is that you never know exactly what can be done or not, e.g. can you start transaction or not, etc.
This article describes seven different ways of invoking functionality at server startup. Not all will work with JBoss though.
Seven ways to get things started. Java EE Startup Classes with GlassFish and WebLogic
If you're targeting JBoss AS 5.1, and you don't mind using the JBoss EJB 3.0 Extensions, you can build a service bean to bootstrap your EJB. If your service implements an interface annotated with the #Management annotation and declares a method with the signature public void start() throws Exception, JBoss will call this method when it starts the service. You can then call a dedicated init() method on the EJB you want to initialize:
#Service
public class BeanLauncher implements BeanLauncherManagement
{
#EJB private SessionBeanLocal sessionBean;
#Override
public void start() throws Exception
{
sessionBean.init();
}
}
#Management
public interface BeanLauncherManagement
{
public void start() throws Exception;
}
More information on this, including additional life-cycle events, can be found here.
Managed Beans can be used to do some process at JBoss startup, you have to add entry of that managed bean in configuration file.
You should be able to add the following line to the top of the method you want to run at startup:
#Observer("org.jboss.seam.postInitialization")