grails hasMany of jodatime Instants - grails

How can I work around http://jira.grails.org/browse/GPJODATIME-28 which prevents a domain class from having a hasMany of any extended type?
I'm thinking of switching the whole app to persisting a custom UserType derived from BigDecimal for posix epoch dates. Seem's like a hammer for a walnut though. IS there another approach I could take?
import org.joda.time.Instant
class Foo {
Instant birthday
Set favoriteDays = []
static hasMany = [
favoriteDays : Instant
]
static constraints = {
}
}

Hopefully I'm not missing something in your question but I've done things like this:
Create a class called MyInstant and use it in the hasMany
import org.joda.time.Instant
class MyInstant {
Instant myInstant
//anything else you might need
}
class Foo {
MyInstant birthday
Set favoriteDays = []
static hasMany = [favoriteDays: MyInstant]
}
I've tested this in the FooController:
import org.joda.time.Instant
class FooController {
def save() {
def fooInstance = new Foo(params)
.addToFavoriteDays(new MyInstant(myInstant: new Instant()))
.addToFavoriteDays(new MyInstant(myInstant: new Instant()))
.addToFavoriteDays(new MyInstant(myInstant: new Instant()))
if (!fooInstance.save(flush: true)) {
render(view: "create", model: [fooInstance: fooInstance])
return
}
flash.message = message(code: 'default.created.message', args: [message(code: 'foo.label', default: Foo'), fooInstance.id])
redirect(action: "show", id: fooInstance.id)
}
}
Everything saves correctly and the show action then shows the new Foo with all the instants. I've tested this on H2 and MySql.

Related

Grails Reusable Service for saving Domain Objects

I have a Grails project with multiple Domain Classes, and I want to make a persistence service as reusable as possible by only having one save() inside of it. To try and achieve this I have done the following in my project.
//PersistenceService.groovy
#Transactional
class PersistenceService {
def create(Object object) {
object.save flush: true
object
}
//BaseRestfulController
class BaseRestfulController extends RestfulController {
def persistenceService
def save(Object object) {
persistenceService.create(object)
}
//BookController
class BookController extends BaseRestfulController {
private static final log = LogFactory.getLog(this)
static responseFormats = ['json', 'xml']
BookController() {
super(Book)
}
#Transactional
def save(Book book) {
log.debug("creating book")
super.save(book)
}
So basically I have a bunch of domains for example Author etc, each with their own controller similar to the bookController. So is there a way to reuse the service for persistence like I am trying above?
Thank you
I'm doing something similar, but mainly because all my entities are not actually removed from the database but rather "marked" as removed. For several apps you need such an approach since it's critical to prevent any kind of data loss.
Since most databases do not provide support for this scenario, you can't rely on foreign keys to remove dependent domain instances when removing a parent one.
So I have a base service class called GenericDomainService which has methods to save, delete (mark), undelete (unmark).
This service provides a basic implementation which can be applied to any domain.
class GenericDomainService {
def save( instance ) {
if( !instance || instance.hasErrors() || !instance.save( flush: true ) ) {
instance.errors.allErrors.each {
if( it instanceof org.springframework.validation.FieldError ) {
log.error "${it.objectName}.${it.field}: ${it.code} (${it.rejectedValue})"
}
else {
log.error it
}
}
return null
}
else {
return instance
}
}
def delete( instance, date = new Date() ) {
instance.dateDisabled = date
instance.save( validate: false, flush: true )
return null
}
def undelete( instance ) {
instance.dateDisabled = null
instance.save( validate: false, flush: true )
return null
}
}
Then, in my controller template I always declare two services: the generic plus the concrete (which may not exist):
def ${domainClass.propertyName}Service
def genericDomainService
Which would translate for a domain called Book into:
def bookService
def genericDomainService
Within the controller methods I use the service like:
def service = bookService ?: genericDomainService
service.save( instance )
Finally, the service for a given domain will inherit from this one providing (if needed) the custom logic for these actions:
class BookService extends GenericDomainService {
def delete( instance, date = new Date() ) {
BookReview.executeUpdate( "update BookReview b set b.dateDisabled = :date where b.book.id = :bookId and b.dateDisabled is null", [ date: date, bookId: instance.id ] )
super.delete( instance, date )
}
def undelete( instance ) {
BookReview.executeUpdate( "update BookReview b set b.dateDisabled = null where b.dateDisabled = :date and b.book.id = :bookId", [ date: instance.dateDisabled, bookId: instance.id ] )
super.undelete( instance )
}
}
Hope that helps.

Grails share a GSP with multiple user

I having a GSP when it is accessed by two or more user at same time, It will throw
Row was updated or deleted by another transaction
Is there any way to share the render safely
Note: There is no update or save operation while rendering
Dude ,Have you tired on the action who updates ,list and read or connected with the row can be
#Transactional or do some concurrencyStuff exception handling
//Assume your domains are implemented just like or to be like this
class Author {
String name
Integer age
static hasMany = [books: Book]
}
//option one in your controllers or service class
Author.withTransaction { status ->
new Author(name: "Stephen King", age: 40).save()
status.setRollbackOnly()
}
Author.withTransaction { status ->
new Author(name: "Stephen King", age: 40).save()
}
//or
#Transactionl
def AuthorController () {
[list:list]
}
//or define a service like this
import org.springframework.transaction.annotation.Transactional
class BookService {
#Transactional(readOnly = true)
def listBooks() {
Book.list()
}
#Transactional
def updateBook() {
// …
}
def deleteBook() {
// …
}
}
for more visit : I hope this will be a bit useful ,Buddy!

Grails clear hasMany entries and add new ones error?

I am currently working on a grails applications and I have a list of addresses that are attached to an account. Basically what I want to do is when the Account is edited is displays a current list of all the attached Addresses and then I can delete/add as many as I want from the view. When this data is captured it is picked up by the controller and what I want to do is to be able to clear all of the current Addresses from this account and then create the list again with what exists on the view, my code is below:
Account Domain:
class Account {
String name
Date dateCreated
Date lastUpdated
static hasMany = [addresses:Addresses]
static mapping = {
addresses cascade:"all-delete-orphan"
}
def getAddressesList() {
return LazyList.decorate(
addresses,
FactoryUtils.instantiateFactory(Addresses.class))
}
static constraints = {
name(blank:false, unique: true)
}
}
Address Domain:
class Addresses {
int indexVal
String firstLine
String postcode
String area
static belongsTo = [account:Account]
static mapping = {
}
static transients = [ 'deleted' ]
static constraints = {
indexVal(blank:false, min:0)
}
}
Account Controller:
def update() {
def accountInstance = Account.get(params.id)
if (!accountInstance) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'account.label', default: 'Account'), params.id])
redirect(action: "list")
return
}
if (params.version) {
def version = params.version.toLong()
if (accountInstance.version > version) {
accountInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
[message(code: 'subscriptions.label', default: 'Subscriptions')] as Object[],
"Another user has updated this Account while you were editing")
render(view: "edit", model: [accountInstance: accountInstance])
return
}
}
accountInstance.properties = params
accountInstance.addresses.clear()
accountInstance.save(flush: true)
....
}
Error:
A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: com.tool.Account.addresses. Stacktrace follows:
Message: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: com.tool.Account.addresses
This error seems to be occurring in the controller on line:
accountInstance.save(flush: true)
I have tried several different way to get this to work and would really appreciate some help.
So it seems like you have done some work that Grails can do for you.
class Account {
String name
Date dateCreated
Date lastUpdated
List addresses
static hasMany = [addresses:Address]
static mapping = {
addresses cascade:"all-delete-orphan"
}
static constraints = {
name(blank:false, unique: true)
}
}
class Address {
String firstLine
String postcode
String area
static belongsTo = [account:Account]
}
This will produce the effect you want of having addresses being a list.
I've found either
instance.addresses = null
or
instance.addresses.clear()
to work for me
When you define addresses cascade:"all-delete-orphan" in Account class you don't need static belongsTo = [account:Account] in Addresses. So just try to remove that statement and test your code. See related link.

How to save associated object in Grails?

I am a grails beginner.
i have a 2domain class
class Employee {
String name
String department
static constraints = {
}
public String toString() {
name
}
}
class Address {
String line1
String line2
Employee employee
static belongsTo = Employee
static constraints = {
}
}
where Address belongs to Employee .. so i have given belongsTo association.
My Employee/create.gsp page takes input for fields specified in Employee and Address.
so on creation of employee , address must be get save automatically .
so what could be the save action in EmployeeController
i have tried some thing like this but did not work.
def save = {
def employeeInstance = new Employee(params)
def addressInstance = new Address(params)
if (employeeInstance.save(flush: true)) {
flash.message = "${message(code: 'default.created.message', args: [message(code: 'employee.label', default: 'Employee'), employeeInstance.id])}"
redirect(action: "show", id: employeeInstance.id)
}
else {
render(view: "create", model: [employeeInstance: employeeInstance])
}
}
how to save this associated model ?
Here you have a one-to-one relationsip - add an address property to the Employee class.
class Employee {
String name
String department
Address address
public String toString() {
name
}
}
Change your belongsTo of the Address like this:
class Address {
String line1
String line2
static belongsTo = [employee: Employee]
}
Now you could create an Employee like this:
def employeeInstance = new Employee(params)
employeeInstance.address = new Address(params)
if (employeeInstance.save(flush: true)) {
// your logic
}
Read the docs (one-to-one relationship) for further informations.

How to can I provide my own custom workflow when saving a Grails domain class?

I'm playing around with Grails and Groovy in Eclipse STS, using the quick shortcut commands to quickly generate domain objects and controller. For instance, I created a simple Trip booking application, generated code is as follows...
class Trip {
String name
String city
Date startDate
Date endDate
String purpose
String notes
}
Controller class shortened to show only save part...
class TripController {
def save = {
def tripInstance = new Trip(params)
if (tripInstance.save(flush: true)) {
flash.message = "${message(code: 'default.created.message', args: [message(code: 'trip.label', default: 'Trip'), tripInstance.id])}"
redirect(action: "show", id: tripInstance.id)
}
else {
render(view: "create", model: [tripInstance: tripInstance])
}
}
There is no save() method in the Trip domain object, I'm assuming it's created dynamically and saves to the internal HSQL database. I want to know how I can override the save method and provide my own implementation, or, instead of doing that, should I just change the controller code directly and provide my own logic for saving?

Resources