"No transaction is in progress" error while following Grails Spring Security Core tutorial
Asked Answered
S

2

9

I'm following the Grails Spring Security Core tutorial in their documentation. When I reach 24.1.5.5, the problems start. I'm instructed to modify Bootstrap.groovy to the following, then run the app:

package com.mycompany.myapp

class BootStrap {

   def init = {

         def adminRole = new Role(authority: 'ROLE_ADMIN').save()

         def testUser = new User(username: 'me', password: 'password').save()

         UserRole.create testUser, adminRole

         UserRole.withSession {
            it.flush()
            it.clear()
         }

         assert User.count() == 1
         assert Role.count() == 1
         assert UserRole.count() == 1

   }
}

Running the app gives me this error:

2020-03-31 15:46:19.294 ERROR --- [ restartedMain] o.s.boot.SpringApplication : Application run failed

javax.persistence.TransactionRequiredException: no transaction is in progress at org.hibernate.internal.SessionImpl.checkTransactionNeeded(SessionImpl .java:3586)

I've attempted to use @Transactional to solve this, but it had no impact on the error. Reverting Bootstrap.groovy to its default allows the application to run normally. What is missing (or incorrect) from this tutorial that is causing it to fail?

Senecal answered 31/3, 2020 at 7:56 Comment(0)
M
17

The documentation is out of date. Hibernate 5.2+ requires transactions for write operations now. Adding the @Transactional did not work because init is a closure and the annotation applies to methods or classes.

Create a new method in bootstrap and add transactional to it. then call it from your init closure. For example.

class BootStrap {

    def init = {
        addTestUsers()
    }

    @Transactional
    void addTestUsers() {
        def adminRole = new Role(authority: 'ROLE_ADMIN').save()

        def testUser = new User(username: 'me', password: 'password').save()

        UserRole.create testUser, adminRole

        UserRole.withSession {
           it.flush()
           it.clear()
        }

        assert User.count() == 1
        assert Role.count() == 1
        assert UserRole.count() == 1
    } 
}
Maiduguri answered 31/3, 2020 at 13:6 Comment(10)
I've created a PR to update the docs github.com/grails-plugins/grails-spring-security-core/pull/613Maiduguri
I'm afraid this results in the same error for me. Is there additional configuration that needs to be done before this point?Senecal
What database are you using/configured? I assumed you were using a hibernate datasource.Maiduguri
I'm using a mysql database, with the com.mysql.jdbc.Driver driver and org.hibernate.dialect.MySQL5InnoDBDialect dialect.Senecal
Hmm, sorry I can't reproduce - if you upload a project to github or something it may help identify the issue.Maiduguri
Here's a blank project other than the tutorial's instructions, the database info, and your suggested modification: github.com/dylan-goss/securitytestSenecal
github.com/dylan-goss/securitytest/blob/master/grails-app/init/… - you are using spring's transactional - please use GORM's and all should work :)Maiduguri
That did it! 16 years of PHP is catching up with me.Senecal
I found the same problem in an abstract DataService, to override the save method. Why? I dunno.Casimir
also the default generator seems to use import org.springframework.transaction.annotation.Transactional . I changed to import grails.gorm.transactions.Transactional and it workedUpland
A
2

You can also try the solution in https://github.com/grails/grails-core/issues/11376, where say that you can add to application.yml the config

hibernate:
    allow_update_outside_transaction: true
Autophyte answered 11/12, 2020 at 15:52 Comment(1)
It's not the best solution, but it worksCroner

© 2022 - 2024 — McMap. All rights reserved.