Execute task after transaction ends - Grails - grails

I need to execute some tasks after grails transaction ends. I'm not looking for afterCommit of Hibernate, instead of that, I need a method to be called after the transaction of the service ends.
Is there any way? I've read the documentation but I couldn't find anything, just normal events like afterUpdate or afterCommit.
Thanks!

You can add an event listener to the current session
sessionFactory.currentSession.addEventListener(...)
class MyListener extends BaseSessionEventListener {
#Override
void transactionCompletion(boolean successful) {
}
}
You just need to verify the transaction was successful via the parameter. Also understand that if there are multiple transactions in a single session the listener will be invoked for each one.

That really depends on what you're trying to do. The best bet is probably to call a #Transactional method on a service, and then when that returns, run the code that you need to happen after the transaction.
An alternative, if you just want to spin off some task to do something simple, you can use:
new java.util.Timer().runAfter(1000) { //time in milliseconds
//code to run here
}
This is just a shortcut to spin off a new thread and runs the closure body after (in the above example) 1 second... I believe the closure still has access to injected grails objects, but does not have access to the session. I'd double-check that though. I've used this in several places for sending notifications that needed to wait until after some processing inside a transaction ended.

Related

Handling a method that takes too long to execute and is not awaitable

We are building a custom way to process timesheets using eConnect. A method is exposed that allows out timesheets documents to be submitted to GP. This method is run synchronously, but can take a long time to complete. How can I handle this so that the user's client can make additional requests in the meantime?
I have attempted to use async/await on this method, but because the method isn't awaitable this will not work. The method depends on a windows service. I have researched potentially wrapping it in Task.Run but have hesitations since this sounds like a bad practice.
public bool SaveTimesheets(string ConnectionString, List<PATimeSheetsType> Timesheets)
{
string timesheetDocument = string.Empty;
//Creating timesheet document
bool result = false;
eConnectMethods eConnectMethods = new eConnectMethods();
//CreateEntity takes minutes to complete and return
result = eConnectMethods.CreateEntity(ConnectionString, timesheetDocument);
return result;
}
The behavior I currently get is that, if for instance I am doing an ajax calls on the client-side, the call doesn't seem to get there while the method above is executing. I would like it so that the method call executes in the background so that the client can still communicate with the server to execute other requests.
How can I handle this so that the user's client can make additional requests in the meantime?
The easiest solution is to change your session state to be None or Read-Only (for both this and the other requests). Then ASP.NET will allow multiple client requests for the same session.
If you're on pre-Core, the session state docs are here.

is java.util observer safe on a (static) grails (2.5) service?

We have decoupled certain events by implementing listeners in exploded plugins (i.e. outside of the core application). Then we can build different implementations. Also, the listeners work must be outside any transaction, as it can take a long time (think connecting to the internet and waiting a long time, and if if fails, it must not rollback anything). The app is a webapp and api running on tomcat.
The problem is setChanged().
Here is a service:
class someService extends Observable {
}
Here is a plugin bootstrap:
SomeService someService
:
someService.addObserver(listenerService)
Here is the listener:
class ListenerService implements Observer {
#NotTransactional
void update(Observable o, Object arg) {
DomainObject domainObject (DomainObject) arg
// do somethign which takes a very log time
}
Here it is being called somewhere (e.g inside a method of someService, or elsewhere)
someService.setChanged()
someService.notifyObservers(someEvent)
I see a big problem here - if the setChanged is called my multiple requests, Each will set changed=true, but the first notifyObserver will set it to false, so when the second notifyObserer executes, it will see changed == false and return.
I see 2 possible solutions:
Put the observer on a domain object, which is not static.
hook into the afterUpdate domain event (not idea as we want to be outside the transaction, but we could start anther thread and do the work asynchronously)
Does anyone know if using the observer on the domain object (and calling setChanged and nofityObservers in some session) is a good solution?

How to force flushing in Grails GORM

I have a service that distributes tasks to operators.
Inside a method I distribute many tasks in time inside a loop. I want to flush the task, the operator, and a DistributionLog. If I just had one domain to save I think I could do something like
Operator.withTransaction{ //...some code }
but I have at least 3 domains to save and to make it even worse, two of them have dependency on each other. The operator have a list of tasks.
I can't wait all the distribution to finish before an operator can get his tasks, so I have to force it to flush. To make it even harder, it's all inside a multitenantService.doWithTenant() (multitenant plugin)
You can get the session using the withSession method available in all domain classes and call to flush() on it.
Operator.withSession { session ->
// ...
session.flush()
}
If you want to do an explicit flush, you can get a reference to the hibernate session factory in your grails service like this:
def sessionFactory
You can then get the current hibernate session, and call flush on that:
sessionFactory.currentSession.flush()
You can force a flush with flush argument to the last call to save:
obj.save flush:true
See the documentation:
http://grails.github.io/grails-doc/2.2.5/ref/Domain%20Classes/save.html
The save method informs the persistence context that an instance should be saved or updated. The object will not be persisted immediately unless the flush argument is used:
b.save(flush: true)

How to get executing job's name?

In my application I have a static class (singleton) that needs to be initialized with some environmental variables that's used through out my layers, I'm calling it my applicationContext. That in turn has customer and user contexts.
As each job runs it modifies these customer and user contexts depending on the situation.
The problem I have is that when 2 jobs fires concurrently they might overwrite each others contexts, therefor I need to keep multiple user and customer contexts alive for each running job and I need to be able to pick the right context by somehow being able to see what the current job is.
Is it possible to somehow get information about the current executing quartz.net job?
I'm envisioning something like this where "currentQuartzJob.Name" is made up and is the part I'm missing:
public class MyContextImpl : IApplicationContext {
private Dictionary<string,subContexts> allCustomerContexts;
public string CurrentContext
{
get { return allCustomerContexts[currentQuartzJob.Name] };
}
}
edit:
I don't think it's possible to do what I wanted, that is to be able to get the executing job's name in a class that doesn't know about Quartz.Net.
What I really needed was a way to keep a different context for each job. I managed to do that by looking at the executing thread's ID as they seem to differ for each running job.
Try this:
public void Execute(IJobExecutionContext context)
{
var yourJobName = context.JobDetail.Key.Name;
}
Given your statement above: "The problem I have is that when 2 jobs fires concurrently they might overwrite each others contexts", you may want to reduce the complexity of your application by making sure that jobs do not fire concurrently. This can be achieved by implementing the IStatefulJob interface instead of the usual IJob interface: http://quartznet.sourceforge.net/tutorial/lesson_3.html
Alternatively if that is not an option you can query the Scheduler object for the currently executing jobs via the Ischeduler.GetCurrentlyExecutingJobs() method. This method returns an IList of those jobs but note the following remarks when using that method (from version 1.0.3 API):
This method is not cluster aware. That is, it will only return Jobs currently executing in this Scheduler instance, not across the entire cluster.
Note that the list returned is an 'instantaneous' snap-shot, and that as soon as it's returned, the true list of executing jobs may be different. Also please read the doc associated with JobExecutionContext- especially if you're using remoting.
I'm not entirely sure of what you're doing with your application, but I will say that the name of the currently executing job is definitely available during job execution.
Inside the IJob Execute() method:
// implementation in IJob
public void Execute(JobExecutionContext context)
{
// get name here
string jobName = context.JobDetail.Name;
}
Is that what you're looking for?

Remoting (server side)

I´m relative new on remoting (2.0 C#). Is there any/someway to lock the server side object/instance to one client?
I have up to 10 clients that will connect to the server. The server will offer 3 different task/operations/classes and if one client does a request and if the server is not working on that, I´ll like to lock this operation to that client. The reason for this is that the requests works with HW that only can handle on task at the time. Hope you understand what I like too do.
EDIT:
I´ll try to explain my problem again...
I have 3 classes that will have X number of methods/operations (operations that will trigger a external hardware to do some measuring). When a client "connects" to one class (at the time) and request a measuring to be performed I want to lock that class to the client, hence, the client will own this class and it shall be able to execute all methods. No other client shall be able/allowed to access this class while the first client has control. The other tow classes should be open for requests from other clients, but the same principle/rules shall apply to these classes. As soon as a client request a lock it shall have it as long as it requires it. I´ll will have an intreface that all clients must follow. Call a method called Lock() to require the control over the class and Unlock() to release the control. I/We will develop all the clients and the server!
Thanks for all the help, so far!
Regards
/Anders
You have to lock the task by using semaphores in order to ensure only one thread at a time. Look into the Semaphore and Mutex classes.
Edit:
You can do many ways from locking to complex semaphores, here you have two samples:
This one only locks to ensure that one execution is being done at a time:
private static object lockObject=new object();
public void Test()
{
lock (lockObject)
{
//your code here
}
}
This one uses a Mutex to wait until it is released, but with a timeout that will return with some information to the client indicating that the method could not be executed.
private static Mutex mutex = new Mutex();
public bool Test2()
{
if (!mutex.WaitOne(500))
{
return false;
}
try
{
//your code here
}
finally
{
mutex.ReleaseMutex();
}
return true;
}
Ok, now I see the point.
You can use the CAO approach instead: create a factory (can be a singleton) that gives you a CAO (Client Activated Object) if nobody else owns an instance.
CAO is good for that because it will ensure that if the client dies the CAO would be released.
Explaining a CAO is too much for a simple answer, it is something like this: CAO is a class inherited from MarshalByRefObject that you will create from your factory and return the instance from one method (i.e.: your Lock method); the object lives in the server and the client receives only a proxy. The object will live into the server while it's lease is being refreshed by the client (done automatically while the object is referenced and client are alive).
You may take a look to the Ingo Rammer's articles and books on remoting.
jmservera, thanks for all your help.
I have now found a solution that will work for me...I´m using the proxy pattern combined with the factory pattern. I do use the WellKnownObjectMode.Singleton method so I can control how many active instances I have on my server.
And by doing it this way, i don´t need to share my code with the client, only the interface (as you said before).
Regards
/Anders

Resources