Home > Blockchain >  Getting "No Session found for current thread" error while using multiple data sources usin
Getting "No Session found for current thread" error while using multiple data sources usin

Time:09-12

I am trying to build an application in Micronaut using gorm with multiple data sources.

Micronaut version is 3.6.2.

When I try to fetch data getting below error:

org.springframework.dao.DataAccessResourceFailureException: Could not obtain current Hibernate Session; nested exception is org.hibernate.HibernateException: No Session found for current thread
    at org.grails.orm.hibernate.GrailsHibernateTemplate.getSession(GrailsHibernateTemplate.java:335)
    at org.grails.orm.hibernate.GrailsHibernateTemplate.doExecute(GrailsHibernateTemplate.java:284)
    at org.grails.orm.hibernate.GrailsHibernateTemplate.get(GrailsHibernateTemplate.java:364)
    at org.grails.orm.hibernate.AbstractHibernateGormStaticApi.get(AbstractHibernateGormStaticApi.groovy:120)
    at org.grails.datastore.gorm.GormEntity$Trait$Helper.get(GormEntity.groovy:553)
    at org.grails.datastore.gorm.GormEntity$Trait$Helper$get.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:148)
    at com.example.domain.Book.get(Book.groovy)
    at com.example.service.$BookServiceImplementation.$tt__get(BookService.groovy)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:107)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1268)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1035)
    at org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:1029)
    at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:1012)
    at org.codehaus.groovy.runtime.InvokerHelper.invokeMethodSafe(InvokerHelper.java:101)
    at com.example.service.$BookServiceImplementation$_get_closure1.doCall(BookService.groovy)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:107)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:274)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1035)
    at groovy.lang.Closure.call(Closure.java:412)
    at groovy.lang.Closure.call(Closure.java:428)

You can find the source code below:

build.gradle

plugins {
    id("groovy") 
    id("com.github.johnrengelman.shadow") version "7.1.2"
    id("io.micronaut.application") version "3.5.3"
    id("io.micronaut.test-resources") version "3.5.3"
}

version = "0.1"
group = "com.example"

repositories {
    mavenCentral()
}

dependencies {

    implementation("io.micronaut:micronaut-http-client")
    implementation("io.micronaut:micronaut-jackson-databind")
    implementation("io.micronaut:micronaut-management")
    implementation("io.micronaut.beanvalidation:micronaut-hibernate-validator")
    implementation("io.micronaut.groovy:micronaut-hibernate-gorm")
    implementation("io.micronaut.groovy:micronaut-runtime-groovy")
    implementation("io.micronaut.sql:micronaut-jdbc-hikari")
    compileOnly("io.micronaut:micronaut-http-validation")
    runtimeOnly("ch.qos.logback:logback-classic")
    runtimeOnly("mysql:mysql-connector-java")
    runtimeOnly("org.apache.tomcat:tomcat-jdbc")
    implementation("io.micronaut:micronaut-validation")
    annotationProcessor "io.micronaut:micronaut-inject-java"
    annotationProcessor "io.micronaut:micronaut-inject-groovy"
    implementation("io.micronaut.security:micronaut-security-jwt")
}


application {
    mainClass.set("com.example.Application")
}
java {
    sourceCompatibility = JavaVersion.toVersion("1.8")
    targetCompatibility = JavaVersion.toVersion("1.8")
}

graalvmNative.toolchainDetection = false
micronaut {
    runtime("netty")
    testRuntime("junit5")
    processing {
        incremental(true)
        annotations("com.example.*")
    }
    testResources {
        additionalModules.add("jdbc-mysql")
    }
}

Controller

package com.example.web.controller

import com.example.domain.Book
import com.example.service.BookService
import grails.gorm.transactions.Transactional
import io.micronaut.http.HttpResponse
import io.micronaut.http.MediaType
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.annotation.PathVariable
import io.micronaut.security.annotation.Secured
import io.micronaut.security.rules.SecurityRule
import jakarta.inject.Inject

@Controller("/book")
@Secured(SecurityRule.IS_ANONYMOUS)
class BookController {

    @Inject
    BookService bookService

    @Get(uri = '/{id}', produces = MediaType.APPLICATION_JSON)
    @Transactional
    HttpResponse<?> getBook(@PathVariable Long id) {
        Book book = bookService.get(id)
        HttpResponse.ok(booko)
    }

}

Service

package com.example.service

import com.example.domain.Book
import grails.gorm.services.Service

@Service(Book)
interface BookService {

    Book get(Serializable id)

}

Domain

package com.example.domain

import grails.gorm.annotation.Entity

@Entity
class Book {

    String name
    int pages

    static mapping = {
        version false
        datasource 'olap'
    }

}

UPDATE:

I have tried service like below as well, but no luck.

package com.example.service

import com.example.domain.Book
import grails.gorm.transactions.Transactional
import jakarta.inject.Singleton

@Transactional
@Singleton
class BookService {

    Book get(Long bookId) {
        Book.findById(bookId)
    }

}

UPDATE 2:

Getting "No Session found for current thread" error occurring only when accessing second data source. Seems like this error is related to multiple data source.

Can someone provide right configuration for multiple data sources with gorm.

CodePudding user response:

Here the issue is happening only when we try to access domains that are configured with the second data source.

In the above example Book domain is configured with second data source called olap.

static mapping = {
    version false
    datasource 'olap'
}

But in the service I added just @Transactional. That means service uses default data source. But Book domain has olap data source. Because of that we are getting No session found error.

To fix this I have added @Transactional(connection="olap") to the method which accesses Book domain. So that both domain & service will use same data source.

After fix my service class looks as below:

package com.example.service

import com.example.domain.Book
import grails.gorm.transactions.Transactional
import jakarta.inject.Singleton

@Transactional
@Singleton
class BookService {

    @Transactional(connection="olap")
    Book get(Long bookId) {
        Book.findById(bookId)
    }

}

  • Related