In this post….
- Whirlwind tour of EJB timers
- Working with EJB timers on the fly via simple REST interface with a sample implementation
——————————- Update (14 July 2015) ————————-
The front end for the application is now available on OpenShift. Since I am a front end novice, I assembled this HTML5 + AngularJS app with help from other sources 😉 So it might feel a little clunky. Please bear with me while I try and improve upon this!
From the UI, you can
- look at all the active timers
- create a timer
- cancel a timer
——————————- Update (14 July 2015) ————————-
The EJB @Schedule annotation comes in handy in case you need to create timers automatically. One can use cron-like expression to configure the appropriate schedule. If you need more flexibility, the good old TimerService works like a charm.
Quick background
- The TimerService interface was Introduced in EJB 2.1 [yeah .. J2EE days ! 😉 ]
- Used to create Timer objects programmatically
- Used to work in conjunction with an implementation of the TimedObject interface [pre EJB 3.0] to serve as a call back for timer triggers
- Since EJB 3.0, the @Timeout annotation was used to mark a method in a (stateless/singleton/message driven) bean to act as the receiver of timer call backs from the EBJ container
- Things were further improved in EJB 3.1 with the introduction of ScheduleExpression which allowed fine grained timer scheduling – this was the programmatic equivalent of @Schedule
EJB Timer related components (for quick reference)
RESTful Timers
One can easily expose a simple RESTful interface to work with EJB Timers. Actions such as creating timers, fetching timer details as well cancelling timers can be executed on the fly.
A simple implementation is available via this Github project. It’s a simple Java EE 7 Maven project built on Netbeans. You should be able to set it up easily.
Here is a gist
- POST a request to schedule a timer (JSON/XML payload representing the schedule configuration)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@POST | |
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) | |
public Response schedule(@HeaderParam("name") final String timerName, final ScheduleConfiguration config) { | |
auditScheduler.schedule(from(config), new TimerConfig(timerName, config.isPersistent())); | |
return Response.created(UriBuilder.fromResource(AuditSchedulerResource.class).path(timerName).build(timerName)).build(); | |
} |
- GET all active timers and their respective details (JSON/XML representation)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@GET | |
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) | |
public Response getAllTimers() { | |
List<String> ejbTimers = auditScheduler.getAllTimers(); | |
List<ScheduledTimerInfo> timers = ejbTimers.stream().map((id) -> auditScheduler.getTimerInfo(id)).collect(Collectors.toList()); | |
GenericEntity<List<ScheduledTimerInfo>> entities = new GenericEntity<List<ScheduledTimerInfo>>(timers) {}; | |
return Response.ok(entities).build(); | |
} |
- GET information for a specific timer (JSON/XML representation)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@GET | |
@Path("{id}") | |
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) | |
public Response getTimerInfo(@PathParam("id") String name) { | |
ScheduledTimerInfo info = auditScheduler.getTimerInfo(name); | |
return Response.ok(info).build(); | |
} |
- DELETE (cancel) an existing timer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@DELETE | |
@Path("{id}") | |
public void cancel(@PathParam("id") String name) { | |
auditScheduler.cancel(name); | |
} |
- Use JAXB annotated POJOs to represent scheduler configuration and details
- Leverage default JSON support in Java EE 7
The WADL should tell the story
Cheers!