org.hibernate.HibernateException: No Session found for current thread - spring

I'm getting the above exception with Spring3 and Hibernte4
The following is my bean xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<context:annotation-config/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/GHS"/>
<property name="username" value="root"/>
<property name="password" value="newpwd"/>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
<property name="packagesToScan">
<list>
<value>com.example.ghs.model.timetable</value>
</list>
</property>
</bean>
<bean id="baseDAO"
class="com.example.ghs.dao.BaseDAOImpl"/>
</beans>
My BaseDAO class looks like this
public class BaseDAOImpl implements BaseDAO{
private SessionFactory sessionFactory;
#Autowired
public BaseDAOImpl(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}
#Override
public Session getCurrentSession(){
return sessionFactory.getCurrentSession();
}
}
The following code throws the exception in the title
public class Main {
public static void main(String[] args){
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("dao-beans.xml");
BaseDAO bd = (BaseDAO) context.getBean("baseDAO");
bd.getCurrentSession();
}
}
Does anyone have an idea about how to solve this problem?

getCurrentSession() only makes sense inside a scope of transaction.
You need to declare an appropriate transaction manager, demarcate boundaries of transaction and perform data access inside it. For example, as follows:
<bean id = "transactionManager" class = "org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name = "sessionFactory" ref = "sessionFactory" />
</bean>
.
PlatformTransactionManager ptm = context.getBean(PlatformTransactionManager.class);
TransactionTemplate tx = new TransactionTemplate(ptm);
tx.execute(new TransactionCallbackWithoutResult() {
public void doInTransactionWithoutResult(TransactionStatus status) {
// Perform data access here
}
});
See also:
10. Transaction Management
13.3 Hibernate

I came across same problem and got solved as below
Added #Transactional on daoImpl class
Added trnsaction manager in configuration file:
<tx:annotation-driven/>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>

I'll just add something that took me some time to debug : don't forget that a #Transactional annotation will only work on "public" methods.
I put some #Transactional on "protected" ones and got this error.
Hope it helps :)
http://docs.spring.io/spring/docs/3.1.0.M2/spring-framework-reference/html/transaction.html
Method visibility and #Transactional
When using proxies, you should apply the #Transactional annotation
only to methods with public visibility. If you do annotate protected,
private or package-visible methods with the #Transactional annotation,
no error is raised, but the annotated method does not exhibit the
configured transactional settings. Consider the use of AspectJ (see
below) if you need to annotate non-public methods.

Which package u have put the BaseDAOImpl class in.. I think It requires a package name similar to the one u have used in the application context xml and it requires a relevant annotation too.

Related

Spring injected bean is null

I am using Spring Framework / Data / HATEOAS and trying to add Dozer.
I have the following bean in my spring-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:data="http://www.springframework.org/schema/data/jpa"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="POSTGRESQL" />
<property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
</bean>
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource" />
<property name="jpaDialect" ref="jpaDialect" />
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://localhost:5432/cp" />
<property name="username" value="cp_user" />
<property name="password" value="+JMJ+pw0m2d" />
</bean>
<context:component-scan base-package="com.mydomain.data.assembler" />
<data:repositories base-package="com.mydomain.repository" />
<mvc:annotation-driven />
<bean id="dozerFactory" class="org.dozer.spring.DozerBeanMapperFactoryBean" scope="singleton">
<property name="mappingFiles" value="classpath*:/*mapping.xml"/>
</bean>
</beans>
And the following assembler:
#Component
public class UserResourceAssembler {
#Inject
private Mapper dozerBeanMapper;
public UserResource toResource(User user) {
UserResource resource = dozerBeanMapper.map(user, UserResource.class);
resource.add(linkTo(methodOn(UserController.class).get(user.getId())).withSelfRel());
return resource;
}
public User toEntity(UserResource resource) {
User user = dozerBeanMapper.map(resource, User.class);
return user;
}
}
So, - I'm very new to beans and injection - but I guess that the factory bean is ?supposed? to inject the Mapper. But the Mapper is definitely null. I know I'm not doing this right, but what am I doing wrong?
Spring injects its beans into spring managed beans. You are using an unmanaged static context. Change UserResourceAssembler into a managed bean as well:
#Component
public class UserResourceAssembler {
#Inject
private Mapper dozerBeanMapper;
public UserResource toResource(User user) {
}
public User toEntity(UserResource resource) {
}
}
See why can't we autowire static fields in spring.
I would have preferred something like the above. But then I read:
Dozer Singleton Startup Bean injetced as Null
That worked. Here was my implementation.
I removed the bean from spring-config, and the context scan.
I added this class:
#Singleton
public class DozerInstantiator {
public static DozerBeanMapper getInstance(){
return MapperHolder.instance;
}
private static class MapperHolder{
static final DozerBeanMapper instance = new DozerBeanMapper();
}
}
And updated my assembler like this:
public class UserResourceAssembler {
private DozerBeanMapper mapper;
public UserResourceAssembler() {
mapper = DozerInstantiator.getInstance();
}
public UserResource toResource(User user) {
UserResource resource = mapper.map(user, UserResource.class);
resource.add(linkTo(methodOn(UserController.class).get(user.getId())).withSelfRel());
return resource;
}
public User toEntity(UserResource resource) {
User user = mapper.map(resource, User.class);
return user;
}
}

in memory db hibernate spring

I have been trying to integrate between spring and memorydb in junit tests but i keep getting the exception.
org.hibernate.exception.SQLGrammarException: user lacks privilege or object not found: ORDERTABLE
testcontext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<jdbc:embedded-database id="testDataSource" type="HSQL">
</jdbc:embedded-database>
<context:annotation-config />
<tx:annotation-driven transaction-manager="transactionManager" />
<context:component-scan base-package="com.bidblaze.service.test"/>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
</bean>
<!-- Hibernate session factory -->
<bean id="SessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
<property name="dataSource">
<ref bean="testDataSource" />
</property>
<property name="packagesToScan" value= MYPACKAGE />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.hbm2ddl.auto">create-drop</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.connection.url">jdbc:hsqldb:mem:projectdb</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="SessionFactory" ref="SessionFactory" />
</bean>
with defining the other beans
My service class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "/testContext.xml" })
#Transactional
public class TestService {
//ApplicationContext context = new ClassPathXmlApplicationContext(
//"spring-config.xml");
#Autowired
PaypalPaymentsService PaypalService;
#Autowired
private OrderDAO orderDAO ;
#Autowired
private SessionFactory sessionFactory;
private Session extSession;
#Before
#Transactional
public void openSessionExternal() {
extSession = sessionFactory.getCurrentSession();
}
#Test
#Transactional
public void shouldHaveASessionFactory() {
assertNotNull(sessionFactory);
}
#Test
#Transactional
public void shouldHaveASession() {
assertNotNull(extSession);
}
#Test
public void saveOrder(){
Order order = new Order();
order.setOrderId("1");
order.setRecieverEmail("enduser_biz#gmail.com");
order.setAmount((double)2.00);
extSession.save(order);
Order testOrder = (Order) extSession.createQuery("from OrderTable where orderId = ?").setParameter(0, "1").list().get(0);
assertNotNull(testOrder);
}
the Order class :
#Entity
#Table(name="OrderTable")
public class Order {
#Id
#GeneratedValue
#Column(name="orderId")
String orderId;
PS: my Order class has other properties that refer to other classes but i didnt map them neither they are entities as well.
any suggestions
Following this answer, and knowing your XML mapping, I'd suggest the following annotation changes to orderId:
#Id
#GeneratedValue
#Column(name="orderId", columnDefintion="BIGINT")
String orderId;
That's assuming that #GeneratedValue equates to a "native" generator as in your XML. You might need to use an #GenericGenerator instead with a strategy=native instead more like this:
#Id
#GeneratedValue(generator="my-native-generator")
#GenericGenerator(name="my-native-generator", strategy = "native")
#Column(name="orderId", columnDefintion="BIGINT")
String orderId;

Change SessionFactory datasource jdbcurl late in runtime

I'm writing a desktop java application for an environment without a network connection. I'm trying to store the application data as securely as I can in an encrypted in-process hsqldb, with an unencrypted user information hsqldb. Hsqldb requires that the crypto_key be set in the jdbcurl when the connection is created. My application uses hibernate to do persistence and Spring to do configuration and injection.
My current scheme is to store username, password hash, salt and the encrypted database's crypto_key in the unencrypted user table. The crypto_key is protected by an asymmetric encryption using the user's password as the key. Thus, the application doesn't know what the crypto_key for the application data is until after it has been running long enough to load a gui, and authenticate the user.
Here is my current applicationContext.xml. Spring uses it to get Hibernate going and functioning.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<context:component-scan base-package="com.company.domain" />
<context:component-scan base-package="com.company.service" />
<tx:annotation-driven />
<bean id="userDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url"
value="jdbc:hsqldb:./ReviewDatabase/users" />
<property name="username" value="reviewer" />
<property name="password" value="$kelatonKey" />
</bean>
<bean id="mainDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url"
value="jdbc:hsqldb:./ReviewDatabase/data" /> <!-- TODO: ;crypt_key=;crypt_type=AES -->
<property name="username" value="reviewer" />
<property name="password" value="$kelatonKey" />
</bean>
<bean id="userSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="userDataSource" />
<property name="annotatedClasses">
<list>
<value>com.company.domain.AppUser</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<bean id="mainSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="mainDataSource" />
<property name="annotatedClasses">
<list>
<!-- <value>com.companu.domain.Person</value> -->
<!-- <value>com.company.domain.Thing</value> -->
<!-- <value>com.company.domain.Thing1</value> -->
<!-- <value>com.company.domain.Thing2</value> -->
<!-- <value>com.company.domain.Review</value> -->
</list>
</property>
<property name="hibernateProperties">
<props>
<pro key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<bean id="mainTransactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="mainSessionFactory" />
</bean>
<bean id="userTransactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="userSessionFactory" />
</bean>
</beans>
Here's an example of a class where I would like to have the SessionFactory injected
#Repository("ReviewDao")
public class HibernateReviewDao implements ReviewDao{
private SessionFactory mainSessionFactory;
#Autowired
public void setMainSessionFactory(
SessionFactory mainSessionFactory){
this.mainSessionFactory = mainSessionFactory;
}
#Override
#Transactional(value = "mainTransactionManager")
public void store(Review review) {
mainSessionFactory.getCurrentSession().saveOrUpdate(review);
}
#Override
#Transactional(value = "mainTransactionManager")
public void delete(Long reviewId) {
Review review = (Review)mainSessionFactory.getCurrentSession()
.get(Review.class, reviewId);
mainSessionFactory.getCurrentSession().delete(review);
}
}
And finally, here's what I've tried to do after authenticating the user and getting that crypto_key.
String jdbcUrl = "jdbc:hsqldb:./ReviewDatabase/data2;crypt_key=" + secret + ";crypt_type=AES";
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
.applySetting("hibernate.dialect", "org.hibernate.dialect.HSQLDialect")
.applySetting("hibernate.show_sql", "true")
.applySetting("hibernate.hbm2ddl.auto","update")
.applySetting("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver")
.applySetting("hibernate.connection.url", jdbcUrl)
.applySetting("hibernate.connection.username", "reviewer")
.applySetting("hibernate.connection.password", "$kelatonKey")
.buildServiceRegistry();
SessionFactory mainSessionFactory = new MetadataSources(serviceRegistry)
.addAnnotatedClass(com.company.domain.Review.class)
.addAnnotatedClass(com.company.domain.Person.class)
.addAnnotatedClass(com.company.domain.Thing.class)
.addAnnotatedClass(com.company.domain.Thing1.class)
.addAnnotatedClass(com.company.domain.Thing2.class)
.buildMetadata()
.buildSessionFactory();
org.springframework.orm.hibernate4.HibernateTransactionManager htm =
(HibernateTransactionManager)context.getBean("mainTransactionManager");
context.getAutowireCapableBeanFactory().initializeBean(mainSessionFactory, "mainSessionFactory");
htm.setSessionFactory(mainSessionFactory);
However, with that, the first query to the object above results in org.hibernate.HibernateException: No Session found for current thread
How can I change the jdbcurl long after hibernate has initialized, dependencies have been injected and other various kinds of tom-foolery has occurred?
I've been putting this part of development off, hoping Google would eventually come through, but I'm out of ideas to search for. All answers will be accepted with sheepish humility :)
I wonder if this might help, Can I replace a Spring bean definition at runtime? , you could dummy up the bean properties to start with and then change the bean in runtime.
So, the missing bit of the recipe was LocalSessionFactoryBean. It got the sessionFactory setup so I could just replace the sessionFactories that are created at initialization.
Here's the code I had to change from the question
org.springframework.orm.hibernate4.HibernateTransactionManager htm =
(HibernateTransactionManager)context.getBean("mainTransactionManager");
Class<?>[] classes = new Class<?>[5];
classes[0] = com.company.domain.Thing1.class;
classes[1] = com.company.domain.Thing2.class;
classes[2] = com.company.domain.Person.class;
classes[3] = com.company.domain.Thing.class;
classes[4] = com.company.domain.Review.class;
String jdbcUrl = "jdbc:hsqldb:./ReviewDatabase/data3;crypt_key=" + secret + ";crypt_type=AES";
java.util.Properties hibernateProperties = new java.util.Properties();
hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
hibernateProperties.setProperty("hibernate.show_sql", "true");
hibernateProperties.setProperty("hibernate.hbm2ddl.auto","update");
hibernateProperties.setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver");
hibernateProperties.setProperty("hibernate.connection.url", jdbcUrl);
hibernateProperties.setProperty("hibernate.connection.username", "reviewer");
hibernateProperties.setProperty("hibernate.connection.password", "$kelatonKey");
LocalSessionFactoryBean slfb = new LocalSessionFactoryBean();
slfb.setHibernateProperties(hibernateProperties);
slfb.setAnnotatedClasses(classes);
try {
slfb.afterPropertiesSet();
} catch (IOException e) {
Log.warn("Cannot connection to application database");
Log.write(e.getLocalizedMessage());
Log.write(e.getStackTrace());
return;
}
SessionFactory mainSessionFactory = slfb.getObject();
context.getAutowireCapableBeanFactory().initializeBean(mainSessionFactory, "mainSessionFactory");
htm.setSessionFactory(mainSessionFactory);
for(ListenForNewSessionFactory dao : daos){
dao.setNewSessionFactory(mainSessionFactory);
}
I had each Dao implement an interface to set the sessionFactory, and had each of them add themselves to a static list on initialization. It's not very reusable, but it works.
I used the following hack - wherever I needed a SessionFactory, I used a SessionFactoryFactory (below) instead - delegates the only SessionFactory method I actually use.
#Component
public class SessionFactoryFactory {
#Autowired
private LocalSessionFactoryBean sessionFactoryBean;
#Autowired
private DriverManagerDataSource dataSource;
private SessionFactory sessionFactory;
private SessionFactory getSessionFactory() {
if (null == sessionFactory) {
sessionFactory = sessionFactoryBean.getObject();
}
return sessionFactory;
}
public Session openSession() {
return getSessionFactory().openSession();
}
public void updateDataSourceUrl() throws IOException {
sessionFactory = null;
sessionFactoryBean.afterPropertiesSet();
}
}

Groovy and spring under same transaction

I'm struggling with legacy code. I'm creating unit tests so I've decided to use groovy to fill database with required legacy data. Normally in my code I using ibatis for persistence. I'd like to rollback test in the end. Problem is that when I create row via groovy then I use it's id to create row via ibatis I get constraint violation exception - parent key not found.
When I use groovy to persist parent and than create child based on parents id it works perfectly fine.
Also I can't use #Transactional because of problems with XML parser (legacy code FTW :/ )
#ContextConfiguration(locations = [ "../dao/impl/ibatis/spring-data-context-config.xml", "classpath:/pl/com/betacom/treq/dao-context.xml"])
#RunWith(SpringJUnit4ClassRunner.class)
public class FinancingForIltCreationTest {
#Autowired
IFinancingForIltDAO financingForIltDAO;
#Autowired
Sql sql;
#Autowired
DataSourceTransactionManager transactionManager;
private TransactionStatus transactionStatus;
#Before
public void setUp() {
transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition());
}
#After
public void tearDown() {
transactionManager.rollback(transactionStatus);
transactionStatus = null;
}
#Test
public void shallCreateFinancingForIlt() throws Exception {
//given
IltOffering offering = new IltOffering("GOING_DOWN_TO_UBERGROUND", offeringTempId, java.sql.Date.valueOf("2011-07-21"), java.sql.Date.valueOf("2012-07-21"));
offering.insert(sql); // it's inserted by groovy
//when
FinancingForIltDTO financingForIltDTO = createFinancingForIlt(offering.id).build(financingForIltDAO); // it's my assembler inserting via iBatis
//then
assertNotNull(financingForIltDTO.id);
}
Configuration looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="dataSourceIn"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>####</value>
</property>
<property name="url">
<value>####</value>
</property>
<property name="username">
<value>####</value>
</property>
<property name="password">
<value>####</value>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<constructor-arg ref="dataSourceIn" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref local="dataSource" />
</property>
</bean>
<bean id="sql" class="groovy.sql.Sql">
<constructor-arg ref="dataSource" />
</bean>
Unfortunately it was a database schema issue.

Injection of the sessionFactory not working

I'm new with Spring and I want to inject the sessionFactory and its not working at all. I'm starting a web server Jetty and then I load the context. After i start a GWT web application, I make a call on the server side and I try to get some info but I get a null pointer. There is no error at all so it make it difficult to know where the problem is. I know its suppose to work because I saw it working on a project I worked on some times ago. Any help will be appreciate. (Sorry for my possibly bad english)
Here is the context.xml :
<?xml version="1.0" encoding="UTF-8" ?>
<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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:security="http://www.springframework.org/schema/security"
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/tx http://www.springframework.org/schema
/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema
/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema
/security/spring-security-3.0.xsd">
<!-- Standard spring initialization -->
<context:component-scan base-package="com.test">
</context:component-scan>
<tx:annotation-driven transaction-manager="txManager"/>
<!-- Connection to the database-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-
method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="root" />
<property name="password" value="123456789" />
</bean>
<!-- Hibernate session factory-->
<bean id="jpaSessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.domain"/>
<property name="namingStrategy" >
<bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!-- Hibernate session factory -->
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="jpaSessionFactory" />
</bean>
</beans>
Here is the main :
public static void main(String[] args) {
ContextHandlerCollection contexts = new ContextHandlerCollection();
contexts.setHandlers(new Handler[]
{ new AppContextBuilder().buildWebAppContext()});
final JettyServer jettyServer = new JettyServer();
jettyServer.setHandler(contexts);
Runnable runner = new Runnable() {
#Override
public void run() {
new ServerRunner(jettyServer);
}
};
EventQueue.invokeLater(runner);
new ClassPathXmlApplicationContext("context.xml");
}
Here is the class Test where I want the injection :
#Component("test")
public class TEST{
#Resource(name="jpaSessionFactory")
private SessionFactory sessionFactory;
#SuppressWarnings("unchecked")
#Transactional(readOnly = true)
public List<Personne> getPersonnes() {
Session s = sessionFactory.getCurrentSession();
Query query = s.createQuery("from Person");
return query.list();
}
}
Here is the server side from the application (not shown completely)
/*** The server side implementation of the RPC service.
*/
#SuppressWarnings("serial")
public class GreetingServiceImpl extends RemoteServiceServlet implements
GreetingService {
#Resource
private TEST t;
public String greetServer(String input) throws IllegalArgumentException {
// Verify that the input is valid.
if (!FieldVerifier.isValidName(input)) {
// If the input is not valid, throw an IllegalArgumentException
back to
// the client.
throw new IllegalArgumentException(
"Name must be at least 4 characters long");
}
t.getPersons(); // NULL pointer here
.........................
The MySQL tables are created like it should, so all the scanning seems to work.
Thanks
Bob
This is because the GreetingServiceImpl class is not created by spring - it is servlet that is initialized by the container directly. Follow the instructions in this article to fix the issue. I have copied the relevant code from the article.
#Override
public void init() throws ServletException {
super.init();
final WebApplicationContext ctx =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
if (ctx == null) {
throw new IllegalStateException("No Spring web application context found");
}
ctx.getAutowireCapableBeanFactory().autowireBeanProperties(this,
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
}

Resources