2

I have a TaskScheduler class like this :

public class NotificationManger {

@Autowired
private TaskScheduler scheduler;

private ScheduledFuture<?> sc;

public NotificationManger(WebSocketMessage webSocketMessage, String userName, Date date, Date time) {
    scheduleTask(webSocketMessage, userName, combine(date,time));
}

public void scheduleTask(WebSocketMessage webSocketMessage, String userName, Date startTime) 
  { 
    Runnable r = new NotificationSenderTask(webSocketMessage, userName);

    sc = scheduler.schedule(r, new Date());//here I get a  NullPointerException 

   }
}

and a Runnable class like this :

class NotificationSenderTask implements Runnable {

@Autowired
SimpMessagingTemplate webSocketMessageTemplate;

private String userName;

private WebSocketMessage webSocketMessage;

public NotificationSenderTask(WebSocketMessage webSocketMessage, String userName) {
    this.webSocketMessage = webSocketMessage;
    this.userName = userName;
}

public void run() {

    webSocketMessageTemplate.convertAndSendToUser(userName, "/notification", webSocketMessage);;
}

}

and I call the TaskScheduler : NotificationManger mn = new NotificationManger(new WebSocketMessage(n), user.getEmail(),date1,date2 );

but I'm getting a java.lang.NullPointerException: null at sc = scheduler.schedule(r, new Date());

maybe I'm using the runnable class wrong.

Any help will be appreciated, Thank you.

EDIT :

@EnableWebMvc
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
@Configuration
@ComponentScan(basePackages = "gestionprojet.java")
@PropertySource("classpath:application.properties")
@Import({PersistenceJPAConfig.class, WebSecurityConfig.class})
public class WebConfig extends WebMvcConfigurerAdapter {...}
Oddkills
  • 67
  • 1
  • 8
  • so your `TaskScheduler` is not getting injected? – Scary Wombat Jan 20 '17 at 02:55
  • Well actually I don't know but now you've mentioned I think so – Oddkills Jan 20 '17 at 02:57
  • First thing to check I thinks – Scary Wombat Jan 20 '17 at 02:58
  • will do now.... – Oddkills Jan 20 '17 at 03:02
  • yep it's not injected, how to fix it ? :D – Oddkills Jan 20 '17 at 03:04
  • your NotificationManager is not Spring Managed (as you've shown with `NotificationManger mn = new NotificationManger(...);`, so no autowiring is performed on it! – alexbt Jan 20 '17 at 03:04
  • you mean the class should be annotated @alexbt – Oddkills Jan 20 '17 at 03:08
  • Well... yes, but its constructor also takes a non-spring managed (ie: `new WebSocketMessage(n)`). The whole stack need to be spring-managed. If you have a Configuration class, you could add an @Bean method to create the NotificationManger there. Then, it would be Spring-managed and the scheduler would be autowired. It may require some refactoring.. Perhaps the Scheduler may be injected before and passed as argument ? – alexbt Jan 20 '17 at 03:10
  • can't I just annotate it with `@Component` and it will be injected and managed automatically ? – Oddkills Jan 20 '17 at 03:12
  • No I can't inject the scheduler before cause I will need to injected it in multiple other classes – Oddkills Jan 20 '17 at 03:14
  • try it you'll see.. It needs either a no-args constructor OR a constructor where all the arguments are also `Components`. Since your constructor takes 4 non-spring managed arguments, it won't work, unless you make these 4 also `@Component`. I think you may need to go through a Spring tutorial first! – alexbt Jan 20 '17 at 03:15
  • Okay...So I need to inject the class as a bean in my webconfig an use setters and getters, you think this will work ? this way I don't handle the parameters – Oddkills Jan 20 '17 at 03:18
  • can you post your Webconfig ? – alexbt Jan 20 '17 at 03:19
  • and you were right about the @Component – Oddkills Jan 20 '17 at 03:19
  • Check now, I don't think you need the full code no ? cause all that's left are beans – Oddkills Jan 20 '17 at 03:22

2 Answers2

2

AutowireHelper to the rescue

Instead of refactoring all the code, the OP actually found a library to force autowiring into a non-spring-managed bean:

The library is: https://github.com/alv-ch/alv-ch-java

it can be used this way:

public class NotificationManager {
    @Autowired
    private TaskScheduler scheduler;

    public NotificationManager(WebSocketMessage webSocketMessage, String userName, Date date, Date time) {
        AutowireHelper.autowire(this, scheduler);
        scheduleTask(webSocketMessage, userName, combine(date,time));
    }
    ...
}

This will autowire the TaskScheduler into NotificationManager, even if it is not spring managed. You can see AutowireHelper source code here.


Another possible solution

1. Annotate NotificationManager with @Service and remove constructor:

@Service
public class NotificationManager {

    @Autowired
    private TaskScheduler scheduler;

    private ScheduledFuture<?> sc;

    public void scheduleTask(WebSocketMessage webSocketMessage, String userName, Date date, Date time) {
        scheduleTask(webSocketMessage, userName, combine(date,time));
    }

    public void scheduleTask(WebSocketMessage webSocketMessage, String userName, Date startTime) 
    { 
        Runnable r = new NotificationSenderTask(webSocketMessage, userName);
        sc = scheduler.schedule(r, new Date());

   }
}

2. Autowire NotificationManager

Then, at the location where you used to do NotificationManager mn = new NotificationManager(...), do this instead:

@Autowired 
private NotificationManager notificationManager;

...
notificationManager.scheduleTask(new WebSocketMessage(n), user.getEmail(),date1,date2);

For this to work, wherever this is, it also needs to be inside a spring-managed bean.

alexbt
  • 16,415
  • 6
  • 78
  • 87
-2

You have not initialized the global instance variable

private TaskScheduler scheduler ;

Since it's an global instance variable it do not give any compile time error for it and it get initialized with null value implicitly.

That is why when you try to access scheduler.schedule it throws null pointer error.

Hope this solve your query.

siddhartha jain
  • 1,006
  • 10
  • 16