1

I'm trying to create some threads in a service, but I got the hibernateException: no session... . I have already seen a discussion about this in stackoverflow with a solution of throwing RuntimeException. In my case is not working. Here is my service code:

class MatchService { static transactional = true def void start(Match match) { Thread.start { Match updateMatch = matchSituation(match) if(!updateMatch.save()) { throw new RuntimeException("match is not valid and cannot be saved!") } } } def Match matchSituation(Match m) { Random random = new Random() if(m.teamH.averagePlayerValue > m.teamA.averagePlayerValue) { m.golTeamH = random.nextInt(5) } else { m.golTeamA = random.nextInt(4) } return m } } 

job class:

 class TestJob { def matchService List<Match> matchList = new ArrayList() static triggers = { cron name: 'trigger', cronExpression: "0 0/1 15 ? * WED" } def group = "threadGroup" def execute() { Cal.get(1).matches.each{ match -> matchList.add(match) } for(Match m: matchList) { if(!m.validate()) { throw new MatchException( message: "match not valid!!" , match:m) } matchService.start(m) } } } 

EDIT

With backgroundThread plugin (that should handle hibernate sessione):

 backgroundService.execute("Calculating match", { def backgroundMatch = match backgroundMatch = matchSituation(backgroundMatch) if(!backgroundMatch.save()) { throw new RuntimeException("match is not valid and cannot be saved!") } }) 

I get this error ERROR events.PatchedDefaultFlushEventListener - Could not synchronize database state with session

4 Answers 4

4

We're using the quartz plugin which works fine.

I have had the same problem before in a different case and what solved it was wrapping the domain access code in

DomainClass.withTransaction { } 

For example:

def execute() { Cal.withTransaction { Cal.get(1).matches.each{ match -> matchList.add(match) } for(Match m: matchList) { if(!m.validate()) { throw new MatchException( message: "match not valid!!" , match:m) } matchService.start(m) } } } 
Sign up to request clarification or add additional context in comments.

4 Comments

In my case it doesn't solve the problem, I get this exception: ERROR hibernate.LazyInitializationException - could not initialize proxy - no Session org.hibernate.LazyInitializationException: could not initialize proxy - no Session maybe something is wrong with the service, I have tried any possible solution with no success -.-
Try something along the lines of this: applicationContext.getBean("transactionManager").getTransaction(new DefaultTransactionDefinition()), but I you'll need to pull the correct applicationContext as well as commit the transaction at the end.
Or look at: grails.org/plugin/quartz which has pretty much the same syntax as the Background Plugin but at least in our case, it just works.
A solution could be also creating like 5 trigger with quartz and then use them like threads. But my question is, is it possible to make a trigger doing something different from the other? because I see just more trigger at different or same time doing execute()....
1

The lazily Exceptions from Hibernate can be fixed by setting the fetchmode in Domain-class to eager.

Comments

0

I think your problem is in passing the actual domain object to the thread. Try just passing the domain object ID to the function, and obtaining and saving inside that function/thread. Passing a domain object to another thread can cause problems.

1 Comment

I have tried how you say, but it's the same as pass the object...could not initialize proxy - no session...I hate hibernate...
0

now is working. Here are the changes I made:

class TestJob { def matchService List<Match> matchList = new ArrayList() static triggers = { cron name: 'trigger', cronExpression: "0 0/1 13 ? * THU" } def group = "threadGroup" def execute() { Cal.get(1).matches.each{ match -> matchList.add(match) } for(Match m: matchList) { if(!m.validate()) { throw new MatchException( message: "match not valid!!" , match:m) } matchService.run(m.id) } } } class MatchService { static transactional = true // Match updateMatch def backgroundService public void run(Long matchId) { backgroundService.execute("Calculating match", { def backgroundMatch = Match.findById(matchId) backgroundMatch = matchSituation(backgroundMatch) println backgroundMatch.teamH.name + " - " + backgroundMatch.teamA.name + ": " + backgroundMatch.golTeamH + " - " + backgroundMatch.golTeamA if(!backgroundMatch.save()) { throw new RuntimeException("match is not valid and cannot be saved!") } }) // Thread.start { // println "run thread (" + matchId + ") : " + String.format('%tH:%<tM:%<tS.%<tL',System.currentTimeMillis()) // this.updateMatch = matchSituation(Match.findById(matchId)) // println updateMatch.teamH.name + " - " + updateMatch.teamA.name + ": " + updateMatch.golTeamH + " - " + updateMatch.golTeamA // if(!updateMatch.save(flush: true)) { // throw new RuntimeException("match is not valid and cannot be saved!") // } // } } def Match matchSituation(Match m) { Random random = new Random() if(m.teamH.averagePlayerValue > m.teamA.averagePlayerValue) { m.golTeamH = random.nextInt(5) } else { m.golTeamA = random.nextInt(4) } return m } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.