title: Grails 3.3.9 No Session found for current thread
body: <p>I'm using grails 3.3.9 with a sql server db. I'm using default scaffold-ed code for my domain class. When I hit the index page, I get the <code>No Session found for current thread</code> error. For using the default scaffold-ed code, I'm a bit stumped as to why this is happening. In Grails 2.x once I scaffold the app just works. Anyway here is my code and hopefully someone can shed some light on what I don't obviously know:</p>
  
  <p><strong>application.yml</strong></p>
  
  <pre><code>hibernate:
      cache:
          queries: false
          use_second_level_cache: false
          use_query_cache: false
  dataSource:
      pooled: true
      jmxExport: true
      driverClassName: org.h2.Driver
      username: sa
      password: ''
  
  environments:
      development:
          dataSource:
              dbCreate: create-drop
              url: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
          dataSources:
              tst:
                  dbCreate: update
                  url: jdbc:sqlserver://TESTSERVER;databaseName=Technician;useNTLMv2=true
                  driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
                  dialect: org.hibernate.dialect.SQLServer2012Dialect
                  pooled: true
                  username: user
                  password: 'pass'
                  formatSql: true
                  logSql: true
      test:
          dataSource:
              dbCreate: update
              url: jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
      production:
          dataSource:
              dbCreate: none
              url: jdbc:h2:./prodDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
              properties:
                  jmxEnabled: true
                  initialSize: 5
                  maxActive: 50
                  minIdle: 5
                  maxIdle: 25
                  maxWait: 10000
                  maxAge: 600000
                  timeBetweenEvictionRunsMillis: 5000
                  minEvictableIdleTimeMillis: 60000
                  validationQuery: SELECT 1
                  validationQueryTimeout: 3
                  validationInterval: 15000
                  testOnBorrow: true
                  testWhileIdle: true
                  testOnReturn: false
                  jdbcInterceptors: ConnectionState
                  defaultTransactionIsolation: 2 # TRANSACTION_READ_COMMITTED
  </code></pre>
  
  <p><strong>build.gradle</strong></p>
  
  <pre><code>buildscript {
      repositories {
          mavenLocal()
          maven { url "https://repo.grails.org/grails/core" }
      }
      dependencies {
          classpath "org.grails:grails-gradle-plugin:$grailsVersion"
          classpath "org.grails.plugins:hibernate5:${gormVersion-".RELEASE"}"
          classpath "com.bertramlabs.plugins:asset-pipeline-gradle:2.15.1"
      }
  }
  
  version "0.1"
  group "tstsupport"
  
  apply plugin:"eclipse"
  apply plugin:"idea"
  apply plugin:"war"
  apply plugin:"org.grails.grails-web"
  apply plugin:"asset-pipeline"
  apply plugin:"org.grails.grails-gsp"
  
  repositories {
      mavenLocal()
      maven { url "https://repo.grails.org/grails/core" }
  }
  
  dependencies {
      compile "org.springframework.boot:spring-boot-starter-logging"
      compile "org.springframework.boot:spring-boot-autoconfigure"
      compile "org.grails:grails-core"
      compile "org.springframework.boot:spring-boot-starter-actuator"
      compile "org.springframework.boot:spring-boot-starter-tomcat"
      compile "org.grails:grails-web-boot"
      compile "org.grails:grails-logging"
      compile "org.grails:grails-plugin-rest"
      compile "org.grails:grails-plugin-databinding"
      compile "org.grails:grails-plugin-i18n"
      compile "org.grails:grails-plugin-services"
      compile "org.grails:grails-plugin-url-mappings"
      compile "org.grails:grails-plugin-interceptors"
      compile "org.grails.plugins:cache"
      compile "org.grails.plugins:async"
      compile "org.grails.plugins:scaffolding"
      compile "org.grails.plugins:events"
      compile "org.grails.plugins:hibernate5"
      compile "org.hibernate:hibernate-core:5.1.16.Final"
      compile "org.grails.plugins:gsp"
      console "org.grails:grails-console"
      profile "org.grails.profiles:web"
      runtime "org.glassfish.web:el-impl:2.1.2-b03"
      runtime "com.h2database:h2"
      runtime "org.apache.tomcat:tomcat-jdbc"
      runtime "com.bertramlabs.plugins:asset-pipeline-grails:2.15.1"
      runtime "com.microsoft.sqlserver:mssql-jdbc:7.2.1.jre8"
      testCompile "org.grails:grails-gorm-testing-support"
      testCompile "org.grails.plugins:geb"
      testCompile "org.grails:grails-web-testing-support"
      testRuntime "org.seleniumhq.selenium:selenium-htmlunit-driver:2.47.1"
      testRuntime "net.sourceforge.htmlunit:htmlunit:2.18"
  }
  
  bootRun {
      jvmArgs('-Dspring.output.ansi.enabled=always')
      addResources = true
      String springProfilesActive = 'spring.profiles.active'
      systemProperty springProfilesActive, System.getProperty(springProfilesActive)
  }
  
  
  assets {
      minifyJs = true
      minifyCss = true
  }
  </code></pre>
  
  <p>Domain class: <code>TST_Customer.groovy</code></p>
  
  <pre><code>package TSTSupport
  
  class TST_Technician {
      String techCode
      String techName
      boolean tec990Flag
      boolean tecCCFlag
      Date tecCreateDate
      String tecCreatedBy
      Date tecModifyDate
      String tecModifiedBy
      boolean tecActiveFlag
  
  
  
      static constraints = {
          techCode shared: "techCode"
          techName blank: false, maxSize: 75
          tecCreatedBy blank: false, maxSize: 35
          tecModifyDate nullable: true
          tecModifiedBy blank: false, maxSize: 35
      }
  
      static mapping = {
          datasource "tst"
          table name: "lkp_Technician", schema: "dbo", catalog: "Technician"
          version false
  
          id generator: 'assigned', name: 'techCode', type: 'string'
          techCode column: '[TechnicianCode]'
          techName column: '[TechnicianName]'
          tec990Flag column: '[Tech990Flag]'
          tecCCFlag column: '[TechCCFlag]'
          tecCreateDate column: '[TechCreateDate]'
          tecCreatedBy column: '[TechCreatedBy]'
          tecModifyDate column: '[TechModifyDate]'
          tecModifiedBy column: '[TechModifiedBy]'
          tecActiveFlag column: '[TechActiveFlag]'
  
  
      }
  }
  </code></pre>
  
  <p>Controller</p>
  
  <pre><code>package TSTSupport
  
  import grails.validation.ValidationException
  import static org.springframework.http.HttpStatus.*
  
  class TST_CustomerController {
  
      TST_CustomerService TST_CustomerService
  
      static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
  
      def index(Integer max) {
          params.max = Math.min(max ?: 10, 100)
          respond TST_CustomerService.list(params), model:[TST_CustomerCount: TST_CustomerService.count()]
      }
  
      def show(Long id) {
          respond TST_CustomerService.get(id)
      }
  
      def create() {
          respond new TST_Customer(params)
      }
  
      def save(TST_Customer TST_Customer) {
          if (TST_Customer == null) {
              notFound()
              return
          }
  
          try {
              TST_CustomerService.save(TST_Customer)
          } catch (ValidationException e) {
              respond TST_Customer.errors, view:'create'
              return
          }
  
          request.withFormat {
              form multipartForm {
                  flash.message = message(code: 'default.created.message', args: [message(code: 'TST_Customer.label', default: 'TST_Customer'), TST_Customer.id])
                  redirect TST_Customer
              }
              '*' { respond TST_Customer, [status: CREATED] }
          }
      }
  
      def edit(Long id) {
          respond TST_CustomerService.get(id)
      }
  
      def update(TST_Customer TST_Customer) {
          if (TST_Customer == null) {
              notFound()
              return
          }
  
          try {
              TST_CustomerService.save(TST_Customer)
          } catch (ValidationException e) {
              respond TST_Customer.errors, view:'edit'
              return
          }
  
          request.withFormat {
              form multipartForm {
                  flash.message = message(code: 'default.updated.message', args: [message(code: 'TST_Customer.label', default: 'TST_Customer'), TST_Customer.id])
                  redirect TST_Customer
              }
              '*'{ respond TST_Customer, [status: OK] }
          }
      }
  
      def delete(Long id) {
          if (id == null) {
              notFound()
              return
          }
  
          TST_CustomerService.delete(id)
  
          request.withFormat {
              form multipartForm {
                  flash.message = message(code: 'default.deleted.message', args: [message(code: 'TST_Customer.label', default: 'TST_Customer'), id])
                  redirect action:"index", method:"GET"
              }
              '*'{ render status: NO_CONTENT }
          }
      }
  
      protected void notFound() {
          request.withFormat {
              form multipartForm {
                  flash.message = message(code: 'default.not.found.message', args: [message(code: 'TST_Customer.label', default: 'TST_Customer'), params.id])
                  redirect action: "index", method: "GET"
              }
              '*'{ render status: NOT_FOUND }
          }
      }
  }
  </code></pre>
  
  <p>Service</p>
  
  <pre><code>package TSTSupport
  
  import grails.gorm.services.Service
  
  @Service(TST_Customer)
  interface TST_CustomerService {
  
      TST_Customer get(Serializable id)
  
      List&lt;TST_Customer&gt; list(Map args)
  
      Long count()
  
      void delete(Serializable id)
  
      TST_Customer save(TST_Customer TST_Customer)
  
  }
  </code></pre>