3

I have a spring webapp with annotation driven configuration.

All Controllers, Repositories are autowired.

When integrating Spring Security I defined a separate security-app.xml. I created a Service called LoginUserService which implements UserDetailsService. Now the method loadUserByUsername() method of this class gets invoked for authentication.

This class has an autowired dependency for UserRepository. Now this autowired dependency turns out to be null. To fix this I enable annotation driven configuration and add the package name for the repository class in component scan configuration.

This solution is also discussed here spring security with custom user details

But now the problem is that the UserRepository has an EntityManager field with @PersistenceContext annotation. For the spring security configuration it is able to locate the UserRepository but not able to locate the entity manager. Should I create a new EntityManagerFactory here? I guess that will create two persistence units in my application?

How can I inject an autowired dependency to UserRepository created with the original servlet xml?

Update

This is briefly discussed here: https://stackoverflow.com/a/7078395/161628

But I guess a canonical detailed answer will be more useful to me.

Update

How about using ApplicationContext to get the UserRepository at runtime?

if (userRepository == null) {
    userRepository = ApplicationContextProvider.getApplicatonContext().getBean(UserRepository.class);
}

Why is Spring's ApplicationContext.getBean considered bad?

Community
  • 1
  • 1
Rohit Banga
  • 18,458
  • 31
  • 113
  • 191

1 Answers1

1

EDIT: Beans that you declare in your config for your DispatcherServlet are not going to be available to any beans you declare or component scan in your contextConfigLocation config files. So in this case, if you're setting up your JPA config in your config file that you load for your DispatcherServlet there is no way to wire that in to beans your declare in your security config. You need to move any "core" bean config like that (datasource config, db connection pool config, JPA/Hibernate config, repository/service component scanning, etc.) into a config file that you load via the contextConfigLocation. Then that stuff will be available both to your security beans and your MVC beans. I think generally the idea is to only load MVC specific beans in your DispatcherServlet config (e.g. Controllers, views, request handlers, request scoped beans, etc.). That way you ensure you have a clean separation between MVC code and non-MVC code, with only a one-way dependency from the MVC code to the "core" code, and no dependencies on MVC code in your "core" code. This helps make your code more modular, and makes it easier to reuse your "core" code in other ways, specifically in unit tests.

(Original comment text was asking about how the security config is loaded, if it's in the contextConfigLocation or somewhere else.)

sdouglass
  • 2,350
  • 16
  • 25
  • I don't have app-config.xml here. Just security-config.xml in the context-param. app-config.xml is loadded using DispatcherServlet. Spring Security configuration is loaded using contextConfigLocation. – Rohit Banga May 09 '13 at 06:05
  • By duplicating the config in both xml files get a NoSuchBeanDefinitionException for EntityManagerFactory because there are two beans instead of one. – Rohit Banga May 09 '13 at 06:44
  • I've updated my answer taking into account your replies and additional info. I think you basically need to rearrange your config a big. You should only have MVC stuff in your DispatcherServlet config, and move non-MVC stuff (e.g. JPA config) to another file that you load in via contextConfigLocation. – sdouglass May 09 '13 at 14:56
  • Thanks that was helpful. For now I got it working by loading the repository bean from ApplicationContext at runtime. I will refactor the configuration as you described. – Rohit Banga May 09 '13 at 19:13