Hej,
I am trying to implement OAuth2 in an Application using Spring-Boot. I am struggling with the implementation of the JdbcTokenStore (did I understood this right, that this is to store the Token in the Database?)
My Code looks like this:
#Configuration
#EnableAuthorizationServer
protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {
#Autowired
private DataSource dataSource;
private TokenStore tokenStore = new JdbcTokenStore(dataSource);
....
#Override
public void configure(OAuth2AuthorizationServerConfigurer oauthServer) throws Exception {
oauthServer.tokenStore(tokenStore).authenticationManager(authenticationManager);
}
Doing this I am getting following error:
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [se.....config.OAuth2ServerConfig$OAuth2Config$$EnhancerBySpringCGLIB$$f6b9ba94]: Constructor threw exception; nested exception is java.lang.IllegalArgumentException: DataSource required
The database connection itself seems to work, at least I can login with user data (username / password) stored in the database when I use InMemoryTokenStore.
Can anyone tell me what I am doing wrong or recommend sources where good examples are for this issue?
Thanks a lot!
That's a basic dependency injection problem (nothing fancy and nothing oauth- or Boot- related). You can't initialize a field from an #Autowired (the wiring takes place after initialization). You need to pull that out into a #PostConstruct or a #Bean.
Related
I am getting the following error in a Spring Boot project on which I work:
The bean 'auditLogDao' could not be injected as a '{redactedpathwithcorporatename}.AuditLogDao' because it is a JDK dynamic proxy that implements:
org.springframework.data.jpa.repository.JpaRepository
Action:
Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies by setting proxyTargetClass=true on #EnableAsync and/or #EnableCaching.
I have tried a variety of solutions on StackOverflow without success, specifically:
Checking that I am indeed calling the interface, not the implementation.
Adding #Component to the top of SwitchUserFilter
Changing #Resource to #Autowired.
AuditLogDao.java
public interface AuditLogDao extends JpaRepository<AuditLog, String> {}
AuditLogService.java
public interface AuditLogService {
AuditLog save(final AuditLog auditLog);
}
AuditLogServiceImplementation.java
public class AuditLogServiceImplementation implements AuditLogService{
#Resource private AuditLogDao auditLogDao;
#Override
public AuditLog save(AuditLog auditLog) {
return auditLogDao.save(auditLog);
}
}
The file where I actually want to use the service to save information
SwitchuserFilter.java
public class SwitchUserFilter
extends org.springframework.security.web.authentication.switchuser.SwitchUserFilter {
#Resource AuditLogService logService;
'''
logService.save(auditLog);
'''
}
I am relatively new to Spring Boot, so an explanation of why it fixes the problem would be appreciated.
I believe the following code will solve your problem. Add it to the AuditLogServiceImplementation and remove the #Resource annotation from the auditLogDao.
#Autowired
private ListableBeanFactory beanFactory;
#EventListener({ContextRefreshedEvent.class})
void contextRefreshedEvent() {
auditLogDao = beanFactory.getBean(AuditLogDao.class);
}
You can do a similar trick in the filter too, whatever more comfortable for you.
I don't know what is the exact problem, but it's some kind of circular-dependency-like issue.
So by manually importing any bean which is affected in this loop, you can resolve the loop. You will set this one particular dependency AFTER Spring had created all of the other beans.
I am building a Spring Boot application with Spring Security (spring-boot-starter-web and spring-boot-starter-security). I receive the following error from my application during boot:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.lang.IllegalStateException: org.springframework.security.config.annotation.ObjectPostProcessor is a required bean. Ensure you have used #EnableWebSecurity and #Configuration
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:625) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:455) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1288) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
...
My application class consists of the following:
#SpringBootApplication
public class CustomPropertiesApplication {
public static void main(String[] args) {
SpringApplication.run(CustomPropertiesApplication.class, args);
}
}
The bean in this next class appears to be the issue. If it's excluded then the application will boot without error.
#Configuration
#EnableWebSecurity
public class MyConfig extends WebSecurityConfigurerAdapter {
#Bean
public CustomPropertyPlaceholderConfigurer propertyConfigurer(ApplicationContext context) {
return new CustomPropertyPlaceholderConfigurer();
}
}
Right now this CustomPropertyPlaceholderConfigurer class does nothing, I have some legacy classes that are similar, but in trying to troubleshoot this issue I eliminated everything else from my test application.
public class CustomPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
}
I'm at a loss of what to try next. I've looked for details in Spring Security and Spring Boot about building a custom property placeholder configurer, but I didn't find anything useful.
Versions: Spring Boot - 2.1.0.RELEASE | Spring Security - 5.1.1.RELEASE | JDK 1.8
Also, I realize this app doesn't really do anything, there is a much larger application that has much more complicated logic, and this sample app here is just to replicate my issue to make it small for stackoverflow.
I see now that the answer was right in my output logs and I just failed to see it.
o.s.c.a.ConfigurationClassEnhancer : #Bean method MyConfig.propertyConfigurer is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as #Autowired, #Resource and #PostConstruct within the method's declaring #Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see #Bean javadoc for complete details.
Adding static to my bean fixed the issue.
actually i'm using spring for developing a web application, the problem i'm facing is that i'm initializing a bean as soon as the spring container is getting loaded, now i have to use that bean in different parts of my program.
constraints that i have
1. i can get application context everywhere and get that bean but according to my problem i should get that bean without writing that redundant code again and again.so is there any way by which i can initialize that bean and use it directly everywhere in my program.
If you already initialized your bean you can get access to it via #Autowired from each Component in your Spring Application.
private SomeClass myBean;
#Autowired
public void setMyBean(SomeClass myBean){
this.myBean =myBean;
}
Or just:
#Autowired
private SomeClass myBean;
I prefer the first method, looks fancier in my eyes.
You should not get your bean from the context directly, instead you should #Autowire them and let Spring inject it for you.
Here’s an example of two dependencies injected via constructor:
#Component
public class Car {
private final Engine engine;
private final Transmission transmission;
#Autowired
public Car(Engine engine, Transmission transmission) {
this.engine = engine;
this.transmission = transmission;
}
}
Note that your class must be a Spring Component itself in order for the injection to occur.
There are actually three types of dependency injection in Spring: constructor, field and setter injection. Spring team recommends using the constructor based approach, and this post brings very nice arguments to this point: https://blog.marcnuri.com/field-injection-is-not-recommended/
You can refer to this link for more information on constructor-based injection: https://www.baeldung.com/constructor-injection-in-spring
I have the following scenario where I am running into null pointer exception because bean not getting initialized and leading to failure in my server failing to boot.
There is a newly introduced call in PostConstruct annotated method which is failing. The same call is being made in another method which is not in PostConstruct which executes correctly and not cause any issue.
#Component
#Lazy
#Primary
class Parent{
#Autowired
private DesignContextService designContextService;
#PostConstruct
private void init(){
designContextService.getMethod();// fails
}
private void someFunction(){
designContextService.getMethod();// executes successfully
}
}
}
Class DesignContextService{
#Autowired
private ContextService contextService;
public void getMethod(){
contextService.isContextCreated();
...
}
// Below classes present in another jar
class ContextService{
#Inject
public ContextAdapter contextAdapter;
public void isContextCreated(){
contextAdapter.isEstablished();// contextAdapter is null . Throws exception here
}
}
}
Error Stack trace :
at
Caused by org.springframework.beans.factory.BeanCreationException : Error creating bean ...
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:137)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1620)
This is because of the #lazy annotation. As specified in the documentation:
The default behavior for ApplicationContext implementations is to eagerly pre-instantiate all singleton beans at startup. Pre-instantiation means that an ApplicationContext will eagerly create and configure all of its singleton beans as part of its initialization process. Generally this is a good thing, because it means that any errors in the configuration or in the surrounding environment will be discovered immediately (as opposed to possibly hours or even days down the line).
Please look into the following link for reference: Using Spring #Lazy and #PostConstruct annotations
Spring: how to initialize related lazy beans after main bean creation
In HomeController i am doing the following
#Controller
public class HomeController {
#Autowired
private EUserService userDao;
#RequestMapping(value = "/")
public String setupForm(Map<String, Object> map) {
User user=(User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
EUser currentUser = userDao.findUserByName(user.getUsername());
System.out.println(currentUser.getUserName());
}
}
It works fine and shows me the output properly. Now If I do the same thing in a non controller type class like following
public class Utility {
#Autowired
private EUserService userDao;
public void getLoggedUser() {
User user = (User) SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
EUser currentUser = (EUser) userService.findUserByName(user
.getUsername());
System.out.println(currentUser.getUserName());
}
}
it gives me the following NullPointerException
SEVERE: Servlet.service() for servlet [spring] in context with path [/Ebajar] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException
How to fix this??
The problem is not that you are calling this not from controller. The problem is that your are calling this from class that is not managed by Spring, so the userDao is not injected here.
It think that "right" solution is to turn your utility to Spring bean, e.g. marking it as #Service and call it via Spring. Alternatively you can retrieve it programmatically using ApplicationContext.getBean() (see here for details)
you should declare/annotate your Utility class as a spring bean so that let other bean get injected. in this case, it is EUserService
try adding #Component to your Utility class. I assumed your package is involved by spring annotated bean scanning settings.
Only Spring managed bean can autowire an instance. Read here
You annotate Utility with #Component.