how to set EntityManagerFactory through constructor by #PersistenceUnit annotation - spring

Does anyone know how to set EntityManagerFactory through constructor by #PersistenceUnit annotation. I could this through xml configuration. But i dont know the corresponding annotation configuration.
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml" />
<property name="persistenceUnitName" value="myUnit"></property>
<bean id="handler" class="com.handler.LocalHTHandler">
<constructor-arg ref="entityManagerFactory"></constructor-arg>
And it is working fine. Can we do it through annotation for my handler bean. I heard about #persistanceunit , but it can not be placed in constructor to achieve it. Is that correct?

As #Dherik said you can do this via constructor. Multi data source example below (tested on SpringBoot 2.0.4):
SomeRepository.java
#Repository
public class SomeRepository {
private final EntityManager entityManager;
public TestService(#Qualifier("someEntityManagerFactory") EntityManager entityManager) {
this.entityManager = entityManager;
}
}
SomeDatabaseConfig.java
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.orm.jpa.vendor.HibernateJpaDialect;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef = "someEntityManagerFactory")
#EnableConfigurationProperties(JpaProperties.class)
class SomeDatabaseConfig {
private static final String PERSISTENCE_UNIT = "some";
private static final String[] PACKAGES_TO_SCAN = {"package.where.you.store.your.entities"};
#Bean(name = "someDataSourceProps")
#ConfigurationProperties("some.datasource")
DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
#Bean(name = "someDataSource")
DataSource dataSource(#Qualifier("someDataSourceProps") DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
#Bean(name = "someEntityManagerFactory")
LocalContainerEntityManagerFactoryBean entityManagerFactory(
JpaProperties jpaProperties,
#Qualifier("someDataSource") DataSource dataSource,
#Qualifier("someJpaVendorAdapter") JpaVendorAdapter jpaVendorAdapter) {
return createEntityManagerFactory(jpaProperties, dataSource, jpaVendorAdapter, PERSISTENCE_UNIT, PACKAGES_TO_SCAN);
}
#Bean("someJpaVendorAdapter")
JpaVendorAdapter jpaVendorAdapter(JpaProperties jpaProperties) {
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setShowSql(jpaProperties.isShowSql());
return vendorAdapter;
}
#Bean(name = "someTransactionManager")
PlatformTransactionManager transactionManager(#Qualifier("someEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
static LocalContainerEntityManagerFactoryBean createEntityManagerFactory(JpaProperties jpaProperties, DataSource dataSource, JpaVendorAdapter jpaVendorAdapter, String persistenceUnit, String[] packagesToScan) {
final LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
factoryBean.setJpaDialect(new HibernateJpaDialect());
factoryBean.setJpaPropertyMap(getVendorProperties(jpaProperties));
factoryBean.setPersistenceUnitName(persistenceUnit);
factoryBean.setPackagesToScan(packagesToScan);
return factoryBean;
}
private static Map<String, Object> getVendorProperties(JpaProperties jpaProperties) {
return jpaProperties.getHibernateProperties(new HibernateSettings());
}
}
Application.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
#SpringBootApplication(
exclude = {
DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class
}
)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

Not possible with Spring using JSR 330 annotations. Currently it's not possible to inject EntityManagers into constructors as #PersistenceContext is defined to not be allowed on parameters. See JPA_SPEC-72 and Allow injecting EntityManagers through constructor injection (and at non-#PersistenceContext injection points in general) [SPR-10443].

Currently, the Spring team says that is possible inject EntityManager by constructor, as they already use on Spring JPA Repository.
Just:
private final EntityManager em;
public YourRepository(EntityManager em) {
this.em = em;
}
I tested. Works :). No more field injection.

If you would not like to use Spring Data in your project for some reason (e.g. you're just making a legacy project a bit better), you can create the following FactoryBean to make EntityManager injectable via constructor injection:
/**
* Makes the {#link EntityManager} injectable via <i>#Autowired</i>,
* so it can be injected with constructor injection too.
* (<i>#PersistenceContext</i> cannot be used for constructor injection.)
*/
public static class EntityManagerInjectionFactory extends AbstractFactoryBean<EntityManager> {
#PersistenceContext
private EntityManager entityManager;
#Override
public Class<?> getObjectType() {
return EntityManager.class;
}
#Override
protected EntityManager createInstance() {
return entityManager;
}
}
Please note, that because we use the #PersistenceContext annotation internally, the returned EntityManager will be a proper thread-safe proxy, as it would have been injected directly at the place of usage with field injection.

In our code, we have a base dao object which uses the injected entity manager through PersistenceContext:
public abstract class BasicJpaDao<T> implements IBasicDao<T> {
#PersistenceContext(type = PersistenceContextType.TRANSACTION, unitName = "default")
protected EntityManager entityManager;
// Default constructor for Spring
public BasicJpaDao() {}
//Use this constructor to set the entity manager yourself
public BasicJpaDao(EntityManager entityManager) {
this.entityManager = entityManager;
}
...
}
The persistence unit is defined in the Application Context file like so:
<!-- JPA -->
<!-- Creates an EntityManagerFactory for use with the Hibernate JPA provider -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSourceGlobal" />
<property name="packagesToScan" value="me.comocomo.nutrino.domain.jpa" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="jpaPropertyMap">
<map merge="true">
<entry key="hibernate.format_sql" value="${hibernate.format_sql}" />
</map>
</property>
</bean>
<!-- jpaVendorAdapter (works in conjunction with the persistence.xml) -->
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="${jpa.database}" />
<property name="showSql" value="${jpa.showSql}" />
<property name="databasePlatform" value="${jpa.dialect}" />
<property name="generateDdl" value="${jpa.generateDdl}" />
</bean>
<!-- In order to enable EntityManager injection -->
<bean id="persistenceAnnotation"
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<!-- Transactions -->
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSourceGlobal" />
</bean>
Similarly, you can create an EntityManagerFactoryFactory class which gets the EntityManagerFactory using Injection, and in turn passes the factory to your bean:
#Component
public class EntityManagerFactoryFactory {
#Inject
private EntityManagerFactory factory;
}

Related

How to fix the Autowired dependencies failing in spring-mvc Hibernate

Hello (i am a new Spring MVC Hibernate developper) and i am working on a user regestration application in Spring MVC and Hibernate using Netbeans. I have a problem and i can not resolve it; it's #Autowired and beans problem.
This my Entity, User:
#Entity
#Table(name = "user")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
/* attributes */
#Column(name = "Username")
private String userName;
#Column(name = "Email")
private String email;
#Column(name = "Firstname")
private String firstName;
#Column(name = "LastName")
private String lastName;
#Column(name = "BirthDate")
private String birthDate;
#Column(name = "PhoneNumber")
private String phoneNumber;
#Column(name = "PWHash")
private String pwHash;
}
The DAO interface
package com.Etravals.DAO;
import com.Etravels.Model.User;
public interface UserDAO {
public void addUser(User user);
}
DAO Impl:
import com.Etravels.Model.User;
import javax.transaction.Transactional;
import org.hibernate.SessionFactory;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
#Repository
#Transactional
public class UserDAOImpl implements UserDAO{
#Autowired
private SessionFactory sessionFactory;
private Session getSession(){
return sessionFactory.getCurrentSession();
}
#Override
public void addUser(User user) {
Session session = getSession();
session.save(user);
}
}
and service inteface :
package com.Etravels.Service;
import com.Etravels.Model.User;
public interface UserService {
public void addUser(User user);
}
Service Impl :
package com.Etravels.Service;
import com.Etravals.DAO.UserDAO;
import com.Etravels.Model.User;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
#Transactional
public class UserServiceImpl implements UserService{
#Autowired
private UserDAO userdao;
#Override
public void addUser(User user) {
userdao.addUser(user);
}
}
My HomeController :
#Controller
public class HomeController {
#Autowired
private UserService userService;
#RequestMapping(value="/")
public String showIndex(){
return "acceuil";
}
#RequestMapping(value="/addUser", method = RequestMethod.POST)
public ModelAndView addUser(#ModelAttribute("userFormSignUp") User user){
userService.addUser(user);
return new ModelAndView("redirect:/");
}
}
and this is my dispatcher-servlet.xml file :
<context:component-scan base-package="com.Etravels" />
<!-- Getting Database properties -->
<context:property-placeholder location="classpath:application.properties" />
<mvc:resources mapping="/resources/**" location="/resources/"/>
<mvc:resources mapping="/img/**" location="/resources/img/" />
<mvc:resources mapping="/styles/**" location="/resources/styles/"/>
<mvc:resources mapping="/javascript/**" location="/resources/javascript/"/>
<mvc:annotation-driven />
<!-- View Resolver -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- DataSource -->
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"
id="dataSource">
<property name="driverClassName" value="${database.driver}"></property>
<property name="url" value="${database.url}"></property>
<property name="username" value="${database.user}"></property>
<property name="password" value="${database.password}"></property>
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
<property name="packagesToScan" value="com.Etravels.Model"></property>
</bean>
<!-- Transaction -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
This is what I have as an error from Apache Tomcat server log :
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'homeController':
Injection of autowired dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException:
Could not autowire field:
private com.Etravels.Service.UserService com.Etravels.Controller.HomeController.userService; nested exception is
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'userServiceImpl':
Injection of autowired dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException:
Could not autowire field:
private com.Etravals.DAO.UserDAO com.Etravels.Service.UserServiceImpl.userdao; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.Etravals.DAO.UserDAO] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProc ....
Try
#Autowired(required=true)
private SessionFactory sessionFactory;
In UserDAOImpl class.

Hibernate+spring java configuration

I am new to spring and hibernate, i want to configure hibernate session factory using java config. now i have an xml config but not working with java configuration
My xml config is:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<context:component-scan base-package="com.java.*" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<!-- Hibernate 4 SessionFactory Bean definition -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.java.web.model.Employee</value>
<value>com.java.web.model.Answer</value>
<value>com.java.web.model.Question</value>
<value>com.java.web.model.Survey</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="dataSource" ref="dataSource" />
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
My java config file is:
package com.java.config;
import java.io.IOException;
import java.util.Properties;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
#EnableWebMvc
#Configuration
#ComponentScan({ "com.java.web.*" })
#Import({ SecurityConfig.class })
//#PropertySource(value = { "classpath:application.properties" })
public class AppConfig {
#Autowired
private Environment environment;
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/pages/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Bean(name = "dataSource")
public DriverManagerDataSource dataSource() {
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
driverManagerDataSource.setUrl("jdbc:mysql://localhost:3306/test");
driverManagerDataSource.setUsername("root");
driverManagerDataSource.setPassword("12345");
return driverManagerDataSource;
}
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "com.java.model" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
properties.put("hibernate.show_sql", "true");
properties.put("hibernate.format_sql", "true");
return properties;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory)
{
HibernateTransactionManager htm = new HibernateTransactionManager();
htm.setSessionFactory(sessionFactory);
return htm;
}
}
But it shows resource not available. Please help me......
Edit
package com.java.config;
import java.io.IOException;
import java.util.Properties;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
#EnableWebMvc
#Configuration
#ComponentScan({ "com.java.web.*" })
#Import({ SecurityConfig.class })
//#PropertySource(value = { "classpath:application.properties" })
public class AppConfig {
#Autowired
private Environment environment;
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/pages/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Bean(name = "dataSource")
public DriverManagerDataSource dataSource() {
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
driverManagerDataSource.setUrl("jdbc:mysql://localhost:3306/test");
driverManagerDataSource.setUsername("root");
driverManagerDataSource.setPassword("12345");
return driverManagerDataSource;
}
/* #Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "com.java.model" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}*/
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
properties.put("hibernate.show_sql", "true");
properties.put("hibernate.format_sql", "true");
return properties;
}
/* #Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory)
{
HibernateTransactionManager htm = new HibernateTransactionManager();
htm.setSessionFactory(sessionFactory);
return htm;
}*/
}
When i comment two methods as shown above. Its working. But i need hibernate configuration.

Spring Data lazyload does not LazyInitializationException

#Component
#Transactional
public class TestClass extends AbstractClass
{
#Autowire
ClassARepo classARepo;
#Override
public void test() {
ClassA classA = classARepo.findOne(1);
List<ClassB> list = classA.getClassBs();
list.size();
}
}
ClassB is mapped as onetomany and lazily loaded.
In the above code
classARepo.findOne(1);
Executes correctly. but
List<ClassB> list = classA.getClassBs();
list.size();
Fails with LazyInitializationException.
public interface ClassARepo extends CrudRepository<ClassA, Integer> {
}
Instance for TestA is created like the one below
#PersistJobDataAfterExecution
#DisallowConcurrentExecution
#Transactional
#Component
public class TestClassJOB extends AbstractJob
{
#Autowired
TestClass indexer;
}
Context:
<!-- JPA mapping configuration -->
<bean id="persistenceXmlLocation" class="java.lang.String">
<constructor-arg value="classpath:/persistence.xml"></constructor-arg>
</bean>
<!-- entity manager -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource" p:persistenceUnitName="jpaData"
p:persistenceXmlLocation-ref="persistenceXmlLocation">
<property name="packagesToScan" value="com..persist.entity" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
</bean>
<!-- transaction manager -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory" lazy-init="true" p:dataSource-ref="dataSource" />
<!-- JPA repositories -->
<jpa:repositories base-package="com..persist.repo"
entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager" />
I tried many resources and could not solve the issue. The following error message is displayed "could not initialize proxy - no Session".
What could be the cause of the issue?
When the session is available while classARepo.findOne(1) is called, why is not available during lazy fetch(list.size())?
The issue was the instance for TestClassJOB was created by Quartz. So the transnational proxy was not applied to the class which was the reason for the issue.
I fixed the issue by declaring a transaction template
#Autowired
TransactionTemplate transactionTemplate;
and then wrapping the code within
transactionTemplate.execute(new TransactionCallbackWithoutResult()
{
#Override
protected void doInTransactionWithoutResult(TransactionStatus status)
{
<code here>
}
}

Mixing declarative beans and annotated beans: org.hibernate.HibernateException No Session found for current thread

I get "No Session found for current thread".
I suppose the problem is in mixing declarative xml beans and annotated beans.
Following, I'll resume my config.
MyLibrary Project
Spring 3.1.4
Hibernate 4
applicationContext.xml
<tx:annotation-driven transaction-manager="transactionManager" />
<context:component-scan
base-package="com.mycompany.dao.core, com.mycompany.services.core,
com.mycompany.permissionEvaluator" />
<import resource="model-core-security.xml" />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
... (sessionFactory ecc...)
model-core-security.xml
<bean id="expressionHandler"
class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator" ref="permissionEvaluator" />
</bean>
<security:global-method-security
pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler" />
</security:global-method-security>
With component-scan I create beans: AccountService, AccountDAO and PermissionEvaluator.
AccountService.java (com.mycompany.services)
#Service("accountService")
#Transactional
public class AccountServiceImpl implements AccountService {
#Resource
private AccountDAO accountDAO;
...
}
AccountDAO.java (com.mycompany.dao)
#Repository
#Transactional
public class HibernateAccountDAOImpl implements AccountDAO {
...query...
}
(AccountService e AccountDAO are transactional)
Now, within AccountController.java I call accountService.listAccounts() and it's all right!
But, if I inject AccountService into PermissionEvaluator class (following snippet), AccountController gets No Session found for current thread when invokes accountService.listAccounts()
PermissionEvaluator.java (com.mycompany.permissionEvaluator)
Component("permissionEvaluator")
public class PermissionEvaluatorImpl implements PermissionEvaluator {
#Resource
private AccountService accountService;
...
}
I use PermissionEvaluator (with AccountService, AccountDAO) created by component-scan in expressionHandler bean declared in model-core-security.xml.
Might it be the cause of "no session found for currend thread"?
#Transactional
what's ur import package
import org.springframework.transaction.annotation.Transactional; ??
U can try to import "import javax.transaction.Transactional;"

Spring 3.1.1 java based configuration issue of FreeMarkerConfigurer

I am using Spring 3.1.1 with Freemarker.
After I have successded to use the new concept of java based configuraion of the new spring 3.1.
Now I try to use Freemarker with it.
However,I got that exception:
javax.servlet.ServletException: Could not resolve view with name
'/welcome' in servlet with name 'appServlet'
org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1139)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:927)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
Here is the WebConfig:
package com.springway.config;
#Configuration
#ComponentScan("com.springway")
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Inject
private Environment environment;
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJacksonHttpMessageConverter());
}
#Bean
public ViewResolver viewResolver() {
UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
viewResolver.setViewClass(FreeMarkerView.class);
return viewResolver;
}
#Bean
public FreeMarkerConfigurer freeMarkerConfigurer() {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPath(
"/WEB-INF/freemarker.xml");
return configurer;
}
freemarker.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- freemarker config -->
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/freemarker/"/>
<property name="freemarkerSettings">
<props>
<prop key="number_format">0.######</prop>
</props>
</property>
<property name="freemarkerVariables">
<map>
<entry key="xml_escape" value-ref="fmXmlEscape"/>
</map>
</property>
</bean>
<bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape"/>
<!--
View resolvers can also be configured with ResourceBundles or XML files. If you need
different view resolving based on Locale, you have to use the resource bundle resolver.
-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="cache" value="true"/>
<property name="prefix" value=""/>
<property name="suffix" value=".ftl"/>
</bean>
</beans>
The controller :
#RequestMapping(value="/", method=RequestMethod.GET)
public ModelAndView home(Principal user) {
return new ModelAndView("/welcome.ftl");
}
I am struggling the same problem as yours. And I tried to turn on logging level "DEBUG" for "org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer". I found following message:
java.io.FileNotFoundException: ServletContext resource [/WEB-INF/freemarker/] cannot be resolved to URL because it does not exist
at org.springframework.web.context.support.ServletContextResource.getURL(ServletContextResource.java:154) ~[spring-web-3.1.1.RELEASE.jar:3.1.1.RELEASE]
at org.springframework.web.context.support.ServletContextResource.getFile(ServletContextResource.java:169) ~[spring-web-3.1.1.RELEASE.jar:3.1.1.RELEASE]
at org.springframework.ui.freemarker.FreeMarkerConfigurationFactory.getTemplateLoaderForPath(FreeMarkerConfigurationFactory.java:351) [spring-context-support-3.1.1.RELEASE.jar:3.1.1.RELEASE]
at org.springframework.ui.freemarker.FreeMarkerConfigurationFactory.createConfiguration(FreeMarkerConfigurationFactory.java:304) [spring-context-support-3.1.1.RELEASE.jar:3.1.1.RELEASE]
.....
And a wired log from Jetty:
WARN org.eclipse.jetty.util.log - /freemarker/
I don't know what going on! So that I replaced the value of "templateLoaderPath" with another name, like "/WEB-INF/tmpl-freemarker/", then everything is workable!!
Next, I tried to use ServerContext.getResource() to test "/WEB-INF/freemarker/html.ftl". Here is the result:
Resource under /WEB-INF/freemarker/: null
My code of testing:
#Inject
private ServletContext servletContext;
try {
logger.info("Resource under /WEB-INF/freemarker/: {}", servletContext.getResource("/WEB-INF/freemarker/html.ftl"));
} catch(Exception e) {
logger.info("Exception while getResource", e);
}
It seems ServletContext can't find out the resource under "/WEB-INF/freemarker/" correctly either. But I'm not sure the object of ServletContext of Spring is as same as one on normal environment of Java Servlet.
I'm using FreeMarker 2.3.19, Springframework 3.1.1.RELEASE, and jetty-maven-plugin 7.4.5.v20110725 of Maven.
#Configuration
#EnableWebMvc
#ImportResource("classpath:/security-integration.xml")
#ComponentScan("com.springway")
public class WebConfiguration extends WebMvcConfigurerAdapter {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Bean
public FreeMarkerViewResolver viewResolver() {
FreeMarkerViewResolver freeMarkerViewResolver = new FreeMarkerViewResolver();
freeMarkerViewResolver.setCache(true);
freeMarkerViewResolver.setPrefix("");
freeMarkerViewResolver.setSuffix(".ftl");
return freeMarkerViewResolver;
}
#Bean
public FreeMarkerConfigurer freemarkerConfig() {
FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
freeMarkerConfigurer.setTemplateLoaderPath("/WEB-INF/freemarker/");
Properties settings = new Properties();
settings.setProperty("number_format", "0.######");
freeMarkerConfigurer.setFreemarkerSettings(settings);
Map variables = new java.util.HashMap<String, Object>();
variables.put("xml_escape", new XmlEscape());
freeMarkerConfigurer.setFreemarkerVariables(variables);
return freeMarkerConfigurer;
}
}
You might have done wrong import
import org.springframework.web.portlet.ModelAndView;
instead of do this
import org.springframework.web.servlet.ModelAndView;

Resources