I'm using grails 4.0.6 and I need to check if a given service's method is in execution with a certain domain object's instance. In this case, the method takes a long time to run and it is called with a parameter (a domain class' instance). If it is called again with the same instance that it is currently in execution with, the call must be aborted. I tried setting a flag in the domain class (and flushed the update) however it is not reflected in the new call. Any hints are appreciated.
If you need to abort the second call, use a Lock. If you just don't want them running concurrently, use a synchronized block.
Lock:
class MyService {
static def locks = [:]
def someMethod(inputParam) {
def key = "${inputParam.class}${inputParam.id}"
def lock = locks.get(key)
if (!lock) {
lock = new ReentrantLock()
locks.put(key, lock)
}
if (lock.tryLock()) {
// do your work here
lock.unlock()
}
}
}
Synchronized:
Your service method would pretty much be
synchronized (key) {
// your work
}
Any of this may need tweaks...I just typed it in here without any testing!
Related
We need to be able to rollback a complex transaction in a service, without throwing an exception to the caller. My understanding is that the only way to achieve this is to use withTransaction.
The question is:
why do I have to call this on a domain object, such as Books.withTransaction
What if there is no relevant domain object, what is the consequence of picking a random one?
Below is more or less what I am trying to do. The use case is for withdrawing from an account and putting it onto a credit card. If the transfer fails, we want to rollback the transaction, but not the payment record log, which must be committed in a separate transaction (using RequiresNew). In any case, the service method must return a complex object, not an exception.
someService.groovy
Class SomeService {
#NotTransactional
SomeComplexObject someMethod() {
SomeDomainObject.withTransaction{ status ->
DomainObject ob1 = new DomainObject.save()
LogDomainObject ob2 = insertAndCommitLogInNewTransaction()
SomeComplexObject ob3 = someAction()
if (!ob3.worked) {
status.setRollbackOnly() // only rollback ob1, not ob2!
}
return ob3
}
}
}
The above is flawed - I assume "return ob3" wont return ob3 from the method, as its in a closure. Not sure how to communicate from inside a closure to outside it.
To your primary question: you can pick a random domain object if you want, it won't do any harm. Or, if you prefer, you can find the current session and open a transaction on that instead:
grailsApplication.sessionFactory.currentSession.withTransaction { /* Do the things */ }
Stylistically I don't have a preference here. Others might.
Not sure how to communicate from inside a closure to outside it.
In general this could be hard; withTransaction could in principle return anything it wants, no matter what its closure argument returns. But it turns out that withTransaction returns the value returned by its closure. Here, watch:
groovy> println(MyDomainObject.withTransaction { 2 + 2 })
4
By convention, all withFoo methods which take a closure should work this way, precisely so that you can do the thing you're trying to do.
I'm assuming this question was from a grails 2 application and this problem from 2015 has been fixed before now.
I can't find this in any of the grails 2 documentation, but services have a magic transactionStatus variable injected into their methods. (at least in grails 2.3.11)
You can just leave all the annotations off and use that injected variable.
Class SomeService {
SomeComplexObject someMethod() {
DomainObject ob1 = new DomainObject.save()
LogDomainObject ob2 = insertAndCommitLogInNewTransaction()
SomeComplexObject ob3 = someAction()
if (!ob3.worked) {
transactionStatus.setRollbackOnly() // transactionStatus is magically injected.
}
return ob3
}
}
This feature is in grails 2, but not documented. It is documented in grails 3.
https://docs.grails.org/latest/guide/services.html#declarativeTransactions
search for transactionStatus.
I'm using Grails 2.4 and I have a helper service that creates a specific domain class, sets up the dependencies surrounding it and then finally saves the object to the database, within a promise.
How would I test this service?
An example of the service is:
def persist(name, objectId, depTwoId) {
Person p = Person.findByName(name)
Object o = Object.findById(objectId)
RepObject rob = RepObject(p, o) //Ok you get the idea here
def task = Promises.task {
rob.save()
}
}
I don't care, within the context of the unit test, if there was a save to the database. I just want to know that it was called.
You'll have to do something to wait for the async call to finish, but that's a separate issue.
I'd do it with the metaclass if all you want to verify is that save is called, but not that the object is actually persisted:
Before you call the persist method in your integration test, add this:
boolean saveCalled = false
RepObject.metaClass.save = { -> saveCalled = true }
and in your Spock then block or wherever you do verification calls, add
assert saveCalled
Note that the signature of the metaclass save closure has to match what's actually called. You show it being called with no args, but if you call save(flush:true) then you're passing a Map arg and the signature would have to be
RepObject.metaClass.save = { Map m -> saveCalled = true }
otherwise Groovy won't choose yours, it will call the real method.
In my Grails app I've installed the Quartz plugin. I want to intercept calls to every Quartz job class' execute method in order to do something before the execute method is invoked (similar to AOP before advice).
Currently, I'm trying to do this interception from the doWithDynamicMethods closure of another plugin as shown below:
def doWithDynamicMethods = { ctx ->
// get all the job classes
application.getArtefacts("Job").each { klass ->
MetaClass jobMetaClass = klass.clazz.metaClass
// intercept the methods of the job classes
jobMetaClass.invokeMethod = { String name, Object args ->
// do something before invoking the called method
if (name == "execute") {
println "this should happen before execute()"
}
// now call the method that was originally invoked
def validMethod = jobMetaClass.getMetaMethod(name, args)
if (validMethod != null) {
validMethod.invoke(delegate, args)
} else {
jobMetaClass.invokeMissingMethod(delegate, name, args)
}
}
}
}
So, given a job such as
class TestJob {
static triggers = {
simple repeatInterval: 5000l // execute job once in 5 seconds
}
def execute() {
"execute called"
}
}
It should print:
this should happen before execute()
execute called
But my attempt at method interception seems to have no effect and instead it just prints:
execute called
Perhaps the cause of the problem is this Groovy bug? Even though the Job classes don't explicitly implement the org.quartz.Job interface, I suspect that implicitly (due to some Groovy voodoo), they are instances of this interface.
If indeed this bug is the cause of my problem, is there another way that I can do "before method interception"?
Because all the job classes are Spring beans you can solve this problem using Spring AOP. Define an aspect such as the following (adjust the pointcut definition so that it matches only your job classes, I've assumed they are all in a package named org.example.job and have a class name that ends with Job).
#Aspect
class JobExecutionAspect {
#Pointcut("execution(public * org.example.job.*Job.execute(..))")
public void executeMethods() {}
#Around("executeMethods()")
def interceptJobExecuteMethod(ProceedingJoinPoint jp) {
// do your stuff that should happen before execute() here, if you need access
// to the job object call jp.getTarget()
// now call the job's execute() method
jp.proceed()
}
}
You'll need to register this aspect as a Spring bean (it doesn't matter what name you give the bean).
You can have your customized JobListener registered in the application to handle logics before execute() is triggered. You can use something like:-
public class MyJobListener implements JobListener {
public void jobToBeExecuted(JobExecutionContext context) {
println "Before calling Execute"
}
public void jobWasExecuted(JobExecutionContext context,
JobExecutionException jobException) {}
public void jobExecutionVetoed(JobExecutionContext context) {}
}
Register the customized Job Listener to Quartz Scheduler in Bootstrap:-
Scheduler scheduler = ctx.getBean("quartzScheduler") //ctx being application context
scheduler.getListenerManager().addJobListener(myJobListener, allJobs())
resources.groovy:-
beans = {
myJobListener(MyJobListener)
}
One benefit I see here using this approach is that we don't need the second plugin used for method interception any more.
Second, we can register the listener to listen all jobs, specific jobs, and jobs in a group. Refer Customize Quartz JobListener and API for JobListener, TriggerListener, ScheduleListener for more insight.
Obviously, AOP is another approach if we do want want to use Quartz API.
You are not getting the job classes like that. If you refer to the Quartz plugin, you can get them by calling jobClasses:
application.jobClasses.each {GrailsJobClass tc -> ... }
see https://github.com/nebolsin/grails-quartz/blob/master/QuartzGrailsPlugin.groovy
If you actually look, you can see that they are almost doing what you are trying to acheive without the need to use aop or anything else.
For method interception implement invokeMethod on the metaclass. In my case the class was not of third party so I can modify the implementation.
Follow this blog for more information.
I'm writing a service that shouldn't have to save anything. It gets some values. Looks up a few things in the database, and then coughs back a response. Is there anything I should do to make the service faster/less overhead? Also whats the best way to pass it something. I usually pass the id and get it again; is that good/bad/dumb?
example
class DoStuffController {
def ExampleProcessingService
def yesDoIt = {
def lookup = "findme"
def theObject = ExampleThing.findByLookie(lookup)
def lolMap = ExampleProcessingService.doYourThing(theObject.id)
if(lolMap["successBool"]){
theObject.imaString = "Stuff"
theObject.save()
}
[]
}
}
service
class ExampleProcessingService{
static transactional = true //???????? false? not-a?
def doYourThing = {theID ->
def returnMap = [:]
def myInstance = ExampleThing.get(theID)
if(myInstance.something)returnMap.put "successBool", true
else returnMap.put "successBool", false
return returnMap
}
}
domain object
class ExampleThing {
String imaString
String lookie
static constraints = {
imaString(nullable:true)
}
def getSomething() {
return true
}
}
bootstrap
import learngrails.*
class BootStrap {
def init = { servletContext ->
def newThing = new ExampleThing(lookie:"findme")
newThing.save()
}
def destroy = {
}
}
Is the an advantage, disadvantage or standard to passing ID and doing get vs. passing the object? Does this change given my case of not going to save anything in the service? Is there something I'm doing glaringly wrong? Do you have a better suggestion for the title?
You've asked a lot of questions, and should split this into several individual questions. But I'll address the overall issue - this approach is fine in general.
There's not a lot of overhead in starting and committing a transaction that doesn't do any database persistence, but it is wasteful, so you should add
static transactional = false
In this case you're using the class as an easily injected singleton helper class. It's convenient to do transactional work in services because they're automatically transactional, but it's far from a requirement.
One thing though - do not use closures in services. They're required in controllers and taglibs (until 2.0 anyway) but should always be avoided in services and other classes. If you're not using the fact that it's a closure - i.e. passing it as an object to a method as a parameter, or setting its delegate, etc. - then you're just being way too groovy. If you're calling it like a method, make it a method. The real downside to closures in services is that when you want them to be transactional, they cannot be. This is because Spring interceptors intercept method calls, not closure calls that Groovy pretends are method calls. So there won't be any interception for transactions, security, etc.
Is it possible to use some kind of 'critical section' so that it is safe to do something like the following within an action...
public ActionResult GenerateTasks()
{
string someDir = ....
if (!Directory.Exists(someDir))
{
Directory.CreateDirectory(someDir);
}
...
}
You can do this only by using a system-wide mutex. Process or app-domain locking primitives will fail to work under certain conditions (for instance when an application pool is recycled).
However, for the specific case here that's not necessary: Directory.CreateDirectory already does implement an existence check on its own, so that you shouldn't need to do anything in this regard.
I'm assuming by your question that the concurrent safety you're interested in is whether or not the directory is created between the Directory.Exists and the Directory.CreateDirectory on a different thread. (If you're concerned about Directory.CreateDirectory throwing an exception if the directory already exists, it won't.) If so, and this is the point in your code that will have the potential to do that, then you can simply use a lock object to make these set of operations safe across multiple threads:
private static object lockObject = new object();
public ActionResult GenerateTasks()
{
string someDir = ....
lock(lockObject)
{
if (!Directory.Exists(someDir))
{
Directory.CreateDirectory(someDir);
}
}
...
}
This does not however make any garauntees that the directory isn't being interacted with outside of your control, say, in another application process.