I have created simple example with #Singleton, #Schedule and #Timeout annotations to try if they would solve my problem.
The scenario is this: EJB calls 'check' function every 5 secconds, and if certain conditions are met it will create single action timer that would invoke some long running process in asynchronous fashion. (it's sort of queue implementation type of thing). It then continues to check, but while the long running process is there it won't start another one.
Below is the code I came up with, but this solution does not work, because it looks like asynchronous call I'm making is in fact blocking my #Schedule method.
#Singleton
#Startup
public class GenerationQueue {
private Logger logger = Logger.getLogger(GenerationQueue.class.getName());
private List<String> queue = new ArrayList<String>();
private boolean available = true;
#Resource
TimerService timerService;
#Schedule(persistent=true, minute="*", second="*/5", hour="*")
public void checkQueueState() {
logger.log(Level.INFO,"Queue state check: "+available+" size: "+queue.size()+", "+new Date());
if (available) {
timerService.createSingleActionTimer(new Date(), new TimerConfig(null, false));
}
}
#Timeout
private void generateReport(Timer timer) {
logger.info("!!--timeout invoked here "+new Date());
available = false;
try {
Thread.sleep(1000*60*2); // something that lasts for a bit
} catch (Exception e) {}
available = true;
logger.info("New report generation complete");
}
What am I missing here or should I try different aproach? Any ideas most welcome :)
Testing with Glassfish 3.0.1 latest build - forgot to mention
The default #ConcurrencyManagement for singletons is ConcurrencyManagementType.CONTAINER with default #Lock of LockType.WRITE. Basically, that means every method (including generateReports) is effectively marked with the synchronized keyword, which means that checkQueueState will block while generateReport is running.
Consider using ConcurrencyManagement(ConcurrencyManagementType.BEAN) or #Lock(LockType.READ). If neither suggestion helps, I suspect you've found a Glassfish bug.
As an aside, you probably want persistent=false since you probably don't need to guarantee that the checkQueueState method fires every 5 seconds even when your server is offline. In other words, you probably don't need the container to fire "catch ups" when you bring your server back online.
Related
I need to schedule a task to run after 2 minutes. Then when the time is up I need to check if we are still ONLINE. If we are still online I simple don't do anything. If OFFLINE then I will do some work.
private synchronized void schedule(ConnectionObj connectionObj)
{
if(connectionObj.getState() == ONLINE)
{
// schedule timer
}
else
{
// cancel task.
}
}
This is the code I am considering:
#Async
private synchronized void task(ConnectionObj connectionObj)
{
try
{
Thread.sleep(2000); // short time for test
}
catch (InterruptedException e)
{
e.printStackTrace();
}
if(connectionObj.getState() == ONLINE)
{
// don't do anything
}
else
{
doWork();
}
}
For scheduling this task should I use #Async? I may still get many more calls to schedule while I am waiting inside the task() method.
Does SpringBoot have something like a thread that I create each time schedule() gets called so that this becomes easy?
I am looking for something similar to a postDelay() from Android: how to use postDelayed() correctly in android studio?
I'm not sure about an exclusively spring-boot solution, since it isn't something that I work with.
However, you can use ScheduledExecutorService, which is in the base Java environment. For your usage, it would look something like this:
#Async
private synchronized void task(ConnectionObj connectionObj)
{
Executors.newScheduledThreadPool(1).schedule(() -> {
if(connectionObj.getState() == ONLINE)
{
// don't do anything
}
else
{
doWork();
}
}, 2, TimeUnit.MINUTES);
}
I used lambda expressions, which are explained here.
Update
Seeing as how you need to schedule them "on-demand", #Scheduling won't help as you mentioned. I think the simplest solution is to go for something like #Leftist proposed.
Otherwise, as I mentioned in the comments, you can look at Spring Boot Quartz integration to create a job and schedule it with Quartz. It will then take care of running it after the two minute mark. It's just more code for almost the same result.
Original
For Spring Boot, you can use the built in Scheduling support. It will take care of running your code on time on a separate thread.
As the article states, you must enable scheduling with #EnableScheduling.
Then you annotate your method you want to run with #Scheduled(..) and you can either setup a fixedDelay or cron expression, or any of the other timing options to suit your time execution requirements.
not sure how to title this issue but lets hope description may give better explaination. I am looking for a way to annotate a ejb method or cdi method with a custom annotation like " #Duration" or someothing aaand so to kill methods execution if takes too long after the given duration period. I guess some pseudo code will make everything clear:
public class myEJBorCdiBean {
#Duration(seconds = 5)
public List<Data> complexTask(..., ...)
{
while(..)
// this takes more time than the given 5 seconds so throw execption
}
To sum up, a method takes extremely long and it shall throw a given time duration expired error or something like that
Kinda a timeout mechanism, I dont know if there is already something like this, I am new to javaEE world.
Thanks in advance guys
You are not supposed to use Threading API inside EJB/CDI container. EJB spec clearly states that:
The enterprise bean must not attempt to manage threads. The enterprise
bean must not attempt to start, stop, suspend, or resume a thread, or
to change a thread’s priority or name. The enterprise bean must not
attempt to manage thread groups.
Managed beans and the invocation of their business methods have to be fully controlled by the container in order to avoid corruption of their state. Depending on your usecase, either offload this operation to a dedicated service(outside javaee), or you could come up with some semi-hacking solution using EJB #Singleton and Schedule - so that you could periodically check for some control flag. If you are running on Wildfly/JBoss, you could misuse the #TransactionTimeout annotation for this- as EJB methods are by default transaction aware, setting the timeout on Transaction will effective control the invocation timeout on the bean method. I am not sure, how it is supported on other applications servers.
If async processing is an option, then EJB #Asynchronous could be of some help: see Asynchronous tutorial - Cancelling and asynchronous operation.
As a general advice: Do not run long running ops in EJB/CDI. Every request will spawn a new thread, threads are limited resource and your app will be much harder to scale and maintain(long running op ~= state), what happens if your server crashes during method invocation, how would the use case work in clustered environment. Again it is hard to say, what is a better approach without understanding of your use case, but investigate java EE batch api, JMS with message driven beans or asynchronous processing with #Asynchronous
It is a very meaningful idea – to limit a complex task to a certain execution time. In practical web-computing, many users will be unwilling to wait for a complex search task to complete when its duration exceeds a maximally acceptable amount of time.
The Enterprise container controls the thread pool, and the allocation of CPU-resources among the active threads. It does so taking into account also retention times during time-consuming I/O-tasks (typically disk access).
Nevertheless, it makes sense to program a start task variable, and so now and then during the complex task verify the duration of that particular task. I advice you to program a local, runnable task, which picks scheduled tasks from a job queue. I have experience with this from a Java Enterprise backend application running under Glassfish.
First the interface definition Duration.java
// Duration.java
#Qualifier
#Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
#Documented
#Retention(RetentionPolicy.RUNTIME)
public #interface Duration {
public int minutes() default 0; // Default, extended from class, within path
}
Now follows the definition of the job TimelyJob.java
// TimelyJob.java
#Duration(minutes = 5)
public class TimelyJob {
private LocalDateTime localDateTime = LocalDateTime.now();
private UUID uniqueTaskIdentifier;
private String uniqueOwnerId;
public TimelyJob(UUID uniqueTaskIdentifier, String uniqueOwnerId) {
this.uniqueTaskIdentifier = uniqueTaskIdentifier;
this.uniqueOwnerId = uniqueOwnerId;
}
public void processUntilMins() {
final int minutes = this.getClass().getAnnotation(Duration.class).minutes();
while (true) {
// do some heavy Java-task for a time unit, then pause, and check total time
// break - when finished
if (minutes > 0 && localDateTime.plusMinutes(minutes).isAfter(LocalDateTime.now())) {
break;
}
try {
Thread.sleep(5);
} catch (InterruptedException e) {
System.err.print(e);
}
}
// store result data in result class, 'synchronized' access
}
public LocalDateTime getLocalDateTime() {
return localDateTime;
}
public UUID getUniqueTaskIdentifier() {
return uniqueTaskIdentifier;
}
public String getUniqueOwnerId() {
return uniqueOwnerId;
}
}
The Runnable task that executes the timed jobs - TimedTask.java - is implemented as follows:
// TimedTask.java
public class TimedTask implements Runnable {
private LinkedBlockingQueue<TimelyJob> jobQueue = new LinkedBlockingQueue<TimelyJob>();
public void setJobQueue(TimelyJob job) {
this.jobQueue.add(job);
}
#Override
public void run() {
while (true) {
try {
TimelyJob nextJob = jobQueue.take();
nextJob.processUntilMins();
Thread.sleep(100);
} catch (InterruptedException e) {
System.err.print(e);
}
}
}
}
and in a seperate code, the staring of the TimedTask
public void initJobQueue() {
new Thread(new TimedTask()).start();
}
This functionality actually implements a batch-job scheduler in Java, using annotations to control the end-task time limit.
I have two ManagedBeans.
Concerning my problem, they do the following:
First:
#ManagedBean
public class Provider {
private Event<ProvideEvent> event;
private static boolean handling = false;
public provide(#Observes ConsumeEvent consume){
if(!handling){
//provide some stuff
event.fire(new ProvideEvent(ProvidedStuff stuff);
}
}
}
Second:
#ManagedBean
#SessionScoped
public class Consumer {
private Event<ConsumeEvent> event;
#PostConstruct
public void initialize(){
event.fire(new ConsumeEvent());
}
private static boolean handling = false;
public consume(#Observes ProvideEvent providedStuff){
if(!handling){
//use the provided stuff
}
}
}
This happens, when the website is called:
1. Consumer is instantiated.
2. Consumer fires the event.
3. Provider is instantiated.
4. provide() is called.
5. A NEW CONSUMER IS INSTANTIATED
6. consume() is called.
As you can see, I had to use a boolean "handling" to keep the application from looping infinitly.
Why is the container not using the instantiated SessionScoped ManagedBean? I thought SessionScoped ManagedBeans are like Singleton for the Session?
I guess I could work around this by:
A: Using static variables for the changed properties.
B: Implementing the Observer-Pattern manually.
But there has to be an easier way here!?
I believe the problem could be that you fire the event in the #PostConstruct method of your Customer.
From the javadocs:
This method MUST be invoked before the class is put into service.
As far as I understand, that results in a race condition. The Provider is probably firing the second event earlier than your Customer instance finishes executing initialize() and the container puts it into service. Hence, it won't receive the event. I'm too inexperienced with Java EE to give good advice how to prevent that race condition though. I would probably work around it with an ugly SynchronousQueue as a meeting point.
Additional info: the default with #Observes is to create a new instance of the event receiver if none exists (is in service). That's why another customer is created. Use #Observes(notifyObserver = Reception.IF_EXISTS) to only notify existing instances that are in service.
I thought SessionScoped ManagedBeans are like Singleton for the Session?
No, it just defines the lifetime of the object(s). It doesn't really enforce session-singleton behavior. The container would probably prefer the existing instance though, if it was in service at the time the second event is fired.
I have a singleton class in my play app. This singleton class is a long process which will generate reports from DB which consumes huge amount of memory. When i run my application in dev mode this singleton functionality is executing several times. I want this functionality to run only once. What should I do for that?
My code is:
public class DataGridManagerImpl extends ComponentContainer implements DataGridManager {
private static DataGridManager instance = null;
private DataGridManagerImpl(){
load();
}}
#Override
public void load() {
//Myreports function
}
public static DataGridManager getInstance(){
if (instance == null){
instance = new DataGridServiceManagerImpl();
}
return instance;
}
}
In my controller file inside a template function
DataGridManager dataGridMgr = DataGridManagerImpl.getInstance();
If i access the page it is executing the load reports function again.
Without code explaining how did you create your class it's hard to answer. From what I understand what you want is to run a process only once.
Problably the best approach is to use a Scheduled Job. This will trigger the process at a certain time, and Play ensures that only 1 instance of this process is running at the same time, even if the schedule would indicate another instance has to run. Let's say you have a process scheduled every hour and the process takes 3 hours. The initial process will be the only one running for 3 hours until it finishes.
Now, I would assume you want your process to be recurring as it generate reports. If not, if you only want to run it once, then you may want to use an asynchronous bootstrap job instead. This would run just once, at the beginning of the application.
EDIT on update: during development the #OnApplicationStart may execute several times, as Play may automatically reload the application when you do certain code changes. This is part of the dev process (the same that an #OnApplicationStart job won't start in Dev until the server gets a request).
As it's a job that you only want to run once, you may try to skip it in dev mode using the check:
if(Play.mode == Play.Mode.DEV)
If you need to run it at least once, add a dev-only url that you can access during dev to start the process.
Now, on your update you also mention that you are calling that code in a controller, and that every time the controller is acessed the method is called. That's expected. Singleton doesn't mean that it will run only once, but that there is only 1 object in the system. If in your controller you launch the calculation, that will happen everytime you access the controller.
SECOND EDIT (on comments): Arasu, the other issue is that you are calling the method load() when you construct the object. A singleton doesn't garantee that the object will only be constructed once. It garantees that, once constructed, only 1 object will exist. But it may happen that the object is removed by GC, in this case as per your code if you construct it again then you'll call load() and redo the processing.
The best solution is to not call "load" on constructor, but to force the user (you) to call it after retrieving the instance. An alternative is to set some flag at the beginning of load that detects if the code has been run. Be aware that Play is stateless, so that flag will need to be stored in the database.
the defition of a singleton is that it can run only once, it's practically the nature of the pattern. If you somehow manage to run it multiple times, you might have implementation errors in your singleton.
Recheck the singleton pattern in Wikipedia.
Edit:
This code makes it impossible to fetch more than one instance. How would you get more than one?
public class Singleton {
private static Singleton _instance;
private Singleton() { }
public static synchronized Singleton getInstance() {
if (null == _instance) {
_instance = new Singleton();
}
return _instance;
}
}
Or do you mean that you instanciate the Singleton class, instead of calling Singleton.getInstance()?
It is possible to have a Singleton doing a time consuming processing and be called the same time by two different threads. I think this is the situation here. The same Singleton object's method is called multiple times from the program.
I have run a little test... two thread calling the same Singleton object and here is the result
Thread[Thread 1,5,main] internal loop number = 0 Object = example.Singeton#164f1d0d
Thread[Thread 2,5,main] internal loop number = 0 Object = example.Singeton#164f1d0d
Thread[Thread 1,5,main] internal loop number = 1 Object = example.Singeton#164f1d0d
and here is the code.
package example;
public class Singeton {
private static final Singeton INSTANCE = new Singeton();
private Singeton() {}
public static Singeton getInstance(){
return INSTANCE;
}
public boolean doTimeConsumingThing(){
for (int i=0; i<10000000;i++){
System.out.println(Thread.currentThread() + " internal loop number = " + i + " Object = " + toString());
}
return true;
}
}
package example;
public class MulThread extends Thread{
public MulThread(String name) {
super(name);
}
#Override
public void run() {
while(true){
Singeton s = Singeton.getInstance();
System.out.println("Thread " + getId());
s.doTimeConsumingThing();
}
}
public static void main(String[] args) {
MulThread m1 = new MulThread("Thread 1");
MulThread m2 = new MulThread("Thread 2");
m1.start();
m2.start();
}
}
Please correct my notion above if i am wrong.
Hence what you need is a variable to keep track of the state of the time consuming procedure (i.e. a boolean isRunning) or the times the procedure has been called.
You can also make the pertinent time consuming method of the Singleton synchronized so only one thread can access the method while it is running (in my example if you make the doTimeConsumingThing() synchronized, the second thread will block until the singleton's method called from the first thread is finished.
Hope it helps
I had the same problem in DEV mode, and what I did is create a module for the tasks I don't want to be run at every #OnApplicationStart.
The trick is to launch those tasks in a overriden "onLoad()" method, in the module:
public void onLoad()
{
// tasks to run one time only
}
The onLoad() method is called one time only, not each time the application is restarted.
I don't know if this will help, but here are some things to check:
The code in your question is not thread-safe. You're missing the synchronized keyword in getInstance. That could cause the constructor to be called more than once by different threads.
Could DataGridManagerImpl be getting loaded by different classloaders? That static instance variable isn't static for the whole JVM, just static for that class' classloader.
load is public. Could some other code being calling that method?
I have a J2EE application that receives messages (events) via a web service. The messages are of varying types (requiring different processing depending on type) and sent in a specific sequence. It have identified a problem where some message types take longer to process than others. The result is that a message received second in a sequence may be processed before the first in the sequence. I have tried to address this problem by placing a synchronized block around the method that processes the messages. This seems to work, but I am not confident that this is the "correct" approach? Is there perhaps an alternative that may be more appropriate or is this "acceptable"? I have included a small snippit of code to try to explain more clearly. .... Any advice / guidance appreciated.
public class EventServiceImpl implements EventService {
public String submit (String msg) {
if (msg == null)
return ("NAK");
EventQueue.getInstance().submit(msg);
return "ACK";
}
}
public class EventQueue {
private static EventQueue instance = null;
private static int QUEUE_LENGTH = 10000;
protected boolean done = false;
BlockingQueue<String> myQueue = new LinkedBlockingQueue<String>(QUEUE_LENGTH);
protected EventQueue() {
new Thread(new Consumer(myQueue)).start();
}
public static EventQueue getInstance() {
if(instance == null) {
instance = new EventQueue();
}
return instance;
}
public void submit(String event) {
try {
myQueue.put(event);
} catch (InterruptedException ex) {
}
}
class Consumer implements Runnable {
protected BlockingQueue<String> queue;
Consumer(BlockingQueue<String> theQueue) { this.queue = theQueue; }
public void run() {
try {
while (true) {
Object obj = queue.take();
process(obj);
if (done) {
return;
}
}
} catch (InterruptedException ex) {
}
}
void process(Object obj) {
Event event = new Event( (String) obj);
EventHandler handler = EventHandlerFactory.getInstance(event);
handler.execute();
}
}
// Close queue gracefully
public void close() {
this.done = true;
}
I am not sure what is the framework (EJB(MDB)/JMS) you are working with. Generally using synchronization inside a Managed Environment like that of EJB/JMS should be avoided(its not a good practice). One way to get around is
the client should wait for the acknowledgement from the server before it sends the next message.
this way you client itself will control the sequence of events.
Please note this won't work if there are multiple client submitting the messages.
EDIT:
You have a situation wherein the client of the web service sends message in sequence without taking into account the message processing time. It simply dumps the message one after another. This is a good case for Queue ( First In First Out ) based solution. I suggest following two ways to accomplish this
Use JMS . This will have an additional overhead of adding a JMS providers and writing some plumbing code.
Use some multitheading pattern like Producer-Consumer wherein your web service handler will be dumping the incoming message in a Queue and a single threaded consumer will consume one message at a time. See this example using java.util.concurrent package.
Use database. Dump the incoming messages into a database. Use a different scheduler based program to scan the datbase (based on sequence number) and process the messages accordingly.
First and third solution is very standard for these type of problems. The second approach would be quick and won't need any additional libraries in your code.
If the events are to be processed in a specific sequence, then why not try adding "eventID" and 'orderID' fields to the messages? This way your EventServiceImpl class can sort, order and then execute in the proper order (regardless of the order they are created and/or delivered to the handler).
Synchronizing the handler.execute() block will not get the desired results, I expect. All the synchronized keyword does is prevent multiple threads from executing that block at the same time. It does nothing in the realm of properly ordering which thread goes next.
If the synchronized block does seem to make things work, then I assert you are getting very lucky in that the messages are being created, delivered and then acted upon in the proper order. In a multithread environment, this is not assured! I'd take steps to assure you are controlling this, rather than relying on good fortune.
Example:
Messages are created in the order 'client01-A', 'client01-C',
'client01-B', 'client01-D'
Messages arrive at the handler in the order 'client01-D',
'client01-B', 'client01-A', 'client01-C'
EventHandler can distinquish messages from one client to another and starts to cache 'client01' 's messages.
EventHandler recv's 'client01-A' message and knows it can process this and does so.
EventHandler looks in cache for message 'client01-B', finds it and processes it.
EventHandler cannot find 'client01-C' because it hasn't arrived yet.
EventHandler recv's 'client01-C' and processes it.
EventHandler looks in cache for 'client01-D' finds it, processes it, and considers the 'client01' interaction complete.
Something along these lines would assure proper processing and would promote good use of multiple threads.