Sunday, March 10, 2013

Optimizing Long Running ADF Operations with Parallel WebLogic Time Manager Execution

This blog title sounds a bit fancy - isn't it? :) I was looking how to optimize long running operation execution and separate it from ADF context (so, ADF application will remain responsive). Additional requirement - the same long running operation might need to be invoked multiple times, based on execution result and other parameters. Here I would like to share solution with you today - solution is pretty cool, it involves WebLogic time scheduling for delayed long running series of ADF requests execution initialized from ADF session context.

WebLogic time manager for scheduling is configured in web.xml, download sample application - ADFWLSSchedulerApp.zip:


Sample application concept is pretty straightforward - user selects row from ADF UI table and calls process by button click. There is action event registered to listen for "Submit for Processing" button, action event retrieves currently selected row key and schedules parallel request execution with WebLogic time manager. From this point - control is returned back to ADF application and request execution will run in parallel without blocking user actions:


Here is source code for the action listener where instance of WebLogic time manager is acquired, current row key is retrieved and task is scheduled to executed every 30 seconds. Action listener returns control back to the user and request goes into the queue for processing. This allows to continue normal user actions in ADF session and run long running jobs in the background, otherwise ADF applications session would be blocked:


WebLogic time manager invokes job every 30 seconds (to simulate long running action with multiple invocations) in this example, current row key is passed to the job. In real life use case, you may pass additional parameters - here my goal is to describe a concept. Scheduled job gets access to ADF BC by creating and releasing new instance of Application Module, we are able to call ADF BC custom method from here:


As you can see, I'm calling ADF BC method maximum 3 times and then scheduled job is marked as completed. Here you can check ADF BC custom method execution status and decide to execute it again (if false status was returned) or stop.

Custom AD BC method is calling ADF BC findByKey operation and returns incremented counter (to make sure repeat scheduling up to 3 times):


There are some tricks you should keep in mind. Scheduler creates and destroys separate AM instance, I would recommend to create separate AM configuration and use it specifically from the scheduler - HrModuleScheduler:


Obviously there is no need to use AM pooling when calling from scheduler (AM instance is created and then destroyed instantly). Make sure to set maximum pool size = 1 and is use exclusive = false, this will create maximum only 1 pool instance and will release reserved DB connection after request was executed:


Select any row and press Submit for Processing button:


Request is submitted to WebLogic scheduler and we can continue working with ADF screen as regular, doing filtering, etc.:


At the same time we can review in the log - application executes parallel requests to ADF BC:

14 comments:

Anonymous said...

For a real production system, the technique explained in this article should not be used. Tasks created with the TimerManager framework are not run in a managed container, thus loosing the benefits.
Use instead JMS and EJBs for asynchronous and long running tasks.

Andrej Baranovskij said...

What is real production system?:) i cant agree with, because time manager is simple solution, that runs well on non clustered environment. I would say half of ADF apps run on non clustered servers. So, time manager approach is quite cool, without having to add beans and jms.

Andrejus

Andrej Baranovskij said...

Additionally you should remember that JMS provides only parallel execution, but with time manager you can schedule multiple request execution.

If you want, Time Manager can run on WebLogic cluster as well. See this blog: https://blogs.oracle.com/jamesbayer/entry/a_simple_job_scheduler_example

Andrejus

Anonymous said...

Java EE 7 has some improvements in this regard. See http://jcp.org/en/jsr/detail?id=236

This has been approved: https://blogs.oracle.com/theaquarium/entry/java_ee_7_platform_completes

I agree with you in you other points, and that EJB anf JMS might be overkill in some situations. Simplicity is king.

Andrej Baranovskij said...

Thanks for update !

Andrejus

Anonymous said...

HI Andrejus,

I followed your blog to make one of the methods in the amimpl to run in the background, but the method is not getting called from batchjob class, and we are using JDev 11.1.1.6, and can you help me out here...

Anonymous said...

Hi Andrejus, thanks a lot for the example. But only one question will scheduled job execute if we close browser window or session expires for application?

Andrej Baranovskij said...

It would be stopped when session stops. If you want to run it independently, it must be separate application.

Regards,
Andrejus

Luís Pinto said...

Hi Andrejus, sorry to push this out of the graveyard, but I'd like to have the project you created for this post. The URL gives me 404.

The requested URL /files/ADFWLSSchedulerApp.zip was not found on this server.

Can you provide a mirror for the project? Thank you very much.

Anonymous said...

Hi Andrejus,

Thanks for the post.

Please suggest how can we show a notification message on screen when Timer Manager process gets completed. I have tried but unable to get Facescontext object to use addMessage function.

Anonymous said...

Hi Andrejus,

If you need to update the GUI after task termination, how would you acomplish that?

Thanks

Andrej Baranovskij said...

You can throw JboException with predefined code, catch it in DC Error Handler and display info message. Or you can simply throw JboException with message, it will be display in ADF popup automatically.

Andrejus

Zhi Yan said...

Hi Andrejus,

Thanks for the info!

I currently have a similar task, but not sure if I can use this technique?

I need to have a scheduler inside ADF to trigger some events periodically - not triggered from UI.

Can I somehow add some setup into ADF (etc, register a periodic job in this Weblogic Timer Manager), and trigger the event periodically - say every 10 minutes.

Currently we want to use ADF UI to do the setup (etc, set up a job and its period), and then trigger the job periodically.

Andrej Baranovskij said...

What kind of events you want to trigger inside ADF?

Andrejus