I have a spring context in which a we have Runnable beans started like so:
public void startChildAndWait(Class type) {
BaseMyDispatcher child = appContext.getBean(type);
child.initialize(this); //The child references its parent during run method
new Thread(child).start();
synchronized(LOCK_OBJECT) {
LOCK_OBJECT.wait(someTime);
}
}
The BaseMyDispatcher class is an abstract class and SampleRunnableX are implementations which are with prototype scope, the base class basically has #PostConstruct method and a #PreDestroy method (the main functionality of which is to call notify on a LOCK_OBJECT) and of course a Run method
My problem is that the PostConstruct method is called but when the Run method completes the object doesn't seem to be destroyed therefore the PreDestroy method is not called and I get stuck waiting in parent on the LOCK_OBJECT
The code is called in a function inside a parent Runnable (which is executed inside a ThreadPoolExecutor and starts (sequentially) several children with the same method startChildAndWait passing each time a different class:
startChildAndWait(SampleRunnable1.class);
if(run2IsRequired && lastExitCode == 100) {//runIsRequired are booleans
startChildAndWait(SampleRunnable2.class);
}
if(run3IsRequired && lastExitCode == 100) {//lastExitCode is an integer
startChildAndWait(SampleRunnable3.class);
}
So what do I do to make the PreDestroy method called upon completion of the child thread?
From the documentation:
In contrast to the other scopes, Spring does not manage the complete lifecycle of a prototype bean: the container instantiates, configures, and otherwise assembles a prototype object, and hands it to the client, with no further record of that prototype instance. Thus, although initialization lifecycle callback methods are called on all objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called.
If you want something to happen when the run() method completes, put that code at the end of the run() method.
#PreDestroy callback method will be called when your application shuts down, you need to register a shutdown hook to JVM and close the application context in it when JVM exits.
//Create applicationContext
final ApplicationContext appContext =
//register ashutdown hook on application context
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
appContext.close();
}});
If you want to execute some code when child thread completes, better put it in end of run method(thread itself).
Related
Using a post construct approach when we want to conditionally initialise some of the bean's fields, do we need to care about volatility of the field, since it is a multithread environment?
Say, we have something like this:
#ApplicationScoped
public class FooService {
private final ConfigurationService configurationService;
private FooBean fooBean;
#Inject
FooService(ConfigurationService configurationService) {
this.configurationService = configurationService;
}
void init(#Observes #Initialized(ApplicationScoped.class) Object ignored) {
if (configurationService.isFooBeanInitialisationEnabled()) {
fooBean = initialiseFooBean(configurationService); // some initialisation
}
}
void cleanup(#Observes #Destroyed(ApplicationScoped.class) Object ignored) {
if (fooBean != null) {
fooBean.cleanup();
}
}
}
So should the fooBean be wrapped into, let's say, the AtomicReference or be a volatile or it would be a redundant extra protection?
P.S. In this particular case it can be reformulated as: are post construct and post destroy events performed by the same thread or not? However I would like to have an answer for a more general case.
I would say it depends which thread is actually initiating and destroying the contexts.
If you use regular events, they are synchronous (asynchronous events have been added in CDI 2.0 with ObservesAsync, see
Java EE 8: Sending asynchronous CDI 2.0 events with ManagedExecutorService ) so they are called in the same thread as the caller.
In general, I don't think the same thread is used (in application servers or standalone applications) so I would recommend using volatile to ensure the right value is seen (basically the value constructed seen on destroy thread). However, it is not a use case happening so much to initiate and destroy your application in a concurrent way...
FooService is a singleton which is shared between all managed beans in the application.
Annotation Type ApplicationScoped
private FooBean fooBean is a state of the singleton object.
By default, CDI does not manage concurrency so it is the responsibility of a developer.
In this particular case it can be reformulated as: are post construct and post destroy events performed by the same thread or not?
CDI specification does not restrict containers to use the same thread for initialization and destruction of the application context. This behavior is implementation specific. In general case those threads will be different because initialization happens on the thread handling the first request to the application but destruction happens on the thread handling request from management console.
You may delegate concurrency management to EJB container - if your runtime environment includes one.
Neither volatile nor AtomicReference are needed in this case!
Following definition will do the job:
#javax.ejb.Startup // initialize on application start
#javax.ejb.Singleton // EJB Singleton
public class FooService {
private final ConfigurationService configurationService;
private FooBean fooBean;
#javax.inject.Inject
FooService(ConfigurationService configurationService) {
this.configurationService = configurationService;
}
#javax.annotation.PostConstruct
void init() {
if (configurationService.isFooBeanInitialisationEnabled()) {
fooBean = initialiseFooBean(configurationService); // some initialisation
}
}
#javax.annotation.PreDestroy
void cleanup() {
if (fooBean != null) {
fooBean.cleanup();
}
}
}
According to the specification:
An event with qualifier #Initialized(ApplicationScoped.class) is synchronously fired when the application context is initialized.
An event with qualifier #BeforeDestroyed(ApplicationScoped.class) is synchronously fired when the application context is about to be destroyed, i.e. before the actual destruction.
An event with qualifier #Destroyed(ApplicationScoped.class) is synchronously fired when the application context is destroyed, i.e. after the actual destruction.
And according to this presentation Bean manager lifecycle: the lifecycle of the bean manager is synchronous between the different states of the process and the sequence is kept: "destroy not before init".
Jboss are the specification lead of CDI 2.0
I do not see any scenario that would require a volatile/protection. Even if T1 inits then T2 destroys, it will be T1 then T2, not T1 and T2 concurrently.
And even if it would be concurrently, to have an issue it would imply weird scenario, edge scenario outside the CDI runtime:
T2 calls destroy (fooBean is null and now 'cached' in a register)
Then T1 calls init: destroy before init, at this point we are in the 4th dimension of CDI),
Then T2 calls destroy (fooBean is already cached in a register so is value is null)).
Or
T2 calls a method that access fooBean (fooBean is null and now 'cached' in a register)
Then T1 calls init: T1 is initialized whereas fooBean has already been used by T2, at this point we are in the 4th dimension of CDI
Then T2 calls destroy (fooBean is already cached in a register so is value is null)).
#Component
#Scope("prototype")
public class MessageHandller {
.........................
private static ConcurrentMap<String, Boolean> someObjectList = new ConcurrentHashMap<>();
....................................
#Scheduled(fixedDelayString = "60000")
public static void doSomething() {
if(***) {
someObjectList.add(**);
} else {
someObjectList.remove(**);
}
}
}
So let say I have Class MessageHandller which is Spring Bean with Scope of Prototype. In this Class I have Scheduled method "doSomething" which runs every 60000 mili seconds.
I think Scheduled method may cause memory leak, because it will always hold refference to MessageHandler class which is "prototype" scope, which means GC will never collect it? Can someone explain if I'am wrong?
You must clearly differentiate between the method annotated with #Schedule and the bean itself , when you annotate you method and you enable schedule feature through #EnableScheduling or xml alternative, the spring will lookup and search annotated method withing managed bean (annotated with #Compenont, #Service ... ) as the mention in doc
If you read about bean processor ScheduledAnnotationBeanPostProcessor. you'll notice that scope it not involved in the process , and that the method w'll be invoked by TaskScheduler regardless the scope of bean parent
Now for prototype bean the documentation mention that :
In contrast to the other scopes, Spring does not manage the complete lifecycle of a prototype bean: the container instantiates, configures, and otherwise assembles a prototype object, and hands it to the client, with no further record of that prototype instance. Thus, although initialization lifecycle callback methods are called on all objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called. The client code must clean up prototype-scoped objects and release expensive resources that the prototype bean(s) are holding
So when no reference to prototype object it w'll be destroyed by garbage collector implicitly like any new object()
To make it clear the life cycle of the behaviour of the schedule method is different from the bean which is declared because its implementation is used by other bean manager by spring like any of TaskScheduler implementation for that purpose,
Cheers
I was wondering if next scenario is thread-safe:
I have a spring controller with method
#Autowired
private JobService jobService;
public String launch(#ModelAttribute("profile") Profile profile){
JobParameters jobParams = MyUtils.transform(profile);
jobService.launch(profile.getJobName(), jobParams);
return "job";
}
and I have MyUtils class with static method that transforms one kind of object to another... like so :
public class MyUtils {
public static JobParameters transform(Profile profile) {
JobParametersBuilder jpb = new JobParametersBuilder();
jpb.addString("profile.name", profile.getProfileName());
jpb.addString("profile.number", String.valueOf(profile.getNumber()));
return jpb.toJobParameters();
}
}
Classes JobParametersBuilder , JobParameters and JobService are from spring batch core project. Profile class is simple POJO.
The question really is... is this static method transform thread-safe since it is dealing with object instances, although all of those instances are locally created for the method.
This concrete code IS thread safe if some conditions are met. Here is explanation:
launch method is called from Spring boot controller. Every call that comes to Spring boot controller is called from different thread and that thread is taking execution to the end of the call stack(unless you call some asynchronous call inside that thread). Tomcat can handle 200 threads in same time by default. Which means you can have 200 calls to your Controllers in same time and they will all be in separate threads. Which means launch is thread safe.
Profile is passed to the transform method and if it is simple POJO it is thread safe, because on every call it will be new instance of Profile.
Inside transform method you are instantiate JobParametersBuilder every time which is thread safe if code inside toJobParameters is thread safe and doesn't keep any state of the JobParametersBuilder class or some other.
I have following code in one my team projects:
this.context = new ClassPathXmlApplicationContext("test_spring.xml");
this.task = ((Task)this.context.getBean("task"));
this.context.registerShutdownHook();
this.context.start();
I have never before seen "start" method being called and i dont understand whats the need of start method?
Spring Documentation says:
Start this component. Should not throw an exception if the component is already running.
In the case of a container, this will propagate the start signal to all components that apply.
But i dont understand what does it imply. Can someone explain what can go wrong if start method is not called or how does it helps?
Spring provides a ApplicationListener interface to listen for various ApplicationEvents. One such event is the ContextStartedEvent. You can create a bean of some class that implements ApplicationListener<ContextStartedEvent>.
When you invoke start(), the ApplicationContext will publish such an event and all ApplicationListener beans registered for ContextStartedEvent (they get registered automatically if found in the context) will get notified.
If you don't call start(), they will not get notified.
Timers are created in EJB3 using the TimerService.createTimer(), and are then run via whatever callback method that's annotated by the #Timeout annotation, i.e:
#Resource
private TimerService timerService;
public void createHampster() {
Hampster hampster = new Hampster("Fluffy III");
timerService.createTimer(3000, 3000, hampster);
}
(...)
#Timeout
public void feedHampster(Timer timer) {
Hampster hampster = (Hampster) timer.getInfo()
//(...)
}
So, my question is, do these two blocks of code need to be within the same bean? Are timers inherit to the bean in which they were created, or are they global? My own testing suggests but former, and I haven't found anything definite in the documentation.
They are tied to the bean that creates them. EJB 3 specification sections 18.2 says:
The bean class of an enterprise bean
that uses the timer service must
provide a timeout callback method.
and
When the time specified at timer
creation elapses, the container
invokes the timeout callback method of
the bean.