Planning in Jakarta EE

1. Overzicht

In een vorig artikel hebben we laten zien hoe je taken in Spring kunt plannen met@Verwachtannotatie. In dit artikel laten we zien hoe u hetzelfde kunt bereiken door te gebruiken de timerdienst in een Jakarta EE-applicatie voor elk geval gepresenteerd in het vorige artikel.

2. Schakel ondersteuning voor planning in

In een Jakarta EE-applicatie is het niet nodig om ondersteuning voor getimede taken in te schakelen. De timerservice is een door containers beheerde service waarmee toepassingen methoden kunnen aanroepen die zijn gepland voor op tijd gebaseerde gebeurtenissen. Een toepassing kan bijvoorbeeld op een bepaald uur enkele dagelijkse rapporten uitvoeren om statistieken te genereren.

Er zijn twee soorten timers:

  • Programmatische timers: de timerservice kan in elke bean worden geïnjecteerd (behalve een stateful session-bean) en de bedrijfslogica moet in een methode worden geplaatst die is geannoteerd met @Time-out. De timer kan worden geïnitialiseerd met een methode die is geannoteerd @PostConstruct van de bonen of het kan ook worden geïnitialiseerd door een methode aan te roepen.
  • Automatische timers: de bedrijfslogica wordt geplaatst in elke methode met annotaties @Schema of @Schema's. Deze timers worden geïnitialiseerd zodra de toepassing start.

Laten we dus beginnen met ons eerste voorbeeld.

3. Plan een taak met een vaste vertraging

In het voorjaar doet u dit eenvoudig door de @Scheduled (fixedDelay = 1000) annotatie. In dit geval is de duur tussen het einde van de laatste uitvoering en het begin van de volgende uitvoering vast. De taak wacht altijd totdat de vorige is voltooid.

Precies hetzelfde doen in Jakarta EE is een beetje moeilijker te bereiken omdat er geen vergelijkbaar ingebouwd mechanisme is, maar toch kan een soortgelijk scenario worden geïmplementeerd met een beetje extra codering. Laten we eens kijken hoe dit wordt gedaan:

@Singleton openbare klasse FixedTimerBean {@EJB privé WorkerBean workerBean; @Lock (LockType.READ) @Schedule (second = "* / 5", minuut = "*", hour = "*", persistent = false) openbare leegte atSchedule () gooit InterruptedException {workerBean.doTimerWork (); }} 
@Singleton openbare klasse WorkerBean {privé AtomicBoolean bezet = nieuwe AtomicBoolean (false); @Lock (LockType.READ) public void doTimerWork () gooit InterruptedException {if (! Busy.compareAndSet (false, true)) {return; } probeer {Thread.sleep (20000L); } eindelijk {busy.set (false); }}}

Zoals u kunt zien, is de timer gepland om elke vijf seconden te worden geactiveerd. De methode die in ons geval werd geactiveerd, simuleerde echter een responstijd van 20 seconden per oproep slaap() op de huidige Draad.

Als gevolg hiervan blijft de container bellen doTimerWork () elke vijf seconden, maar de voorwaarde aan het begin van de methode, busy.compareAndSet (false, true), keert onmiddellijk terug als het vorige gesprek niet is beëindigd. Hierbij zorgen we ervoor dat de volgende taak pas wordt uitgevoerd nadat de vorige is voltooid.

4. Plan een taak tegen een vast tarief

Een manier om dit te doen is om de timerservice te gebruiken die wordt geïnjecteerd door gebruik te maken van @Resource en geconfigureerd in de geannoteerde methode @PostConstruct. De methode geannoteerd met @Time-out wordt gebeld wanneer de timer afloopt.

Zoals vermeld in het vorige artikel, wacht het begin van de taakuitvoering niet op de voltooiing van de vorige uitvoering. Deze optie moet worden gebruikt wanneer elke uitvoering van de taak onafhankelijk is. Het volgende codefragment maakt een timer die elke seconde wordt geactiveerd:

@Startup @Singleton openbare klasse ProgrammaticAtFixedRateTimerBean {@Inject Event-gebeurtenis; @Resource TimerService timerService; @PostConstruct public void initialize () {timerService.createTimer (0,1000, "Elke seconde timer zonder vertraging"); } @Timeout public void programmaticTimout (Timer timer) {event.fire (nieuwe TimerEvent (timer.getInfo (). ToString ())); }}

Een andere manier is om te gebruiken @Verwacht annotatie. In het volgende codefragment activeren we elke vijf seconden een timer:

@Startup @Singleton openbare klasse ScheduleTimerBean {@Inject Event-gebeurtenis; @Schedule (hour = "*", minute = "*", second = "* / 5", info = "Elke 5 seconden timer") openbare leegte automatisch Gepland (Timer timer) {fireEvent (timer); } private void fireEvent (Timer timer) {event.fire (nieuwe TimerEvent (timer.getInfo (). toString ())); }}

5. Plan een taak met aanvankelijke vertraging

Als uw use case-scenario vereist dat de timer met een vertraging start, kunnen we dat ook doen. In dit geval staat Jakarta EE het gebruik van de timerservice toe. Laten we eens kijken naar een voorbeeld waarbij de timer een initiële vertraging van 10 seconden heeft en vervolgens elke vijf seconden wordt geactiveerd:

@Startup @Singleton openbare klasse ProgrammaticWithInitialFixedDelayTimerBean {@Inject Event-gebeurtenis; @Resource TimerService timerService; @PostConstruct public void initialize () {timerService.createTimer (10000, 5000, "Vertraging 10 seconden en daarna elke 5 seconden timer"); } @Timeout public void programmaticTimout (Timer timer) {event.fire (nieuwe TimerEvent (timer.getInfo (). ToString ())); }}

De createTimer methode die in onze steekproef wordt gebruikt, is het gebruik van de volgende handtekening createTimer (long initialDuration, long intervalDuration, java.io.Serializable info) waar initialDuration is het aantal milliseconden dat moet verstrijken voordat de eerste timer-afloopmelding en interval Duur is het aantal milliseconden dat moet verstrijken tussen meldingen over het verlopen van de timer.

In dit voorbeeld gebruiken we een initialDuration van 10 seconden en een interval Duur van vijf seconden. De taak wordt voor de eerste keer uitgevoerd na de initialDuration waarde en het zal verder worden uitgevoerd volgens de interval Duur.

6. Plan een taak met behulp van cron-expressies

Alle schedulers die we hebben gezien, zowel programmatisch als automatisch, maken het gebruik van cron-expressies mogelijk. Laten we een voorbeeld bekijken:

@Schedules ({@Schedule (dayOfMonth = "Last"), @Schedule (dayOfWeek = "Fri", hour = "23")}) public void doPeriodicCleanup () {...}

In dit voorbeeld is de method doPeriodicCleanup () wordt elke vrijdag om 23.00 uur en op de laatste dag van de maand gebeld.

7. Conclusie

In dit artikel hebben we verschillende manieren bekeken om dit te doen taken plannen in de Jakarta EE-omgeving met als uitgangspunt een vorig artikel waar samples werden gedaan met Spring.

Codevoorbeelden zijn te vinden in de GitHub-opslagplaats.