My problem is that I need to get an authentication token before I make a call to an API. The api must be called on start up of application. However I am having trouble in that both calls are made at the same time thus creating an error of not having the authentication token before making the api call.
I basically need the tokenUtilityClass to create the token before instantiating the Paypal class. I have tried the @Preconstruct and the @Lazy annotation but neither are working for me.
I have a boolean value of validToken which returns true once the authentication token has been created.
This is what my Springboot configuration file looks like
@Autowired
private TokenUtilityClass tokenUtilityClass;
@Bean ResourceConfig resourceConfig() {
return new ResourceConfig().registerClasses(Version1Api.class); }
@PostConstruct
public void postConstruct() {
tokenUtilityClass.tokenTimer();
}
@DependsOn("TokenUtilityClass")
@ConditionalOnProperty(name ="tokenUtilityClass.validToken", havingValue ="true")
@Lazy
public Paypal eventPublisherBean() {
return new Paypal();
}
Would anyone have any ideas about initializing the Paypal class only after the authentication token has been generated.
All help would be appreciated
4
Answers
You are looking for
@Order
annotation.@Order
works with both types of declarations:@Component
/@Service
/@Repository
/@Controller
and with@Bean
However, if you have a clear dependency of one bean on the other bean, then use
@DependsOn
annotation.You can find more info here
It looks like you are sharing the code inside class with
@Configuration
annotation. It seems you markTokenUtilityClass
with@Component
(or similar) annotation.The issue with that is that
@PostConstruct
is connected to your Configuration class, not toTokenUtilityClass
. I suggest moving@PostConstruct
method toTokenUtilityClass
.You can just have token refreshing functionality and make sure token exists upon creating another bean.
What you declared cannot work :
because
tokenUtilityClass.validToken
is not a property but a bean method whileConditionalOnProperty
expects to a property.Concretely, you cannot achieve it straightly with Spring because beans are instantiated as soon as these are required by other beans in their dependencies.
But declaring just that :
could work if that bean is never used as a eager loaded dependency of other beans but rather required at the good time for you : after the token was retrieved.
To achieve that you have two ways :
1) don’t use dependency injection for
PayPal
instance but use exclusively bean factory.Not tested but it sounds conform to the
@Lazy
javadoc :So inject
BeanFactory
in the bean responsible to get the token and use that factoryto initialize the bean after the token was retrieved.Something like that :
2) A straighter alternative to the BeanFactory is declaring the bean as a lazy dependency :
I created just now a very basic project (Java 11) to test that :
https://github.com/ebundy/lazy-init-spring-example/.
When you execute
spring-boot:run
you should get :