FULL PRODUCT VERSION :
A DESCRIPTION OF THE PROBLEM :
When you add a changelistener to ScheduledService.stateProperty(), you will realize that the service does not transition into "SUCCEEDED" state after each iteration. However, ScheduledService.setOnSucceeded() can still be used to detect the completion of each iteration. Additionally, ScheduledService.stateProperty() transitions to "SCHEDULED" state twice on every iteration.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
The sample code creates an instance of ScheduledService which polls every 2 seconds. The sample prints out every new state received from ScheduledService.stateProperty()'s changelistener, and sets an event handler for SUCCEEDED state.
final ScheduledService<Void> service = new ScheduledService<Void>() {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() throws Exception
{
return null;
}
};
}
};
service.setOnSucceeded(event -> {
System.out.println("onSucceeded() triggered!");
});
service.stateProperty().addListener((obs, o, n) -> {
System.out.println("Old: " + o);
System.out.println("New: " + n);
});
service.setPeriod(Duration.seconds(2));
service.start();
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Old: READY
New: SCHEDULED
Old: SCHEDULED
New: RUNNING
Old: RUNNING
New: SUCCEEDED
onSucceeded() triggered!
Old: SUCCEEDED
New: READY
Old: READY
New: SCHEDULED
Old: SCHEDULED
New: RUNNING
Old: RUNNING
New: SUCCEEDED
onSucceeded() triggered!
Old: SUCCEEDED
New: READY
Old: READY
New: SCHEDULED
ACTUAL -
Old: READY
New: SCHEDULED
Old: SCHEDULED
New: RUNNING
onSucceeded() triggered!
Old: SUCCEEDED
New: READY
Old: READY
New: SCHEDULED
Old: RUNNING
New: SCHEDULED
Old: SCHEDULED
New: RUNNING
onSucceeded() triggered!
Old: SUCCEEDED
New: READY
Old: READY
New: SCHEDULED
Old: RUNNING
New: SCHEDULED
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
See "Steps to Reproduce."
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Using the respective setOn<State>() event handler setter seems to work correctly.
A DESCRIPTION OF THE PROBLEM :
When you add a changelistener to ScheduledService.stateProperty(), you will realize that the service does not transition into "SUCCEEDED" state after each iteration. However, ScheduledService.setOnSucceeded() can still be used to detect the completion of each iteration. Additionally, ScheduledService.stateProperty() transitions to "SCHEDULED" state twice on every iteration.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
The sample code creates an instance of ScheduledService which polls every 2 seconds. The sample prints out every new state received from ScheduledService.stateProperty()'s changelistener, and sets an event handler for SUCCEEDED state.
final ScheduledService<Void> service = new ScheduledService<Void>() {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() throws Exception
{
return null;
}
};
}
};
service.setOnSucceeded(event -> {
System.out.println("onSucceeded() triggered!");
});
service.stateProperty().addListener((obs, o, n) -> {
System.out.println("Old: " + o);
System.out.println("New: " + n);
});
service.setPeriod(Duration.seconds(2));
service.start();
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Old: READY
New: SCHEDULED
Old: SCHEDULED
New: RUNNING
Old: RUNNING
New: SUCCEEDED
onSucceeded() triggered!
Old: SUCCEEDED
New: READY
Old: READY
New: SCHEDULED
Old: SCHEDULED
New: RUNNING
Old: RUNNING
New: SUCCEEDED
onSucceeded() triggered!
Old: SUCCEEDED
New: READY
Old: READY
New: SCHEDULED
ACTUAL -
Old: READY
New: SCHEDULED
Old: SCHEDULED
New: RUNNING
onSucceeded() triggered!
Old: SUCCEEDED
New: READY
Old: READY
New: SCHEDULED
Old: RUNNING
New: SCHEDULED
Old: SCHEDULED
New: RUNNING
onSucceeded() triggered!
Old: SUCCEEDED
New: READY
Old: READY
New: SCHEDULED
Old: RUNNING
New: SCHEDULED
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
See "Steps to Reproduce."
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Using the respective setOn<State>() event handler setter seems to work correctly.