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?
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.)
Related
Using Spring Boot 1.5.12, we create scoped proxies for #ConfigurationProperties beans. We do this so that we can effectively have property values that are scoped to the user/session/etc. We use a BeanFactoryPostProcessor to register a scoped proxy created by ScopedProxyUtils.createScopedProxy and change the scope of the target bean definition to our custom scope.
This worked great in Spring Boot 1.5.12. However, in Spring Boot 2, the introduction of the Binder API has made this stop working. This is because when Spring Boot binds #ConfigurationProperties in its ConfigurationPropertiesBindingPostProcessor, it uses Bindable.of(type).withExistingValue(bean) passing in a type (e.g. org.example.Foo) and the bean which is an instance of ScopedProxyFactoryBean. Bindable checks that bean is an instance of type which it's not and things blow up.
Does anyone know of a general way to accomplish this? Specifically, to replace the #ConfigurationProperties bean definition with a proxy while still allowing the properties to bind to the instance? I've considered delaying the creation of the proxy until after the target has already been bound by ConfigurationPropertiesBindingPostProcessor (i.e. in my own BeanPostProcessor). However, at this point the bean is instantiated and my proxy can only replace the bean. It can't really leave the original bean in the context as a target. So I'm struggling with how to do this using a BeanPostProcessor.
EDIT: I've created a simple example project that demonstrates the issue (with the ability to check out code that works on Spring Boot 1 and fails on Spring Boot 2).
I'm making a web app using spring, in web.xml I have defined context-param to look for application-context.xml file which scans for everything besides controllers and app-servlet.xml that scans only for controllers.
application-context.xml contains the datasource to the database and I inject the datasource in the daos like this:
#Autowired
DataSource dataSource;
Now if I try create a DAO by hand in the controller(I know i probably should use services for that, but it's just for test purposes for now) I get null pointer exception, however when I inject the DAO it loads properly.
So why does it happen? DAOs are not managed by the DI container only the datasource is, so why can't I create the dao by hand?
Spring bean factory and "new" are orthogonal: once you call "new", it's in your hands, not Spring's.
The situation you describe is common: You want Spring to manage bean lifecycle and dependencies in production, but when testing you want to do it yourself with mocks. My suggestion is to write your app to use Spring for DI and bean creation, but have constructors for manual injection of mocks when you test.
Yes; objects not under Spring's control are... well, outside of Spring's control.
There are some ways around this, e.g., allowing newed objects to get Spring DI (e.g., byte code manipulation).
I am experimenting with Java Dependency Injection. Many questions here on SO talk about jndi resources being wired. But I think, a java class can be wired using #Resource annotation. I have a simple servlet in which I have two properties to be wired using CDI. I am using Tomcat6, Servlet 2.5, and Weld configuration.
The servlet code:
#Inject
private HikariConnectionProperties hikariConnectionProperties;
#Resource(name = "connectionProvider")
private IConnectionProvider connectionProvider;
However I get the code compiled, deployed. But, when there is a request for the corresponding servlet I get javax.naming.NameNotFoundException: Name connectionProvider is not bound in this Context.
But, I have #Named annotation for the ConnectionProvider class. The same configuration works with #Inject for both the fields.
So, my first question is how can I fix this issue? And is there any way that I can specify scope for a particular injection(using only annotations of JSR) without using Spring's #Scope? Any example is a great help as I am a newbie to CDI.
#Resource only works in Tomcat when you set up a resource in your container. Here's a reference for your own sake: http://tomcat.apache.org/tomcat-6.0-doc/jndi-resources-howto.html
It expects that you're binding a JNDI entry called "connectionProvider" in Tomcat. CDI does not bind elements to JNDI, it has its own internal mapping of objects to scopes. #Inject works here as you likely have not setup a resource for this class in your resource configuration.
I have a spring mvc controller and I want to enable it only in some profiles (for example development and test).
I know I can use the profile attribute of the beans element in xml configuration to limit the scope of my beans, but I'm using convenient annotations for the controllers now.
Can I bind the annotated controller to given profile somehow?
Or do I have to use the "old way" (of implementing and declaring controller) without annotations and use the beans element in xml configuration?
Will the annotated controllers mix well with the "old ones"?
EDIT: another way, which comes to my mind, is to check the profile in runtime from autowired Environment instance, but this denies the inversion of control
Is this what you mean ?
#Controller
#Profile("test")
public class CacheController {
}
javadoc
I'm having trouble with a field annotated as #Resource in a Spring bean. What I have:
A field, with setter method, annotated #Resource
#Resource
private URL someUrl;
public void setSomeUrl(URL someUrl) {
this.someUrl = someUrl;
}
An <env-entry> tag in my deployment descriptor (web.xml)
<env-entry>
<env-entry-name>someUrl</env-entry-name>
<env-entry-type>java.net.URL</env-entry-type>
<env-entry-value>http://somedomain.net/some/path</env-entry-value>
</env-entry>
The application fails to start with a BeanCreationException, which I dont' expect because I don't necessarily want spring to inject a Spring-managed bean. I want Spring to process #Resource and retrieve the JNDI resource.
This is Spring 2.5.6SEC03 and the bean itself is annotated #Service for autowiring into other #Component instances. Servlet container in this case is Tomcat 7 but will ultimately be deployed onto Weblogic 10, so while I'd like ideally for a solution to work on both, Weblogic is the must-have.
Am I misusing this feature in Spring 2.5? In general? Is there some bit I'm missing? Something I misunderstand about JNDI? All help is appreciated. Thanks.
If you are using Spring Stereotype annotations, (#Service, #Component...), then you are probably including in your spring configuration the <context:component-scan /> element to pick them up. It is fine to do this, but it will automatically register a CommonAnnotationBeanPostProcessor with the application context, as stated just above the second note in this link.
The issue with including the CommonAnnotationBeanPostProcessor is that Spring handles the #Resource annotation and will attempt to inject beans from its application context. You can register your own CommonAnnotationBeanPostProcessor bean and tell Spring to allow direct JNDI access to these #Resource's by configuring the bean by setting the alwaysUseJndiLookup property to true.
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor">
<property name="alwaysUseJndiLookup" value="true"/>
</bean>
Pay attention to the note in the linked documentation:
NOTE: A default CommonAnnotationBeanPostProcessor will be registered by the "context:annotation-config" and "context:component-scan" XML tags. Remove or turn off the default annotation configuration there if you intend to specify a custom CommonAnnotationBeanPostProcessor bean definition!