Using domain classes as both persistent and transient? - grails

I am implementing a trading system, and I want to use the same code for both live trading and backtesting. When doing live trading, I need to persist everything that happens, but when backtesting, I would like to use the same classes and logic but not persist them (for speed and because I have no reason to store them).
I thought I could do this simply by not calling save() on them, but I've run into a problem. I have an Account class that includes a hasMany collection of Position objects. The trouble is that I need to find the right Position in the Account, but it seems that I can't, since it's never been saved. I tried iterating through the hasMany collection of Positions but there's nothing in there, even though I constructed a Position object and added it to the account with addToPositions(). I guess this won't be meaningful until after that call to save() that I'm trying to avoid.
Is there a way to reuse the same classes for both persistant and transient purposes, or am I trying to commit an unnatural act? I am open to any suggestions for how to reuse these classes in both scenarios.
Update (adding code samples):
Account.groovy:
class Account {
String name
static belongsTo = [user:S2User]
static hasMany = [positions:Position, transactions:Transaction]
}
SimAccount.groovy:
class SimAccount extends Account {
}
Position.groovy:
class Position implements Serializable {
String symbol
static belongsTo = [account:Account]
}
BacktestController.groovy:
// add Account
def acct = new SimAccount(name:"backtest")
// add position
def pos = new Position(symbol:'SIRI')
acct.addToPositions(pos)
Strategy.groovy:
println "apply($accounts, $quotes) [$name]"
accounts.each{ a ->
println " acct $a (${a?.name})"
a?.positions?.each{ p ->
println " pos: $p"
}
}
def siri = Position.findByAccountAndSymbol(accounts[0], 'SIRI')
println "siri pos: $siri"
The output from Strategy.groovy when the objects have been saved is
apply([com.lossless.account.SimAccount : 1, null], [:]) [Live SIRI 50k]
acct com.lossless.account.SimAccount : 1 (sim1)
pos: com.lossless.account.Position : 1
acct null (null)
siri pos: com.lossless.account.Position : 1
The output when the objects have not been saved is
apply([com.lossless.account.SimAccount : null, null], [bid:1.74, ask:1.74]) [Backtest SIRI 50k]
acct com.lossless.account.SimAccount : null (backtest)
pos: com.lossless.account.Position : null
acct null (null)
| Error 2013-01-21 03:11:11,984 [http-bio-8080-exec-2] ERROR errors.GrailsExceptionResolver - TransientObjectException occurred when processing request: [POST] /lossless/backtest/index - parameters:
object references an unsaved transient instance - save the transient instance before flushing: com.lossless.account.Account. Stacktrace follows:
Message: object references an unsaved transient instance - save the transient instance before flushing: com.lossless.account.Account
Line | Method
->> 105 | doCall in org.grails.datastore.gorm.GormStaticApi$_methodMissing_closure2
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 66 | apply in com.lossless.Strategy
Line 66 in Strategy.groovy is the call to Position.findByAccountAndSymbol().

Related

How to import service in Domain?

How to import service in Domain?
It has a field where I need to fill a field with a protocol. The protocol is automatically generated and created a service excluvivamente for this generation.
In the field in method 'AfterInsert' was inserted a call to this service that automatically populates the field.
I put on bootstrap the creation of some objects that need to be filled in your field with this protocol. But an error occurs which is apparently due to the use of 'Services' in 'Domain'. Could anyone help me?
class Post {
static transient postService
String conteudo
Date dataCriacao = new Date()
String protocolo
static constraints = {
dataCriacao(nullable:false, blank:false)
conteudo nullable:false, blank: false
protocolo nullable: true, blank: true
}
static mapping = {
conteudo type: 'text'
sort dataCriacao:"desc"
}
def afterInsert(){
if(!this.protocolo){
registraProtocolo()
}
}
protected void registraProtocolo() {
postService.teste(this)
}
}
Error: ERROR hibernate.AssertionFailure - an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
Message: null id in com.app.post.Post entry (don't flush the Session after an exception occurs)
Line | Method
->> 105 | doCall in org.grails.datastore.gorm.GormStaticApi$_methodMissing_closure2
Message: null id in com.app.post.Post entry (don't flush the Session after an exception occurs)
Line | Method
->> 105 | doCall in org.grails.datastore.gorm.GormStaticApi$_methodMissing_closure2
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 27 | recInsertProtocolo in com.app.post.PostService
| 83 | teste . . . . . . in ''
| 117 | registraProtocolo in com.app.post.Post
The postService shouldn't be static, it should be simply
transient postService
Problem Solved! It is a matter of logic. The service comes automatically setados as 'transational = true', using AfterInsert the error occurs due to this feature of the service. but if you use a closure 'withNewSession', this problem is solved and is allowed to change the attributes of objects with services once the new session will meet the requirement 'transational'. Just got my domain like this:
AfterInsert def () {
if (! this.protocolo) {
Post.withNewSession
{
registraProtocolo ()
}
}
}
protected void registraProtocolo () {
postService.teste (this)
}
Thank you all for the help
For those who want more information down a JIRA who helped me in this solution (read the comments)
class Post {
def postService
...
}
ref: http://grails.org/doc/2.1.0/guide/single.html#dependencyInjectionServices

Grails Multiple domain classes with belongsTo and default value

I have special case of domain classes structure where three classes presents and they are connected to chain: Event <- Room <- Projector. (All relation ships are one-to-one)
The implementation looks like:
class Event {
Room room
static constraints = {
room(nullable:false)
}
}
class Room {
Projector projector = new Projector()
static belongsTo = [event: Event]
static constraints = {
projector(nullable:false)
}
}
class Projector {
String something = "Something"
static belongsTo = [room: Room]
static constraints = {
room(nullable:false)
}
}
When I want to create Event with new Room I expect that the Projector will be created by default:
class TestController {
def index() {
Room room = new Room()
Event event = new Event(room: room)
event.save(flush: true, failOnError: true)
render event
}
}
I receive following exception
| Error 2012-07-11 16:09:12,541 [http-bio-8080-exec-3] ERROR errors.GrailsExceptionResolver - TransientObjectException occurred when processing request: [GET] /Test/room/index
object references an unsaved transient instance - save the transient instance before flushing: Projector. Stacktrace follows:
Message: object references an unsaved transient instance - save the transient instance before flushing: Projector
Line | Method
->> 46 | onApplicationEvent in org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 18 | index in RoomController
| 1110 | runWorker . . . . in java.util.concurrent.ThreadPoolExecutor
| 603 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 722 | run . . . . . . . in java.lang.Thread
It seems that cascading over three classes doesn't save default values. Is there any solution for that? Or what am I doing wrong?
There is an open jira for your issue at http://jira.grails.org/browse/GRAILS-4613?attachmentOrder=desc
Personally I would handle the creation of objects in my controller instead of doing it in the domain. You need to be able to call projector.save(flush:true).

Grails GORM: How to 'null' a property of a child in a one-to-many relationship?

I have a undirectional one to many relationship of two domain classes:
package net.peddn
class User {
static hasMany = [texts: Text]
String username
}
and
package net.peddn
class Text {
long creator
String title
static constraints = {
creator( nullable: true )
}
}
my User controller looks like this:
package net.peddn
class UserController {
static scaffold = true
def delete() {
def userInstance = User.get(params.id)
userInstance.texts.each { text ->
text.creator = null
}
userInstance.delete(flush: true)
}
my BootStrap.groovy looks like this:
import net.peddn.Text
import net.peddn.User
class BootStrap {
def init = { servletContext ->
User user = new User(username: "username")
user.save(flush: true)
Text text1 = new Text(title: "titel 1", creator: user.id)
Text text2 = new Text(title: "titel 2", creator: user.id)
user.addToTexts(text1)
user.addToTexts(text2)
user.save(flush: true)
}
def destroy = {
}
}
When I now try to delete my User I get the following error:
| Server running. Browse to http://localhost:8080/usertexts
| Error 2012-06-17 19:33:49,581 [http-bio-8080-exec-4] ERROR errors.GrailsExceptionResolver - IllegalArgumentException occurred when processing request: [POST] /usertexts/user/index - parameters:
id: 1
_action_delete: Löschen
Stacktrace follows:
Message: null
Line | Method
->> 21 | doCall in net.peddn.UserController$_delete_closure1
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 19 | delete in net.peddn.UserController
| 1110 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 603 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 722 | run . . . in java.lang.Thread
If i change the code to
text.creator = 0
in UserController.groovy is works perfectly.
By the way: I used this domain model because I don't want the Text objects to be deleted when a User will be deleted. But I also want to know who created the Text object. If someone has a better solution for this problem PLEASE let me know.
Thanks!
Peter
With your current implementation please try if this works:
def delete() {
def userInstance = User.get(params.id)
userInstance.texts.each { text ->
userInstance.removeFromTexts(text)
}
userInstance.delete(flush: true)
}
If you want bidirectional relation User-Texts and you don't want texts to be deleted when user is deleted you can change this behaviour. Check documentation section on cascades in Hibernate here: custom cascades. You can change mapping like this:
class User {
static hasMany = [texts: Text]
static mapping = {
texts cascade: "save-update"
}
}
Finally I found the right hint. It seems that this is a casting problem. see:
Groovy Primitive Type Cast Gotcha When Upgrading to Grails 2.0
So i changed the primitive "long" property of the Text domain class to its "boxed" version "Long":
package net.peddn
class Text {
Long creator
String title
static constraints = {
creator( nullable: true )
}
}
and now the property can be set to null!
Thank you Tomasz for your help!

How to save multiple object from one view using Grails

This question is in follow up to this post Grails one to many relationship view
The example suggested there is not working and throwing following exception at run time
null id in blog.omarello.Phone entry (don't flush the Session after an exception occurs). Stacktrace follows:
Message: null id in blog.omarello.Phone entry (don't flush the Session after an exception occurs)
Line | Method
->> 43 | doCall in blog.omarello.ContactController$_closure4$$ENLORkU6
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 886 | runTask in java.util.concurrent.ThreadPoolExecutor$Worker
| 908 | run . . in ''
^ 662 | run in java.lang.Thread
I think rather then making the example work can any one help me understand how can I create a GSP which can let me save multiple instances of same domain class. For example, a GSP which can let me insert multiple Book instances at once?
Once again, examine the project I linked on github. It is a demonstration of some of the one of the better practices for doing this. Particularly, look at the question/index, as this is what the view can look like. The actual saving piece is done in the QuestionService, used by the QuestionController. This project does exactly what you're trying to do. Review it.
Change the Contact class in the phone example as follows and it should work fine.
package blog.omarello
import org.apache.commons.collections.list.LazyList;
import org.apache.commons.collections.FactoryUtils;
class Contact {
static constraints = {
firstName(blank:false)
lastName(blank:false)
}
String firstName
String lastName
String nickName
List phones = LazyList.decorate(new ArrayList(),
FactoryUtils.instantiateFactory(Phone.class));
// List phones = new ArrayList()
static hasMany = [ phones:Phone ]
static mapping = {
phones cascade:"all-delete-orphan"
}
// def getPhonesList() {
// return LazyList.decorate(
// phones,
// FactoryUtils.instantiateFactory(Phone.class))
// }
def String toString() {
return "${lastName}, ${firstName}"
}
}

Grails Gorm : Object references an unsaved transient instance

I get the following Exception when saving an instance of Trip in Grails:
2011-01-26 22:37:42,801 [http-8090-5]
ERROR errors.GrailsExceptionResolver
- object references an unsaved transient instance - save the
transient instance before flushing: Rower
org.hibernate.TransientObjectException:
object references an unsaved transient
instance - save the transient instance
before flushing: Rower
The concept is simple: For a boattrip you need some rowers, a coxwain (is also a rower) and a boat:
Trip looks like (shortened):
class Trip {
Boat boat;
Rower coxwain;
static belongsTo = [Rower,Boat]
static hasMany = [rowers:Rower]
}
and Rower (shortened)
class Rower {
String firstname;
String name;
Rower reference;
static hasMany = [trips:Trip];
static mappedBy = [trips:"rowers"]
}
The trip then is saved in the controller like:
def save = {
def trip = new Trip(params)
// adding Rowers to Trip
if (params.rower instanceof String) {
def r = Rower.get(params?.rower)
if (r != null) {
trip.addToRowers(r)
}
} else {
params?.rower?.each{
rowerid ->
def r = Rower.get(rowerid)
log.info("rowerid (asList): " + rowerid)
if (r != null) {
trip.addToRowers(r)
}
}
}
// saving the new Trip -> EXCEPTION IN NEXT LINE
if(!trip.hasErrors() && trip.save(flush:true)) {
// ...
}
// ...
}
I think I have set the relations between the domains correct.
The Rower is not changed while it is added to the Trip. Why does Grails want it to save? why is it a transient instance?
Unfortunately this is an issue with the way GORM handles things, or more specifically the way that it expects that you deal with transients. If you don't persist the contained classes to the database first (Rowers in this case), you will get this exception every single time.
With GORM you have to save and attach in a bottom up fashion or when grails goes to flush the connection for the next instance you will get the transient instance exception. The instance is 'transient' because its just an in-memory reference. To persist the parent, GORM needs to link the parent to the child in the database. Without the child being persisted it has no way to do that, this is where the exception is coming from.
Wish there was better news. Not that its hard, but it gets annoying with complex hierarchies.
The Problem was somehow different.
it's in here:
def trip = new Trip(params)
which references a coxwain (of class Rower), which is not set (id=-1 is returned). This constructs a new Rower instead of a 'null' value. And this is the 'unsaved transient instance'.
If I check first for a valid instance, then it works :-)
Thanks for the help!
Just a quick note for anyone dealing with singular or multiple parameters with the same name, using the params.list("parameterName") helper you can always return a list
...
// adding Rowers to Trip
if (params.rower instanceof String) {
def r = Rower.get(params?.rower)
if (r != null) {
trip.addToRowers(r)
}
} else {
params?.rower?.each{
rowerid ->
def r = Rower.get(rowerid)
log.info("rowerid (asList): " + rowerid)
if (r != null) {
trip.addToRowers(r)
}
}
}
...
could become a bit groovier
...
// adding Rowers to Trip
for(rower in params.list("rower") {
def r = Rower.get(rower)
if(r) trip.addToRowers(r)
}
...
you can find it hiding away under 6.1.12 Simple Type Converters
At first I thought it was to do with cascading saves and belongsTo, as described in The Grails Reference section 5.2.1.3 and Gorm Gotchas part 2. However since the Rowers are already in the DB I think it should work. The domain model is complicated to me, what you need to do is simplify it and run some tests using Grails console (run grails console in your project directory). First create a basic many-to-many between Trip and Rower and get it to execute the desired code. Then add the other parts bit-by-bit, like Rower's reference to itself. I'm not sure that the mappedBy part is necessary at all.
I think you have to save the trip before you add the rover to the trip.
Also it make no sense to check if trip has errors before you validate and/or save it.
Try this:
if(trip.validate() && trip.save(flush:true)) {
if (r != null) {
trip.addToRowers(r)
}
}
In many use cases, you should be able to address this by applying the cascade setting to your collection:
static mapping = {
rowers cascade: 'all-delete-orphan'
}
https://docs.grails.org/latest/ref/Database%20Mapping/cascade.html
Suppose, you are using Trip is hasMany relationship with Rower
class Trip {
static hasMany = [rowers:Rower]
...
}
class Rower{
static belongsTo =[trips:Trip]
...
}
Actually, it's looking for new session. So we need to stop/rollback the current transaction then this error won't raise, For that
Try This,
def row = new Row()
row.save()
NOTE: this save won't affect your database. It's just for rollback the transaction.
I had this problem but the answer for me was much simpler - my first object had not saved properly because it didn't validate successfully.
I somehow didn't notice that the first object had not saved, and so the error was confusing to me.
While debugging the problem, I eventually noticed that the first object was not saving properly, and when I fixed that, the object references an unsaved transient instance problem went away.

Resources