2

I am attempting to create rest web services to handle CRUD operations for an android application. I'm using Spring 4.0 with Hibernate. I'm trying to autowire a dao and it's always null and I haven't been able to figure out the cause of the issue. I searched online and everything looks right to me so I'm at a complete lost. I defined the bean in the applicationContext as I have saw in many tutorials but I'm unable to get the dao to autowire. Any help would be appreciated.

dispatch-servlet.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:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">


    <context:annotation-config />
    <mvc:annotation-driven />
    <context:component-scan base-package="com.bike.party.services, com.bike.party.daos" />
  <tx:annotation-driven transaction-manager="transactionManager"  />

</beans>

applicationContext.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p" 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-4.0.xsd        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

   <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" id="propertyConfigurer" p:location="/WEB-INF/jdbc.properties"/>

<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource" p:driverClassName="${jdbc.driverClassName}" p:password="${jdbc.password}" p:url="${jdbc.url}" p:username="${jdbc.username}"/>

    <!-- ADD PERSISTENCE SUPPORT HERE (jpa, hibernate, etc) -->
    <bean class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" id="sessionFactory">
        <property name="dataSource" ref="dataSource"/>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">true</prop>

            </props>
        </property>
        <property name="packagesToScan" value="com.bike.party.models"/>
    </bean>

    <bean class="org.springframework.orm.hibernate4.HibernateTransactionManager" id="transactionManager" p:sessionFactory-ref="sessionFactory" />    

    <tx:annotation-driven/>
</beans>

UserDao

package com.bike.party.daos;

import com.bike.party.models.User;

public interface UserDao extends Dao<User> {

    public User findByUserName(String username);
}

UserDaoImpl

package com.bike.party.daos;

import com.bike.party.models.User;
import java.util.List;
import javax.transaction.Transactional;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;

@Repository
@Transactional
@Qualifier("userDaoImpl")
public class UserDaoImpl implements UserDao {

    @Autowired
    private SessionFactory sessionFactory;

    @Override
    public User findByUserName(String username) {
        List<User> userList = sessionFactory.getCurrentSession().createCriteria(User.class).add(Restrictions.eq("username", username)).setMaxResults(1).list();
        return userList.isEmpty() ? null : userList.get(0);
    }
}

UserWebService

package com.bike.party.services;

import com.bike.party.daos.UserDao;
import com.bike.party.models.User;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.Provider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Provider
@Component
@Path("userservice")
public class UserWebService {

    @Autowired
    private UserDao userDao;

    @GET
    @Path("/user/{username}")
    @Produces(MediaType.TEXT_PLAIN)
    public String getUser(String username) {
        if (userDao == null) {
            return "the dao is null";
        }

        User user = userDao.findByUserName(username);
        if (user == null) {
            return "No user was found.";
        } else {
            return user.getUsername();
        }
    }
}

UPDATE:

I modified the UserWebService with

private UserDao userDao;

    @Autowired
    public void setUserDao(UserDao userDao) {
        if (functionDao != null) {
            System.out.println(String.valueOf(userDao.findByUserName("chris")));
        } else {
            System.out.println("setting the dao is null :(");
        }
        this.userDao= userDao;
    }

When the web app is deployed this is called and finds the user but when I call it from the client it is always null. Could this be because I'm calling the service directly and not going through spring? If so could any point me to the create way to call the service from the client. Thanks

Chris
  • 21
  • 1
  • 5
  • Have you correctly integrated Spring with your JAX RS implementation? – Sotirios Delimanolis Nov 26 '14 at 01:34
  • 1
    Consider reducing that code to the minimum reproducible issue. – Tomasz Kowalczyk Nov 26 '14 at 01:44
  • Where is the datasource declared? – stringy05 Nov 26 '14 at 02:53
  • Added them to the code above. – Chris Nov 26 '14 at 02:57
  • try adding `@Qualifier("userDaoImpl")` above the `autowired` `setUserDao` method. – Sajan Chandran Nov 26 '14 at 16:33
  • @SajanChandran After adding the setter I can see that it is actually being set by spring. I believe the issue is that jersey creates its own instance and I can't figure out how to get jersey to use the spring initiated fields. I have done what this [post](http://stackoverflow.com/questions/19745187/spring-di-autowired-property-is-null-in-a-rest-service) has but I'm still getting null. – Chris Nov 26 '14 at 19:42
  • if you've got the jersey-spring dependency included and are using the spring spi servlet then it should all just magically happen, can you add your web.xml and the pom? – stringy05 Nov 26 '14 at 23:25

3 Answers3

1

i believe spring can not find your UserDao class.

try to change your component-scan instruction in dispatch-servlet.xml to this one:

<context:component-scan base-package="com.bike.party.*" />

If you're using Spring Tool Suite all @Component's in your project should be marked as Component(icon with S):

enter image description here

EDIT: remove bean definition from xml, do not mix xml and annotated configuration. Remove also "userDaoImpl" from your Annotations. Change @Repository("userDaoImpl") to @Repository()

alex
  • 8,904
  • 6
  • 49
  • 75
  • Still getting null after this change. – Chris Nov 26 '14 at 16:22
  • Made the changes, in the above code and still no change. I found another one with a similar issue [here](http://stackoverflow.com/questions/19745187/spring-di-autowired-property-is-null-in-a-rest-service) . I made the changes to the web.xml that were mentioned and I'm still having the same issue. – Chris Nov 26 '14 at 19:30
0

Remove the <bean id="userDao" class="com.bike.party.daos.UserDaoImpl" /> bean from the applicationContext.xml file.

I think you are injecting this instance instead of the the one that gets created via the @Repository annotation which is why your SessionFactory is null

stringy05
  • 6,511
  • 32
  • 38
  • I removed the bean in the applicationContext and it is still null. – Chris Nov 26 '14 at 15:33
  • here's a modified version of the sample jersey + spring hello world project on github. I've basically added the DAO and ORM layers to the existing webapp, which is all getting injected correctly, : https://github.com/stringy05/jersey/tree/master/examples/helloworld-spring-webapp – stringy05 Nov 27 '14 at 03:21
0

Try to derive your UserWebService from SpringBeanAutowiringSupport.