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.
Related
#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
This question already has answers here:
Why use #PostConstruct?
(4 answers)
Closed 5 years ago.
What is the difference between
public UserBean() {
// create the session state
state = new BigInteger(64, new SecureRandom()).toString(32);
}
and
public UserBean() {
init();
}
#PostConstruct
public void init() {
// create the session state
state = new BigInteger(64, new SecureRandom()).toString(32);
}
where state is one of the many attributes of the class.
You misunderstand the #PostConstruct annotation.
A method annotated with should be invoked by the container after dependency injection was performed. It has not to be invoked by your applicative code.
So of course using #PostConstruct without container (EJB, Spring, Guice...) makes no sense.
The #PostConstruct doc states :
The PostConstruct annotation is used on a method that needs to be
executed after dependency injection is done to perform any
initialization.
To summarize :
the container creates the bean by invoking the constructor
the container sets the bean dependencies
the #PostConstruct method is invoked
Note that between the steps 1, 2 and 3, the container may perform other tasks for other beans but you should not worry about that as the javadoc also states that #PostConstruct method MUST be invoked before the class is put into service.
Similar questions have been asked, but don't quite address what I'm trying to do. We have an older Seam 2.x-based application with a batch job framework that we are converting to CDI. The job framework uses the Seam Contexts object to initiate a conversation. The job framework also loads a job-specific data holder (basically a Map) that can then be accessed, via the Seam Contexts object, by any service down the chain, including from SLSBs. Some of these services can update the Map, so that job state can change and be detected from record to record.
It looks like in CDI, the job will #Inject a CDI Conversation object, and manually begin/end the conversation. We would also define a new ConversationScoped bean that holds the Map (MapBean). What's not clear to me are two things:
First, the job needs to also #Inject the MapBean so that it can be loaded with job-specific data before the Conversation.begin() method is called. Would the container know to pass this instance to services down the call chain?
Related to that, according to this question Is it possible to #Inject a #RequestScoped bean into a #Stateless EJB? it should be possible to inject a ConservationScoped bean into a SLSB, but it seems a bit magical. If the SLSB is used by a different process (job, UI call, etc), does it get separate instance for each call?
Edits for clarification and a simplified class structure:
MapBean would need to be a ConversationScoped object, containing data for a specific instance/run of a job.
#ConversationScoped
public class MapBean implements Serializable {
private Map<String, Object> data;
// accessors
public Object getData(String key) {
return data.get(key);
}
public void setData(String key, Object value) {
data.put(key, value);
}
}
The job would be ConversationScoped:
#ConversationScoped
public class BatchJob {
#Inject private MapBean mapBean;
#Inject private Conversation conversation;
#Inject private JobProcessingBean jobProcessingBean;
public void runJob() {
try {
conversation.begin();
mapBean.setData("key", "value"); // is this MapBean instance now bound to the conversation?
jobProcessingBean.doWork();
} catch (Exception e) {
// catch something
} finally {
conversation.end();
}
}
}
The job might call a SLSB, and the current conversation-scoped instance of MapBean needs to be available:
#Stateless
public class JobProcessingBean {
#Inject private MapBean mapBean;
public void doWork() {
// when this is called, is "mapBean" the current conversation instance?
Object value = mapBean.getData("key");
}
}
Our job and SLSB framework is quite complex, the SLSB can call numerous other services or locally instantiated business logic classes, and each of these would need access to the conversation-scoped MapBean.
First, the job needs to also #Inject the MapBean so that it can be loaded with job-specific data before the Conversation.begin() method is called. Would the container know to pass this instance to services down the call chain?
Yes, since MapBean is #ConversationScoped it is tied to the call chain for the duration starting from conversation.begin() until conversation.end(). You can think of #ConversationScoped (and #RequestScoped and #SessionScoped) as instances in ThreadLocal - while there exists an instance of them for every thread, each instance is tied to that single thread.
Related to that, according to this question Is it possible to #Inject a #RequestScoped bean into a #Stateless EJB? it should be possible to inject a #ConservationScoped bean into a SLSB, but it seems a bit magical. If the SLSB is used by a different process (job, UI call, etc), does it get separate instance for each call?
It's not as magical as you think if you see that this pattern is the same as the one I explained above. The SLSB indeed gets a separate instance, but not just any instance, the one which belongs to the scope from which the SLSB was called.
In addition to the link you posted, see also this answer.
Iv'e tested a similar code to what you posted and it works as expected - the MapBean is the same one injected throughout the call. Just be careful with 2 things:
BatchJob is also #ConversationScoped but does not implement Serializable, which will not allow the bean to passivate.
data is not initialized, so you will get an NPE in runJob().
Without any code samples, I'll have to do some guessing, so let's see if I got you right.
Would the container know to pass this instance to services down the call chain?
If you mean to use the same instance elsewhere in the call, then this can be easily achieved by making the MapBean an #ApplicationScoped bean (or, alternatively, and EJB #Singleton).
it should be possible to inject a ConservationScoped bean into a SLSB, but it seems a bit magical.
Here I suppose that the reason why it seems magical is that SLSB is in terms of CDI a #Dependent bean. And as you probably know, CDI always creates new instance for dependent bean injection point. E.g. yes, you get a different SLS/Dependent bean instance for each call.
Perhaps some other scope would fit you better here? Like #RequestScoped or #SessionScoped? Hard to tell without more details.
I am following the Using the Timer Service tutorial to build a simple scheduled execution. Trying the automatic approach and using WildFly 8.1.0 Final for it.
Session Bean
#Singleton
#Startup
public class HelloJob {
private static final Logger logger = Logger.getLogger(HelloJob.class);
public HelloJob() {
logger.error(">>> Hello Job Created.");
}
#Schedule(second="*")
public void sayHello() {
logger.error(">>> Server Hello!");
}
}
On deploy the class is properly instantiated printing the >>> Hello Job Created. message, but the method sayHello() is never called.
According to the tutorial the #Schedule(second="*") means that it should execute every second.
Setting an attribute to an asterisk symbol (*) represents all
allowable values for the attribute.
Also only stateful session beans are not allowed for timers, and I am using a singleton, which is also used in the example.
The timer service of the enterprise bean container enables you to
schedule timed notifications for all types of enterprise beans except
for stateful session beans.
Use #Schedule(second="*", minute="*", hour="*").
the default values for hour and minute are "0" which can be quite irritating and effectively forces you to set these.
I'm doing my graduation project, and have run into a dilemma here.
I need to make an application that generates PDFs and emails them to people on a schedule defined by data in the database.
I'm working for a company with this project, and we already have a GlassFish application server that we use. It would be best if the entire solution is delivered in one package, as it is now.
Client with webstart
Web Application etc. is all in one package
My new service needs to run on a separate thread, generate reports and send them out on emails. From what I can read on the web, running your own threads in an application server as GlassFish is highly discouraged, so it sounds like I need to make my own separate application.
Can this really be? What are your comments, and what are the best practices for this?
#Schedule
If you are using Ejb 3.1 (glassfish 3.x), you may use the #Schedule annotation to have the container invoke a method in a specified interval or at a given calendar time. Allowing you to avoid handling threads in your own code
Read about ejb 3.1 timer
#Stateless
public class LabbBean {
#EJB
WorkerEjb workerEjb;
#Schedule(second="*/5", minute="*",hour="*", persistent=false)
public void myMethod() {
for (all jobs found in db){
workerEjb.workerMethod(job);
}
}
}
#Stateless
public class WorkerEjb {
#Asynchronous
public void workerMethod(job) {
//Send emails
}
}
If you wanted to do the work in separate threads, the #Schedule annotated method could call a worker-ejb with the worker-method annotated as #Asynchronous
#Timeout
I just realised you wanted the schedule to be initiated from the database. An option the would be to initiate a bunch of timers programmatically using a #Singleton ejb with #Startup annotation. The timeout annotated method would be called in separate threads if some timers run out at the same time.
#Singleton
#Startup
public class LabbBean {
#Resource
protected TimerService timerService;
#PostConstruct
public void init() {
//Init your timers from the data in the database here
for (all your timers) {
TimerConfig config = new TimerConfig();
config.setInfo("timer1");
config.setPersistent(false);
ScheduleExpression schedule = new ScheduleExpression();
schedule.dayOfMonth(10);
schedule.minute(2);
timerService.createCalendarTimer(schedule, config);
}
}
//method called when timeout occurs
#Timeout
public void timeoutHandler(Timer timer) {
String name = timer.getInfo().toString();
System.out.println("Timer name=" + name);
}
}