2
public class ProcessSchedulerServlet implements javax.servlet.Servlet {
    Timer timer=new Timer();

    @Override
    public void init(ServletConfig arg0) throws ServletException {
        timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            LogProcessorService logProcessorService=new LogProcessorServiceImpl();
            logProcessorService.processPageRequestsLogs();
        }
     }, 60*1000, 120*1000);
}

This is ugly and it doesn't work, anyway. The LogProcessorServiceImpl has properties with @Autowired annotation. These properties are not autowired when this code runs. This may be expected.

The real question is: how to make this run() method work. It seems to me that Spring wants the logProcessorService to be autowired to have properties within LogProcessorServiceImpl autowired, as well.

=== SCENARIO 1 ==============================================================

public void run() {
    final LogProcessorService logProcessorService=null;
    WebApplicationContextUtils.getWebApplicationContext(arg0.getServletContext()).getAutowireCapableBeanFactory().autowireBean(logProcessorService);
    logProcessorService.processPageRequestsLogs();
}

Result: compile time error: Cannot refer to a non-final variable arg0 inside an inner class defined in a different method

=== SCENARIO 2 ==============================================================

@Autowired
LogProcessorService logProcessorService;
public void run() {
    logProcessorService.processPageRequestsLogs();
}

Result: run time error: logProcessorService is null;

==== SOLUTION (from Boris) ======================================================

public class ProcessSchedulerServlet implements javax.servlet.Servlet {
    Timer timer=new Timer();

    @Autowired
    LogProcessorService logProcessorService;

    @Override
    public void init(ServletConfig arg0) throws ServletException {
        final AutowireCapableBeanFactory autowireCapableBeanFactory=WebApplicationContextUtils.getWebApplicationContext(arg0.getServletContext()).getAutowireCapableBeanFactory();
        autowireCapableBeanFactory.autowireBean(this);

        timer.scheduleAtFixedRate(new TimerTask() {
            public void run() {
                logProcessorService.processPageRequestsLogs();
            }
        }, 60*1000, 120*1000);
}
jacekn
  • 1,521
  • 5
  • 29
  • 50
  • what's wrong with the manual autowiring shown in [my answer](http://stackoverflow.com/questions/13437741/why-would-spring-autowire-fail/13437803#13437803)? Why are you creating LogProcessorService with new operator instead of delegating its creation to Spring container? – Boris Treukhov Nov 18 '12 at 06:21
  • Boris, nothing that I'm trying works. I'm simply posting another question with less info and more direct issue to avoid people digesting all of my logic. This right now should be a very simple issue to understand. Can't autowire a static property, so I'm trying implementer directly. No luck. What is it that you would do wiht this? The answer should deal directly with the two lines within the run() method. – jacekn Nov 18 '12 at 06:29
  • RE `The LogProcessorServiceImpl has properties with @Autowired annotation` that implies it's rather a Spring bean; you can still do manual autowiring `WebApplicationContextUtils.getWebApplicationContext(arg0.getServletContext()) .getAutowireCapableBeanFactory().autowireBean(logProcessorService);` but there's no objective reason for doing this as it is supposed to be Spring bean - i.e. instantiated and autowired with the Spring container. – Boris Treukhov Nov 18 '12 at 06:35
  • Boris, in your comment you imply that I can do either, or. The problem is neither works for me. Let's take the autowired Spring bean for LogProcessorServiceImpl. How would you write the run() method quoted in my question? – jacekn Nov 18 '12 at 06:49
  • Assuming that the idea with timer correct - in the real app I would use [Spring scheduling API]( http://static.springsource.org/spring/docs/3.0.x/reference/scheduling.html) I would just inject the bean with @Autowired to the servlet and call it's `fire()` or whatever method in the `run()`. What is currently not working? – Boris Treukhov Nov 18 '12 at 06:54
  • I'll use the question to illustrate the issues. – jacekn Nov 18 '12 at 06:56
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/19700/discussion-between-boris-treukhov-and-jacekn) – Boris Treukhov Nov 18 '12 at 06:57
  • P.S. the problem seems to be resolved, I think the question may be closed as the duplicate of http://stackoverflow.com/questions/13437741/why-would-spring-autowire-fail/13437803 – Boris Treukhov Nov 18 '12 at 07:58
  • you shold not post the incorrect variant with autowiring :-( it's `.autowireBean(this)` and `@Autowired` ` LogProcessorService logProcessorService;` – Boris Treukhov Nov 18 '12 at 08:04

1 Answers1

4

Why bother with servlets and Timer class if Spring has a built in scheduling support:

@Service
public class LogProcessorService {

    @Scheduled(fixedRate=120*1000, initialDelay=60*1000)
    public void processPageRequestsLogs() {
        //...
    }

}

That's it! No timers, runnables and servlets. Note: initialDelay was introduced in Spring 3.2 M1 (see SPR-7022).

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • Notice that the question is not about the timer. Timer is simple to use and gives me ability to schedule events dynamically. I used a basic example here because more code would confuse the issue. And the issue was: how to get Spring to autowire a service within TimerTask which Boris figured out. – jacekn Nov 18 '12 at 15:48
  • @jacekn: I understand. On the other hand you might want to move `Timer` handling to another Spring beans to simplify autowiring. Nevertheless I don't want to remove my answer since few people found it interesting so please turn comments below your question into an answer (or ask Boris to do so) and accept it. – Tomasz Nurkiewicz Nov 18 '12 at 15:57
  • @jacekn this answer perfectly answers the question, Spring scheduling API is the way to go of course. SO is about sharing the information, and it's ok to get the answer that in some way criticizes the approach used in the question - we are all learners here http://meta.stackexchange.com/questions/8891/is-dont-do-it-a-valid-answer – Boris Treukhov Nov 18 '12 at 16:28
  • @BorisTreukhov Boris, please... Where do you see critism in my comment to Tomasz? The question is "How to go about Spring autowiring?" and not "How would you schedule this simple service call?". I'm not going to paste my schedule logic because it's all "business logic" completely irrelevant to what my challenge is. Or was, as you have helped me address this. Please add an answer here so I can give you the credit. Thanks, again. – jacekn Nov 19 '12 at 23:26