2013-08-06 10 views
7

Ok, so ist es hier möchte ich eine Aufgabe planen am letzten Tag eines jeden Monats auf 10.10 AM.My Cron-Ausdruck zu laufen istProblemumgehung für CronSequenceGenerator Letzter Tag des Monats?

0 10 10 L * ? 

Nun das Problem ist CronSequenceGenerator ist Number für ‚L‘ zu werfen Das bedeutet, dass Spring's CronSequenceGenerator diese Art von Ausdruck nicht unterstützt. Wie kann ich das anders machen (Workaround). Ich möchte keinen Quarz verwenden oder Wird der Frühling das in neuen Versionen unterstützen? Hier

ist voll Stacktrace:

Exception in thread "main" java.lang.NumberFormatException: For input string: "L" 
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) 
    at java.lang.Integer.parseInt(Integer.java:492) 
    at java.lang.Integer.valueOf(Integer.java:582) 
    at org.springframework.scheduling.support.CronSequenceGenerator.getRange(CronSequenceGenerator.java:324) 
    at org.springframework.scheduling.support.CronSequenceGenerator.setNumberHits(CronSequenceGenerator.java:297) 
    at org.springframework.scheduling.support.CronSequenceGenerator.setDays(CronSequenceGenerator.java:275) 
    at org.springframework.scheduling.support.CronSequenceGenerator.setDaysOfMonth(CronSequenceGenerator.java:266) 
    at org.springframework.scheduling.support.CronSequenceGenerator.parse(CronSequenceGenerator.java:239) 
    at org.springframework.scheduling.support.CronSequenceGenerator.<init>(CronSequenceGenerator.java:81) 
    at org.springframework.scheduling.support.CronTrigger.<init>(CronTrigger.java:54) 
    at org.springframework.scheduling.support.CronTrigger.<init>(CronTrigger.java:44) 
    at com.hcdc.coedp.datantar.scheduler.SchedulerUtil.start(SchedulerUtil.java:75) 
    at com.hcdc.coedp.datantar.scheduler.SchedulerUtil.changeTrigger(SchedulerUtil.java:106) 
    at com.hcdc.coedp.datantar.scheduler.SchedulingService.scheduleTransfer(SchedulingService.java:70) 
    at com.hcdc.coedp.datantar.scheduler.Scheduler.schedule(Scheduler.java:107) 
    at main.Main.main(Main.java:47) 

Update:

Es folgt mein Scheduling-Verfahren

/** 
    * Schedule a task {@link Task} with a specified cron expression. 
    * @param task {@link Task} 
    * @param cronExpression cron expression to be applied must be a vaild one. 
    * @param taskName 
    * @return 
    */ 
    public String start(Task task, String cronExpression, String taskName) { 
     CronTrigger trigger = new CronTrigger(cronExpression);//line 2 

     CronSequenceGenerator generator = new CronSequenceGenerator(cronExpression, TimeZone.getTimeZone("GMT+5:30")); 
     List<Date> dateList = new ArrayList<>(5); 
     Date currentDate = new Date(); 
     for (int i = 0; i < 5; i++) { 
      currentDate = generator.next(currentDate); 
      dateList.add((currentDate)); 
      System.out.println("Next Exceution times are" + currentDate); 
     } 
     ScheduledFuture sf = tps.schedule(task, trigger); 

     //TODO Save this scheduled future with a specific task name. 
     ContextHolder.schduledFutureMap.put(taskName, sf); 
     return cronExpression; 
    } 

Und auf der Linie 2 wirft Number wenn ich Cron-Ausdruck angegeben passieren.

+0

Ich sah mich um ein wenig, und es scheint, dass L tatsächlich unterstützt wird. Wie definierst du den Job? Anmerkung? Sie sollten dies wahrscheinlich zu Ihrer Frage hinzufügen. – Magnilex

+0

@Magnilex überprüfen update –

+0

Großartig. Könnten Sie auch den entsprechenden Code einfügen, der die 'start()' Methode aufruft? Es tut mir leid, aber ich denke wirklich, dass 'L' funktionieren sollte. – Magnilex

Antwort

6

Diese Funktion ist nicht in standard cron expression syntax die Ausführung planen. Wahrscheinlich wird Spring das also nie umsetzen. Mit Blick auf die code, kann ich keine chirurgische Lösung CronSequenceGenerator. Warum benutzt man einfach nicht Quarz, weil es ein particular feature ist?

Abhängig von Ihrem genauen Bedarf könnten Sie Ihre eigenen Trigger implementieren. Etwas wie:

import java.util.Date; 

import org.joda.time.LocalDate; 
import org.joda.time.LocalTime; 
import org.springframework.scheduling.Trigger; 
import org.springframework.scheduling.TriggerContext; 

public class LastDayOfMonthTrigger implements Trigger { 

    private final LocalTime time; 

    public LastDayOfMonthTrigger(LocalTime time) { 
     this.time = time; 
    } 

    @Override 
    public Date nextExecutionTime(TriggerContext ctx) { 
     Date last = ctx.lastScheduledExecutionTime(); 
     LocalDate date = last == null ? new LocalDate() : new LocalDate(last).plusDays(1); 
     LocalDate lastDay = date.dayOfMonth().withMaximumValue(); 
     return lastDay.toDateTime(time).toDate(); 
    } 
} 
+0

Danke, und ich könnte nicht Quarz verwenden, weil es Architektur-Ebene Refactoring fordert ... "Sie werden mich töten" .... Und ich werde versuchen, Ihre CustomTrigger Idee Es scheint als würde es funktionieren ... –

5

Als Abhilfe würde ich für alle Termine

0 10 10 * * ? 

und überprüft das aktuelle Datum in der geplanten Methode

public void scheduledTask() { 
    Calendar c = Calendar.getInstance(); 
    if (c.get(Calendar.DATE) == c.getActualMaximum(Calendar.DATE)) { 
     ... 
    } 
} 
+2

Es würde funktionieren, aber ich würde nur die Methode für die möglichen letzten Tage des Monats planen, etwas wie Tag 27-31. – Magnilex

+0

Ja, ich denke, es wäre eine Optimierung –

+0

Danke ... Aber es funktioniert nur für den letzten Tag des Monats. –

2

optimierte Version, die erst am letzten Tag eines Monats läuft:

@Scheduled(cron = "0 55 23 28-31 * ?") 
public void doStuffOnLastDayOfMonth() { 
    final Calendar c = Calendar.getInstance(); 
    if (c.get(Calendar.DATE) == c.getActualMaximum(Calendar.DATE)) { 
     // do your stuff 
    } 
} 
Verwandte Themen