public class ReferenceDataTimer extends TimerTask
{
private static ReferenceDataTimer refDataTimerTask = new ReferenceDataTimer();
private Timer refDataTimer = null;
public void start()
{
refDataTimer = new Timer();
refDataTimer.schedule(refDataTimerTask, DELAY, refreshTime*PERIOD);
}
#Override
public void run()
{
// Get DB connection using
// InitialContext lookup
// using resource reference
=> This is where it is failing. lookup is not working from this run() method of timer task.
// Then load the data to cache
}
}
public class ReferenceDataManager implements ServletContextListener {
// Invoking ReferenceDataTimer -> start() method.
}
And Im getting JNDI lookup error while getting data source Connection from server context using a resource reference. Please note that look up IS WORKING if I don't use TimerTask.
javax.naming.ConfigurationException: A JNDI operation on a "java:" name cannot be completed because the server runtime is not able to associate the operation's thread with any J2EE application component. This condition can occur when the JNDI client using the "java:" name is not executed on the thread of a server application request. Make sure that a J2EE application does not execute JNDI operations on "java:" names within static code blocks or in threads created by that J2EE application. Such code does not necessarily run on the thread of a server application request and therefore is not supported by JNDI operations on "java:" names.
Can any one please suggest? If it is not possible to get resource (available in server context) with in java.util.Timer task run() method then please suggest an alternative.
I even tried with java.util.concurrent.ScheduledExecutorService -> scheduleAtFixedRate but in vain.
You should not use TimerTask in an EJB application as this will create and start a custom Thread which is not allowed in a Java EE environment.
Instead, use the TimerService. It is part of the Java EE standard.
http://docs.oracle.com/javaee/6/tutorial/doc/bnboy.html
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.
Is this code copmliant to Java EE spec and can be used?
#Stateless
public class SomeBean {
#Inject
protected TransactedRunner txRunner;
public void someFunc() {
txRuner.run(new Runnable(){
Connection c = ds.getConnection();
//do jdbc stuff or jpa stuff
//close everything etc.
});
}
}
#Stateless
public class TransactedRunner {
#TransactionAttribute(REQUIRES_NEW)
public void run(Runnable r) {
r.run();
}
}
In this case a new transaction should be started and every thing that will be done in runnable will be transacted. Is that right? Or there is some trick in which I should suffer from EE?
This should work as intended. But be aware, that multiple calls of txRunner.run during one service call might lead to inconsistent data if anything happens between or during those calls, like connection-timeout, transaction-timeout, or the node dies or something. And the calling transaction (if there is any) might not see the changes done during the call until it itself has been committed.
There is an annotation in JavaEE6 called #Asynchronous which is specifically for this purpose. Here is the official tutorial: http://docs.oracle.com/javaee/6/tutorial/doc/gkkqg.html
#Stateless
public class SomeBean {
#Inject
private SomeBean self;
public void someFunc() {
self.doSomething();
}
#TransactionAttribute(REQUIRES_NEW)
#Asynchronous
private void doSomething() {
Connection c = ds.getConnection();
//do jdbc stuff or jpa stuff
//close everything etc.
}
}
Also it's not allowed to create or manage Threads within a EJB Container. Check out: http://www.oracle.com/technetwork/java/restrictions-142267.html#threads
Why is thread creation and management disallowed?
The EJB specification assigns to the EJB container the responsibility for managing threads. Allowing enterprise bean instances to create and manage threads would interfere with the container's ability to control its components' lifecycle. Thread management is not a business function, it is an implementation detail, and is typically complicated and platform-specific. Letting the container manage threads relieves the enterprise bean developer of dealing with threading issues. Multithreaded applications are still possible, but control of multithreading is located in the container, not in the enterprise bean.
Method "run" will be executed in transaction, that's true. But it has nothing in common with threading or using executor. In your example, the calling thread will execute your "run" method. Runnable interface itself won't create a separate thread for you.
If you need this call to be executed by separate thread, you can use asynchronous calls, or, starting from EE7, a ManagedExecutorService is available:
http://docs.oracle.com/javaee/7/api/javax/enterprise/concurrent/ManagedExecutorService.html
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 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
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);
}
}