Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tasks created using task:scheduled-tasks never start if default-lazy-init="true" [SPR-8498] #13144

Closed
spring-projects-issues opened this issue Jun 29, 2011 · 13 comments
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

Mike Youngstrom opened SPR-8498 and commented

Given the example below. My scheduled task will never start. If I change default-lazy-init="false" then the scheduled task starts. It seems to me that the scheduled-tasks created from the task namespace handler should be forced to be lazy=false.

applicationContext.xml
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd" default-lazy-init="true">
task:scheduled-tasks
<task:scheduled ref="someService" method="print" fixed-rate="2000"/>
</task:scheduled-tasks>

<bean id="someService" class="org.lds.stack.example.service.SomeService"/>

</beans>
SomeService.java
public class SomeService {
public void print() {
System.out.println("Dude");
}
}


Attachments:

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

Hi Mike,

While I agree that the result of this is unintuitive at first glance, it is nevertheless consistent behavior. In light of 3.1's support for nested <beans> elements, could it be sufficient for you to a) nest the task within a <beans default-lazy-init="false"> block, or b) nest only those beans that need to be lazy within a <beans default-lazy-init="true"> block (leaving the enclosing <beans> element's default-lazy-init attribute alone)?

@spring-projects-issues
Copy link
Collaborator Author

Mike Youngstrom commented

While I think nesting beans makes the work around less bad than the current solution of creating another file I think the nested beans element makes the problem no more intuitive.

I act as a central support engineer for my organization of a couple of hundred developers. I think pretty much every project I know of that uses task:scheduled-tasks has run into this issue. Our project templates set default-lazy-init="true".

I can see the value of consistency. However, can you think of any scenario where a lazy scheduled-task would be useful?

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

All reasonable points, and I agree that it's unlikely a lazy scheduled-task would even make sense. Changing to 'improvement' as it's not technically a bug, but nevertheless will look at resolving this for RC1.

It sounds like it's quite common for you guys to use default-lazy-init. I believe this approach is comparatively rare. Just out of curiosity, what leads to this pattern? i.e. what benefit do you get out of being lazy by default? Do you actually have so many beans that may or may not be used in a given runtime?

@spring-projects-issues
Copy link
Collaborator Author

Mike Youngstrom commented

Our use of lazy contexts is somewhat historical. We used to provide a rather large set of default configuration portions of which may or may not be turned on based upon the preferences of the project (caching, hibernate, etc).

Now, however, the benefit isn't as direct. We've moved most of that type of configuration in to namespace handlers so lazy initialization doesn't factor into the runtime directly like it used to. Now the benefit is mostly in development start up times. Quite often in a developer will focus on a relatively small portion of an application so there is some benefit in not initializing components that aren't used. Another benefit is developers don't seem to notice initialization of components as much when using the application as apposed to when they are sitting looking at their startup console waiting it to be started.

I've seen startup times benefit from lazy initialization ranging from 2 sec to 30 sec. Which can be significant. If we run into more problems like scheduled-task we might consider changing our default. But as it is use of scheduled-task is comparatively rare among our projects so I don't think this issue alone is enough to change the default. Generally speaking we rarely run into any other issues with lazy initialization.

@spring-projects-issues
Copy link
Collaborator Author

Mike Youngstrom commented

Would a patch for this come in handy? It seems like a rather simple change but perhaps it would save some time for me to provide a tested patch?

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

Feel free, yes! As the fixVersion makes clear, we will make this happen in any case for 3.1 RC1, but patches are always welcome.

@spring-projects-issues
Copy link
Collaborator Author

Mike Youngstrom commented

Patch forces ScheduledTaskRegistrar to not be lazy. Should be the central catalyst to initialize others in a lazy environment.

Added a test.

I also updated the other scheduler tests to close the context when done. Normally it is probably fine to leave contexts around. However, in this case leaving activated schedulers around probably isn't a good idea.

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

Thanks for the patch Mike! You'll find this change is now in place with the next nightly snapshot (and available in source now).

@spring-projects-issues
Copy link
Collaborator Author

Guy Incognito commented

actually, i'm not sure i'm so keen on this. pre-patch, the behaviour is that if i have a bean that is lazy-init, that is only referenced in a scheduled-tasks element, then the task will never actually run because the bean will not be initialized unless it is reference elsewhere. post-patch, the task will always be run regardless?

i quite like the idea that i can specify a task that runs against a bean only if the bean is required by something else.

@spring-projects-issues
Copy link
Collaborator Author

Mike Youngstrom commented

Pre-Patch the bean that is lazy is the instance of org.springframework.scheduling.config.ScheduledTaskRegistrar. This is the bean that needs to not be lazy in order for any tasks to be fired. Currently there is no way to dictate the firing of a scheduled task based on if a transitive bean is initialized or not.

@spring-projects-issues
Copy link
Collaborator Author

Mauro Molinari commented

Before opening a new bug, I would like to know if I understand this bug report (and fix) right.

I'm using Spring 4.2.8.RELEASE. My applicationContext.xml specifies default-lazy-init="true", I have <task:annotation-driven> and a @Named annotated bean with a method annotated with @Scheduled. In this scenario, the scheduled method is never invoked,unless I annotate the owning bean also with @Lazy(false). I would like to understand if this is the expected behaviour, because it isn't intuitive for me (I thought that annotation scanning and processing would have found my @Scheduled method anyway and trigger an eager bean initialisation). Also, if I understand this bug report and fix right, I would expect the @Lazy(false) annotation not to be required.

This Stack Overflow question: http://stackoverflow.com/questions/15333108/running-scheduled-method-with-lazy-init-option-of-the-class-it-belongs-to
seems also to suggest that I am right and that I've hit a problem, probably because I'm adding my scheduled bean to the application context through @Named annotation rather than by declaring it in the XML config file.

Thanks in advance for any hint.

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

This sounds like expected behavior: @Scheduled on its own does not trigger creation of a particular bean. Scheduled callbacks are just applied during the natural lifetime of each bean instance, but the creation of the bean instance itself needs to be triggered by some other means (declared as non-lazy singleton, explicit access to lazy singleton, etc).

@spring-projects-issues
Copy link
Collaborator Author

Mauro Molinari commented

Thank you Juergen! This puzzles me a bit, because its sounds incoherent with other ways of scheduling something (and with what was reported on that Stack Overflow question, maybe it was experienced with an older Spring Framework version and changed meanwhile...).

I would also like to notify to you too, that this JIRA instance is not sending mail notifications about new messages any more... I already notified Spring Integration devs about this problem some weeks ago and they said they're aware of the problem, but it's still there :(

@spring-projects-issues spring-projects-issues added type: enhancement A general enhancement in: core Issues in core modules (aop, beans, core, context, expression) labels Jan 11, 2019
@spring-projects-issues spring-projects-issues added this to the 3.1 RC1 milestone Jan 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

1 participant