We're running into a weird issue where objects are created in a first request, but they are not returned in a second request.
Let's assume we have two domain classes:
Class A {
static hasMany = [bs: B]
def afterUpdate() {
this.addToBs(new B(a: this))
this.save()
}
}
Class B {
static belongsTo = [a: A]
}
When a put is sent on an instance of A via PUT /as/<id>, update() is invoked in the RestfulController which is annotated with #Transactional.
What we can observe is, that every once in a while a follow-up request send by the API consumer after the response of the first request is returned, GET /bs does not return the new instance of B which should have been created in the first request and is also returned on further requests.
I'd expected that grails only sends the response to the API consumer once the transaction is committed, which would mean that the next request should see all changes from that transaction, shouldn't it?
What could be the reason for that behavior? Is the transaction committed after the grails app already sent the response to the API consumer? If so, is the reason the #Transactional around the update() which is turned on by default?
I know in this example the code in afterUpdate could probably also be put into beforeUpdate, but I just tried to to simplify the example as far as I could.
In my experience, code in afterUpdate() and the like are not included in the transaction. You'd have to create a transaction explicitly (and maybe a session too). See http://docs.grails.org/latest/ref/Domain%20Classes/withTransaction.html
I advise against GORM updates within afterUpdate() and friends because it leads to weird issues like this, and makes it difficult to unit test the domain models. If you delegate saving to a transactional service instead, not only would it just work, you'd also be able to confirm it with integration tests.
In my Grails apps, I keep my controllers really dumb:
Call a service
Return the service's output (possibly formatting it).
I keep all business logic in services because controllers are kind of a pain to test well. Here's an example:
#grails.transaction.Transactional
class SomeService {
def saveA(A a) {
// This method will run in a transaction.
a.addToBs(new B(a: this))
a.save()
}
}
And in the controller...
class SomeController {
def update() {
...
someService.save(a)
}
}
Related
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?
I have a service method to transfer funds to/from an external system.
it should create a transaction in our system first (so we have a transactionId)
Then we call the external system.
If the external system fails, we need to rollback the transaction, then write a new record in our payment audit log table, regardless of if the call failed or worked.
I cant figure out how to control the transaction in this case.
I understand services are transactional by default.
I assume I could create 3 methods (they are all 1 method now, which doesn't work as I have no control over what gets committed and what gets rolled back)
createPaymentTransaction()
sendToPaymentSystem()
createPaymentRecord()
I need to rollback 1 if 1 fails, and do nothing more.
I need to rollback 1 if 2 fails, but write 3.
I need to write 3 if 1 and 2 works.
I don't know how to annotate these, or how to structure a 4th request to manage the 3.
I'd go with something like this:
package com.myapp
import grails.transaction.Transactional
import org.springframework.transaction.annotation.Propagation
#Transactional
class MyService {
def createPaymentTransaction() {}
def sendToPaymentSystem() {}
#Transactional(propagation=Propagation.REQUIRES_NEW)
def createPaymentRecord() {}
def method4() {
try {
def transactionId = createPaymentTransaction()
sendToPaymentSystem(transactionId)
}
finally {
createPaymentRecord()
}
}
}
By annotating at the class level, we set the defaults for all methods, but can customize as needed, e.g. for createPaymentMethod.
So what will happen is that calling method4 will join an existing transaction, or start a new one if necessary. If there's a problem in either createPaymentTransaction or sendToPaymentSystem then the transaction will be rolled back, but the call to createPaymentRecord will happen because it's in the finally block, and it will run in a separate transaction so it isn't affected by a rollback in the main transaction, and a failure there doesn't affect the main transaction.
If you're not able to use the new grails.transaction.Transactional annotation, use the standard Spring org.springframework.transaction.annotation.Transactional annotation, but you need to make a small change. One of the motivations for the Grails annotation is to provide the same functionality as the Spring annotation, but avoid the problems with calling an annotated method from within the service. The Spring annotation triggers creation of a proxy at runtime which intercepts all calls, manages transactionality for the method, and then calls the real method in the service instance. But with the current code, the call to createPaymentRecord will bypass the proxy (the service instance is just calling itself) and there won't be a new transaction. The Grails annotation rewrites the bytecode to wrap each method in a transaction template which uses the applicable annotation settings (explicit or inferred from a class-scope annotation), so it works correctly internally and externally. If using the Spring annotation, you need to call the method on the proxy, which just involves accessing the Spring bean for this service. Add a dependency injection for the GrailsApplication as a field:
def grailsApplication
and then call createPaymentRecord via
grailsApplication.mainContext.myService.createPaymentRecord()
in the finally block.
By default all methods in a service are transactional, but you can change the behaviour on a method-by-method basis with annotations, e.g.
import grails.transaction.*
// By default all methods are transactional
#Transactional
class MyService {
#NotTransactional
def notTransactional() {
}
// inherits the class-level default
def transactional() {
}
}
See the Grails manual for more details about the transaction annotations.
If you need to manage transactions at a more fine-grained level than per-method, you can use the withTransaction domain class method to manage transactions programatically.
If you use a controller to implement rest APIs, you want to deal with any exception thrown and return a generic or specific well formed REST response.
We can't use global error URL mapping method, as the application has a number of APIs and interfaces with different response requirements, and we also don't know which type of Grails' HTTP error codes will be thrown (e.g don't know if it will be a 400, 422, 500 etc). Also, if we used the error page mappings, we won't be able to put relevant data into the JSON response.
E.g. this will generate a GrailsRuntimeException:
class SomeController {
def payload = request.JSON
def someMethod() {
BigDecimal x = new BigDecimal(payload.notExists)
}
The problem is, it seems impossible to catch any error thrown.
E.g. neither this approach:
def handleRuntimeException(RuntimeException e) {
render("some JSON error message")
}
Nor this approach:
try {
:
}
catch (GrailsRuntimeException e) {
render("some JSON error message")
}
Works - it never catches the error.
Tried GroovyRuntimeException, Exception, MissingMethodException, Throwable etc.
The only solution we can think of is to not do any work in the controller, do everything in a service, where apparently we can catch errors.
This approach:
static mappings = {
"500"(controller: "error")
}
Is not want we need for several reasons:
We have several different APIs in different controllers which would require different response formats.
we also have UI controllers, which would want the default error system which shows the stack trace etc.
We want to handle the error in the controller where the exception happened, so we can clean up, or at least can log or return the stat which only the controller knows.
Have decided the only way is to move all code into services, and do nothing in the controller except pass the request, and render the resultant string. i.e. all parameter handling, especially number conversion, is done in the service.
It's ironic that the solution that you see as suboptimal that you're settling for is exactly what you should always do. This isn't PHP - don't put logic in Controllers (or GSPs).
Services are by default transactional, so they're a great place to put code that writes to the database since that should always happen in a transaction. They're also excellent for business logic whether it's transactional or not, and you can either annotate individual methods with #Transactional to partition the methods into ones that run in a transaction and ones that don't, or split the services into some that are fully transactional and some that aren't.
If you keep all of the HTTP-related code in the controllers, doing the data binding from params, and calling helper classes (services, domain classes, taglibs, etc.) you get a good separation of concerns, and if the service layer doesn't know anything about params, HttpServletRequest, HTTP sessions, etc. then it's easily reusable in other Grails apps and even in non-Grails apps. They'll also be easier to test, since there isn't so much inter-related code that needs to be mocked and otherwise made test-friendly.
Using this approach, the controllers basically become dumb routers, accepting requests, calling helpers to do the real work, and delegating page rendering or response writing, or redirecting or forwarding.
I am very late to answer this, but I think it might help people stumbling and searching for solution.
Here is one of my blogs explaining Custom exception handling in grails and error responses for RESTfull services
Hope this might help someone
I am using grails 3.2.4 and there is no issue as you have explained here. I have moved all business logics inside the service class and catching exceptions by parent controller trait. Here I am handling this exception in another ParentExceptionController trait which is implemented by classes where such exception is occurring from service class. Example:
UserService {
boolean create(Map params) {
throw new InvalidParameterException('some message')
}
UserController implements ParentExceptionController {
UserService userService
userService.create(params.userDetails)
}
trait ParentExceptionController {
Object handleInvalidParameterException(InvalidParameterExceoption exception) {
log.error 'log message'
respond([message: exception.message])
}
first and second both are working in my case.
I have the following method within my controller:
#Transactional
def update(Filter filterInstance) {
bindData(filterInstance, params, [include: ['name, 'code', 'value']])
filterService.update(filterInstance)
mappingService.update(filterInstance)
respond filterInstance
}
I need to use #Transactional here because I call multiple services. How to handle case when transaction fails for some reason? Should I use try catch or may be there is some other way?
Thanks!
If you have the code inside a controller action, you have to keep an eye on 2 things:
transactionality (with try/catch/finally etc)
what should the action return/render in case of TX-success/-failure.
It's complicated enough, so you should put the service calls into another service method, where you have to deal with the transactions only.
A controller action is a place, where you may fire really simple 1-step transactions. If you need to implement a more complex TX-logic, do it on the service layer
see ref-doc on how to control multi-step transactions.
you can make your update() methods return false or throw an exception, and if such thing occurs, call status.setRollbackOnly(). Don't forget also to mark the update() methods with #Transactional(propagation = Propagation.SUPPORTS)
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