RequestScope #PostConstruct is called more than once - java

I have a Service that using asynchronic.
#Service
public class MainService{
AsyncServicd asyncService;
public void main(){
for(int i=0; i<10; i++){
asyncService.asyncMethod();
}
}
}
#Service
#RequiredArgsConstructor
public class AsyncService{
RequestScopeBean requestScopeBean;
#Async
public CompleteableFuture<Void> asyncMethod(){
requestScopeBean.getSomething();
return...
}
}
#RequestScope
#Data
public class RequestScopeBean{
Private int something;
#PostConstruct
public void init(){
System.out.println("post construct called");
}
}
Now my problem I see that the init() method is beeing called 10 times per http request (once for every thread). I want it to be executed only once because I calling external APIs. How can I do that?
I tried using synchronized block:
synchronized(RequestContextHolder.getcurrentRequest()){
requestScopeBean.getSomething();
}
It works now and I see the post construct called only once. But I'm not sure if it is safe to do so. Any suggestions?

Related

Spring Transactions with Executor

I have a method something like:
#Transactional
public void method1() {
taskExecutor.execute() -> {
// do work here
}
}
The #Transactional annotation isn't honored due to new thread pool.
How can I fix this?
You can try to write a Class with a method of your work(will do) and set the #Transactional annotation on this method.Then inject this Class and invoke its work method in new thread pool.
For example:
public class WorkClass {
#Transactional
public void work() {
//do work here...
}
}
#autowired
private WorkClass workClass;
#Transactional
public void method1() {
taskExecutor.execute() -> {
workClass.work();
}
}
And you can adjust policy by Spring Transaction Propagation.

Spring Cache not working as a compute property

I want to use a mechanism for create a one time compute function. I try to use Spring Caching. But it does not working. Please help me to solve this problem. My code like as below,
Gradle Dependency
compile 'org.springframework.boot:spring-boot-starter-cache'
Main Class of Spring Boot Application
#SpringBootApplication
#EnableCaching
public class Application {
public static ApplicationContext applicationContext;
public static void main(String[] args) {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
// todo: Try to save response text and request body
applicationContext = SpringApplication.run(Application.class, args);
}
#Bean
WebMvcConfigurer webMvcConfigurer(){
return new WebMvcConfigurer() {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/**")
.addResourceLocations("classpath:/")
.setCacheControl(CacheControl.maxAge(3600, TimeUnit.SECONDS).noTransform().mustRevalidate());
}
};
}
}
My Coputational property and Test method
public String test(){
return hello();
}
#Cacheable("hello")
public String hello(){
System.out.println("hello");
return "Hello";
}
The #Cacheable annotation caches the values when it is called from outside your #Bean so calling it from another method inside your bean will not work.
try something like
#Bean
public class CachingBean {
#Cacheable("hello")
public String hello(){
System.out.println("hello");
return "Hello";
}
}
#Service
public class CallerService {
#Autowired
private CachingBean cachingBean;
// Setters, constructors...
public String test(){
return cachingBean.hello();
}
}
And then it should work.
That's because the #Cacheable annotation creates a proxy around the method call when it is injected as a Bean, so a direct call (to an instance created directly) or an internal call are not intercepted and the caching mechanism does not even see those calls.
I still sometimes forget about it and get biten by it at the beginning :).
Cheers!

Spring AOP expression executed but it shouldn't

I am newbie in Spring and trying to understand AOP. Here's what I got
I have one simple aspect, which I want to run when any non-getter method gets called
#Aspect
#Component
public class LoggingAspect {
#Pointcut("execution(* org.practice.entity.Person.get*())")
private void getter() {}
#Before("!getter()")
public void noGetter() {
System.out.println("NO GETTER GETS CALLED");
}
}
Person class is simply
#Component
public class Person {
public void getPerson() {
System.out.println("GETTING PERSON....");
}
}
I am initializing the config using Java annotations
#Configuration
#EnableAspectJAutoProxy
#ComponentScan("org.practice")
public class DemoConfig {}
And then in my main method i have
public class MyApp {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DemoConfig.class);
context.close();
}
}
As you can see I am simply creating a context and closing it and not calling any getter or non-getter method. When I run the program, I got the following console output
NO GETTER GETS CALLED....
This makes semi-sense as I am not calling any getter method, but I expected this aspect to execute only if I am explicitly calling any non-getter not by just opening the context. Please let me know if I want my business logic to execute only if any non-getter method gets invoked then how would I do it?
Thanks
Try this:
#Pointcut("execution(* org.practice.entity.Person.*())")
private void methodCall() {}
#Before("!getter() && methodCall")
public void noGetter() {
System.out.println("NO GETTER GETS CALLED");
}
I think its happening during the initializing of Person bean at the time od application context loading
Since you have given joinpoint as not of getter so at the time of default construction execution (provided by compiler) the advice is getting triggered

Execution Order of #PostConstruct

I have 2 singletons in my JEE application that I want to initialize at start up. Something like this:
#Singleton
#Startup
public class ServiceB {
#EJB
private ServiceA a;
#PostConstruct
private void init() {
....
}
}
ServiceB doesn't really need ServiceA, I just added the dependency to make sure that ServiceA is fully initialized (read: #PostConstruct-method finished) before ServiceB's init() -Method starts.
But it doesn't wait. ServiceB actually starts before ServiceA.
Is there any way to ensure that one Bean's #PostConstruct- method waits for another Bean's #PostConstruct-method to finish?
I know I could just remove the #PostConstruct Annotation in ServiceA and call it directly from ServiceB
#PostConstruct init() {
a.init();
}
but I have deployments where there is no ServiceB. So I can't rely on ServiceB to init ServiceA. ServiceA has to do that itself. And ServiceB must wait for ServiceA to be done with it.
Use the #DependsOn annotation to declare an initialization dependency on startup beans.
Example:
#Singleton
#Startup
public class ServiceA {
#PostConstruct
public void init() { ... }
}
#Singleton
#Startup
#DependsOn("ServiceA")
public class ServiceB {
#EJB
ServiceA a;
#PostConstruct
public void init() { ... } // will be called after a is initialized
}
A question on the answer given by #DmiN
(I am new user so not able to post a comment directly)
With your suggestion (as shown in code below) -- I agree that Service B will start after Service A is initialized (just initialized, not that postconstruct is complete). But I doubt if it can be guaranteed that ServiceB's init method will never run unless the Service A's PostConstruct method has finished execution? Correct?
#Singleton
#Startup
public class ServiceA {
#PostConstruct
public void init() { ... }
}
#Singleton
#Startup
#DependsOn("ServiceA")
public class ServiceB {
#EJB
ServiceA a;
#PostConstruct
public void init() { ... } // will be called after a is initialized
}
The #PostConstruct annotation is used for methods executed after dependency injection is complete, So here the injection of service A in service B is done, then the init function of Service B can be executed
public class ServiceA {
#PostConstruct
public void init() { }
}
public class ServiceB {
#Autowired
ServiceA a;
#PostConstruct
public void init() { }
}
As a simple alternative solution, you can manually collect all your independent beans that should be inited in a defined order in one place. It helps to avoid #DependsOn
public interface OrderedPostConstruct {
void init();
}
// ==== Production ====
#Configuration
public class InitConfig {
private final ObjectProvider<OrderedPostConstruct> initializers;
#PostConstruct
public void initEntryPoint() {
initializers.orderedStream().forEach(Initialize::init);
}
}
#Order(1)
#Component
public class OneUsefullComponent implements OrderedPostConstruct {
#Override
public void init() {
// executed first
}
}
#Order(2)
#Component
public class TwoUsefullComponent implements OrderedPostConstruct {
#Override
public void init() {
// executed second
}
}
// ==== Integration tests ====
#Order(Ordered.HIGHEST_PRECEDENCE)
#Component
public class TestDataPopulator implements OrderedPostConstruct {
#Override
public void init() {
// populate data for tests
}
}

How to properly destroy a Spring configuration class

Case 1
Let's consider the following Spring configuration:
#Configuration
public class MyConf1 {
#Bean
public Foo getFoo() {
// Foo class is defined as part of an external lib.
return new Foo();
}
#Bean
public Bar getBar() {
return new Bar(getFoo());
}
}
For some reasons, I need to invoke a Foo's method (i.e. myFoo.shutdown();) when MyConf1 is destroyed.
Is there any way to perform this operation without retrieving the bean instance directly from the application context (via ApplicationContext.getBean())?
Case 2
Again, let's consider a second Spring configuration class:
#Configuration
public class MyConf2 {
#Bean
public ScheduledJob scheduledJob() {
Timer jobTimer = new Timer(true);
return new ScheduledJob(jobTimer);
}
}
This time, I need to invoke jobTimer.cancel() before destroying MyConf2. Indeed, I can instantiate jobTimer outside scheduledJob(), or making it a method's parameter, as scheduledJob(Timer jobTimer).
It will then be possible to define a proper destroyer method for MyConf2. However, I would like to know if there are other ways to proceed.
Any good suggestion?
Note: Foo, Bar, Timer, ScheduledJob classes are defined externally. Thus, there is no possibility to explicitly define an inner destroy method. As assumption, I can modify only MyConf1 and MyConf2.
I would suggest defining a destroy() method (annotated with #PreDestroy) in Foo class
Similarly, modify ScheduledJob class like
public class ScheduledJob {
private Timer timer;
public ScheduledJob(Timer timer){
this.timer = timer;
}
#PreDestroy
public void destroy(){
timer.cancel();
}
}
And add destroyMethod param in #Bean
#Configuration
public class MyConf2 {
#Bean(destroyMethod = "destroy")
public ScheduledJob scheduledJob() {
Timer jobTimer = new Timer(true);
return new ScheduledJob(jobTimer);
}
}
Please see the following page http://forum.spring.io/forum/spring-projects/container/48426-postconstruct-and-predestroy-in-javaconfig
DisposableBean should help you with case #1.
You can implement the DestructionAwareBeanPostProcessor interface that can adds a before-destruction callback when the bean is destroy.In that interface,the method postProcessBeforeDestruction is do that,see the following:
#Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
System.out.println("before destory:"+bean);
}
#Override
public boolean requiresDestruction(Object bean) {
return true;
}
Pay attention to that the method requiresDestruction should return true,otherwise the method postProcessBeforeDestruction will not call when bean should destroy.
And i have a test:
public static void main(String[] args){
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:application-main.xml");
applicationContext.registerShutdownHook();
}
The postProcessBeforeDestruction really call when the bean is destroy.The output is :
before destory:com.zhuyiren.spring.learn.util.Handler#55141def
before destory:com.zhuyiren.spring.learn.controller.TestControleler#47eaca72
before destory:com.zhuyiren.spring.learn.service.impl.TestServiceImpl#7b2bbc3
before destory:com.zhuyiren.spring.learn.service.impl.TwoServiceImpl#48f2bd5b
before destory:com.zhuyiren.spring.learn.controller.ConverConroller#72967906
before destory:org.springframework.context.event.DefaultEventListenerFactory#1a482e36
before destory:org.springframework.context.event.EventListenerMethodProcessor#77fbd92c

Categories