3

In my model I have a repository called UserRepository. Additionally I have a UserFacade that basically adds the user to the repository and is accessed by the Controller. The repo is @Autowired in the Facade. When I want to add a new user I get a nullPointerException for the repository.

My spring-servlet.xml contains the required

<jpa:repositories base-package="project.user.repositories" />

while repositories is the folder containing the UserRepository.java. It extends the CrudRepository:

@Repository
public interface UserRepository extends CrudRepository<User, Long> {
    User findByUsername(String username);
}

Facade.java is the object containing repository:

public class UserFacade {
    @Autowired
    private static UserRepository userRepo;

    private static Logger logger = LoggerFactory.getLogger(UserFacade.class);

    public UserFacade(){} //Thought it might work if I add a constructor and call it?

    public static User findByUsername(String username) {
        logger.debug(username+userRepo);  // prints SomeStringnull
        return userRepo.findByUsername(username); //NullPointerException
    }
}

And from my controller I have a method like:

@RequestMapping(value = CONTEXT)
public String test(){
    User user = UserFacade.findByUsername("get"); 
    //obviously user will be null if there is no such user
    return "success";
}

Imports will should not be a problem as I am using Android Studio. What did I miss?

Note: There are many great answers to related questions (like this one), but each has it's own, different context and didn't help me.

Community
  • 1
  • 1
Patrick
  • 879
  • 2
  • 11
  • 29

1 Answers1

7

Spring doesn't autowire static fields. That is why userRepo field is null. One way is to make the UserFacade a bean itself, and then you can make userRepo a non-static field. I would prefer this way. UserFacade shouldn't really be a utility class, since it is interacting with the repository bean. It would make much more sense to make it a bean.

Another option is to provide a setter, and use @Autowired on that:

@Autowired
public void setUserRepo(UserRepository userRepo) {
    UserFacade.userRepo = userRepo;
}

Or using it even on a parameterized constructor would work.

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • Thanks, I didn't know that. Is there any way to keep it static (as an alternative to `@Autowired`)? – Patrick Mar 31 '14 at 14:39
  • @Patrick I guess I gave you two. `setter` and `constructor`. But really you should change it to bean. – Rohit Jain Mar 31 '14 at 14:41
  • Ups you're right.. I was confused, I thought I couldn't set the static variable variable from a non-static method (while it's the other way round). How would I call the setter? You still recommend to use a bean, why so? I think it doesn't make sense in that context, it's more of a helper class. – Patrick Mar 31 '14 at 14:57
  • @Patrick It's not a helper class. It's more like a Service class, which interacts with Repository class. And you don't need to call the setter. Spring will take care of that. – Rohit Jain Mar 31 '14 at 15:00
  • Thanks. I am not really familiar with beans and thought of it more like an entity. But [wikipedia](http://en.wikipedia.org/wiki/JavaBeans) corrects me. Didn't know of @Autowired on setters, this helped me: http://www.mkyong.com/spring/spring-auto-wiring-beans-with-autowired-annotation/ – Patrick Mar 31 '14 at 15:13
  • As I understand, spring needs a default constructor with no parameters, so how would a paremeterized constructor work? The autowired setter is not called, what could be the reason for it? I have annotated UserFacade with ` @Component @Scope(value = "singleton")` but it doesn't work either if I remove it or only remove @Scope. When should the setter be called? I really have a though time with that^^ – Patrick Apr 03 '14 at 06:23