В нашем проекте мы видим, что наш сеанс Hibernate по умолчанию кажется потерянным при добавлении другого существующего файла войны во встроенный контейнер tomcat при загрузке Grails/Spring.
Как только мы прокомментируем оператор, чтобы добавить файл войны, все работает как положено. Когда мы развертываем приложение в рабочей среде, этой проблемы не существует, в любом случае файл войны, который мы пытаемся добавить при разработке, также запускается в рабочей среде.
Мы используем Grails 3.3.1, созданную при загрузке Spring, и таким образом добавляем существующий файл войны во встроенный кот через файл Applications.groovy.
class Application extends GrailsAutoConfiguration implements EnvironmentAware {
static void main(String[] args) {
GrailsApp.run(Application, args)
}
@Bean
EmbeddedServletContainerFactory servletContainerFactory() {
return new TomcatEmbeddedServletContainerFactory() {
@Override
protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) {
try {
// Ensure that the folder exists
tomcat.getHost().getAppBaseFile().mkdir()
String projektrod = System.getProperty('user.dir')
// Add external Orbeon war file
Context context = tomcat.addWebapp("/blanketdesigner/orbeon", "${projektrod}\\..\\blanket-orbeon-plugin\\orbeon\\orbeon.war")
context.setParentClassLoader(getClass().getClassLoader())
} catch (ServletException ex) {
throw new IllegalStateException("Failed to add webapp", ex)
}
return super.getTomcatEmbeddedServletContainer(tomcat)
}
}
}
Когда вышеперечисленное установлено, и приложение, и внешний файл войны запускаются и работают должным образом, но мы должны вызывать .withTransaction, .withNewTransaction, .withNewSession или что-то подобное для объектов домена.
Это также происходит для сервисов, которые помечены @Transactional. Если мы этого не делаем, возникает следующее исключение:
No Session found for current thread. Stacktrace follows:
java.lang.reflect.InvocationTargetException: null
at org.grails.core.DefaultGrailsControllerClass$ReflectionInvoker.invoke(DefaultGrailsControllerClass.java:211)
at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:188)
at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.hibernate.HibernateException: No Session found for current thread
at org.grails.orm.hibernate.GrailsSessionContext.currentSession(GrailsSessionContext.java:117)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:688)
at org.grails.orm.hibernate.HibernateSession.createQuery(HibernateSession.java:177)
at org.grails.orm.hibernate.HibernateSession.createQuery(HibernateSession.java:170)
at org.grails.datastore.gorm.finders.FindAllByFinder.buildQuery(FindAllByFinder.java:63)
И если мы удалим строку, которая добавляет файл войны
tomcat.addWebapp("....")
Все работает так, как ожидалось, и мы можем работать с объектами предметной области без вызова .with...
Как упоминалось ранее, эта проблема, по-видимому, связана со встроенным сервером tomcat и функцией добавления файла войны рядом.
Мы не хотим вызывать .with... по всему коду, так как это неправильное решение.
Почему мы должны добавить файл войны во встроенный tomcat при разработке, потому что наше основное приложение зависит от другой войны для работы всех функций. На рабочем сервере он также работает как отдельное веб-приложение.
Мы можем жить с исправлением для подключения сеанса гибернации по умолчанию, когда среда находится в разработке, но я не могу понять, как это сделать.
Думая о чем-то подобном
if(grails.util.Environment.current == grails.util.Environment.DEVELOPMENT) {
// Then bind new default session to current thread
}
Это должно быть легко воспроизвести.
Будем признательны за любую помощь или предложение
Спасибо