Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Singleton and @Autowired returning NULL

I have a repository manager that manages my repositories. I have the @Autowired to instantiate my properties, but they are always null. The beans are correctly configured in my xml. Any reason why?

public class RepositoryManager {

        private static RepositoryManager instance;

        private RepositoryManager()
        {
        }

       public static RepositoryManager Instance()
       {
            if(instance == null)
                 instance  = new RepositoryManager();

            return instance;
        }

        @Autowired
        private IUserRepository userRepository;

        @Autowired
        private IRoleRepository roleRepository;

        @Autowired
        private IAssetRepository assetRepository;

        public IUserRepository getUserRepository() {
            return userRepository;
        }

        public void setUserRepository(IUserRepository userRepository) {
            this.userRepository = userRepository;
        }

        public IRoleRepository getRoleReposttory() {
            return roleRepository;
        }

        public void setRoleReposttory(IRoleRepository roleRepository) {
            this.roleRepository = roleRepository;
        }

        public IAssetRepository getAssetRepository() {
            return assetRepository;
        }

        public void setAssetRepository(IAssetRepository assetRepository) {
            this.assetRepository = assetRepository;
        }
    }

dao.xml

    <!-- Scans within the base package of the application for @Components to configure as beans -->
    <context:component-scan base-package="com.cisco.badges.data.*" />

    <context:property-placeholder location="classpath:jdbc.properties"/>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
      </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration"/>
        <property name="annotatedClasses">
          <list>
              <value>com.cisco.badges.data.domain.User</value>
              <value>com.cisco.badges.data.domain.Role</value>
              <value>com.cisco.badges.data.domain.Asset</value>
              <value>com.cisco.badges.data.domain.UserRole</value>
              <value>com.cisco.badges.data.domain.UserRole$UserRolePK</value>
              <value>com.cisco.badges.data.domain.UserAsset</value>
              <value>com.cisco.badges.data.domain.UserAsset$UserAssetPK</value>
          </list>
        </property>
        <property name="configLocation">
            <value>classpath:hibernate.cfg.xml</value>
        </property>
        <property name="hibernateProperties">
            <props>
                 <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
            </props>
        </property>
    </bean>

     <tx:annotation-driven/>

     <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

</beans>

userrepository.java

    @Repository("userRepository")
public class UserRepository extends
        BaseRepository<User, Long> implements
        IUserRepository {

    @Autowired
    public UserRepository(SessionFactory sessionFactory) {
        super(sessionFactory);
    }
like image 283
Mike Flynn Avatar asked Feb 15 '11 22:02

Mike Flynn


People also ask

Why is Autowired returning null?

The field annotated @Autowired is null because Spring doesn't know about the copy of MileageFeeCalculator that you created with new and didn't know to autowire it.

Why is @autowired not working?

When @Autowired doesn't work. There are several reasons @Autowired might not work. When a new instance is created not by Spring but by for example manually calling a constructor, the instance of the class will not be registered in the Spring context and thus not available for dependency injection.

Is @autowired a singleton?

You can simply put @Autowired annotation, followed by visibility tag and object, to can use every object managed by Spring context. But beware, all of these objects are a kind of Spring-managed singleton.

Why is my Spring bean null?

Spring dependency injection only works with Spring-managed objects or Beans. If the object in which a Bean is getting injected is not a spring managed object, you will get null @Autowired fields. To fix this, make sure only the framework create and manage the related dependencies.


3 Answers

I just ran into this myself. The problem is that when you do

new RepositoryManager();

in Instance(), you are not using Spring to create RepositoryManager, and thus the dependency injection isn't happening for your instance (no autowiring).

The solution is to do away with the Instance() singleton pattern. If you want to insist on a Singleton, then do this

@Component
@Scope(value = "singleton")
public class RepositoryManager {
    ...
}

Then wherever you need the repository manager, just autowire in a reference to it (assuming the calling bean is also managed by Spring!)

@Autowired
private RepositoryManager repositoryManager = null;
like image 198
werkshy Avatar answered Nov 03 '22 04:11

werkshy


Please make sure that you have the following in your config:

<context:annotation-config />

<context:component-scan base-package="name.of.your.package"></context:component-scan>

If you have it then post your configuration xml

like image 34
danny.lesnik Avatar answered Nov 03 '22 06:11

danny.lesnik


There is actually a very elegant way to have your cake and eat it, i.e., have a JVM singleton that's also Spring-managed. Say you have a pure java singleton with an autowired bean like this:

public final class MySingletonClass{
  private static MySingletonClass instance;

  public static MySingletonClass getInstance(){
    if(instance==null){
      synchronized{
        if(instance==null){
          instance = new MySingletonClass();
        }
      }
    }
    return instance;
  }

  @Autowired
  private SomeSpringBean bean;

  // other singleton methods omitted
}

You can force Spring to manage this singleton simply by adding in your application context the following line:

<bean class="com.mypackage.MySingletonClass" factory-method="getInstance"/>

Now your singleton will have an instance of SomeSpringBean autowired (if available in the context).

Moreover, this is a 'fix' for the typical problem with Spring singleton beans that are not truly JVM singletons because they get instantiated by Spring. Using the pattern above enforces JVM level singleton, i.e., compiler enforced singleton, together with container singleton.

like image 5
Giovanni Botta Avatar answered Nov 03 '22 04:11

Giovanni Botta