0

On saving a domain object in a service, with a flush: true on the save of the domain, the object isn't getting saved before I have to use the object.

Domain domain = new Domain(property: something.toString()).save(failOnError: true, flush: true)

I'm unsure how to force a flush of the hibernate session in either of the services that I'm using.

For some context, I'm making an API call to an API service, which goes to another service where I'm saving the domain, then back to the API service then adding a string to a RabbitMQ queue then returning a 200OK to the user. But because the domain isn't getting saved in the second service, when the item is added to the queue, rabbitMQ is handling the message before the domain is saved.

EDIT:

My current fix:

API controller:

def apiActionCreate()
{
   Map returnMap = apiService.createAction(params, request)
   rabbitSend staticQueue, [id: returnMap.id.toString()]
}

API service:

Map createAction(GrailsParameterMap params, HttpServletRequest request)
{
   //do some logic related to a related domain
   seperateService.someAction(domain.id)
}

Service where I'm saving domain:

Map someAction(UUID id)
{
   Domain domain = new Domain(property: something.toString()).save(failOnError: true, flush: true)
}
David Brewer
  • 1,864
  • 8
  • 25
  • 37
  • 1
    maybe it's because of [not yet committed] transactions? – Igor Artamonov Nov 23 '15 at 17:08
  • Above is exactly why the instance doesn't exist yet. The `flush: true` hint on the domain instance is just that. A hint to Hibernate to flush any pending SQL to the database. However, depending on your transaction isolation level those changes may not be visible to other threads or Hibernate sessions. You could look into setting a less restrictive isolation level, but that has the drawback of phantom or dirty reads (depending on what isolation level you pick). – Joshua Moore Nov 23 '15 at 17:24
  • Hmm.. @JoshuaMoore with that in mind, would it be easier to just come from a controller to the API service then whatever I need and back to the controller? My experience with similar issues like this is that when you return to the controller from a service the information saved in that service is persisted to the database. – David Brewer Nov 23 '15 at 17:43
  • 1
    Is the service method `@Transactional`? – Emmanuel Rosa Nov 23 '15 at 23:07
  • 1
    try putting `static transaction=false` in your service – Vinay Prajapati Nov 24 '15 at 03:45
  • 1
    Your code looks similar to what I am extensively using in my application without any issue. Controller calls a service and service persists data with flush:true flag. I am not using failOnError:true but that should not make any difference. Moreover, my services are not transnational. Do you have any such attribute? If possible, can you push certain pieces of code in github to reproduce the issue? – Ejaz Ahmed Nov 24 '15 at 08:10
  • @EmmanuelRosa It is not a transactional service. Yeah it's not transactional at all. We have API's setup where we hit an API controller which calls out to an API service. But I think RabbitMQ is picking up the message because it can fully save. The only fix I have found so far is handling sending the message to RabbitMQ in the API controller instead of the service. At that point, the data is persisted. – David Brewer Nov 24 '15 at 13:11
  • Making the service method transactional will force it to persist the save. The flush hint is not even needed. – Emmanuel Rosa Nov 24 '15 at 13:34
  • @emmanuelRosa I thought services were transactional automatically unless you specified they weren't? – David Brewer Nov 24 '15 at 17:27
  • Yes, that is correct. When you said your service is not transactional I understood that you purposely disabled transactions: `static transaction=false` – Emmanuel Rosa Nov 24 '15 at 17:29

1 Answers1

0

You could create a transaction which will persist to DDBB when finish.

MyDomain.withTransaction{
        somecode()
}
quindimildev
  • 1,280
  • 8
  • 21
  • This didn't work for me sadly. I couldn't get that to work properly. I ended up just falling back to the controller level and letting the domain save before sending a request to RabbitMQ. – David Brewer Dec 02 '15 at 14:42