HomeDocumentation > Reference > Samples > Java EE sample applications > ejbtimer-javaee6 - A simple EJB timer service application
{scrollbar}

Application Overview

This sample demonstrates a calender based timer service that triggers certain callbacks to enterprise beans at a specified time or interval programmatically. The cron-style timer service is managed by the EJB container and can be created using @Schedule annotation.

Also this sample introduces the annotation way to define servlets, stateless session beans and Persistence Context.

Application Content

ejbtimer-javaee6 application consists of following list of packages and classes.

org.apache.geronimo.samples.javaee6.ejbtimer

  • ShowLog.java displays the detailed activities of all created timer.
  • ScheduleTask.java is a stateless session bean which creates timers automatically.
  • logFacade.java is a stateless session bean which retrieves the detailed activities of all timers.
  • Log.java is a persistent unit to preserve each timers' activity.

The list of web application files in the application is depicted in the following.

+-WEB-INF

|_ web.xml

|_ geronimo-web.xml

+- Resources

|_ persistence.xml

|_ index.html

|_ header.html

|_ intro.html

Application Implementation

geronimo-web.xml specifies the module's information and the url for the web application

Information about the project sucha as module's unique identification, dependencies is described inside the <sys:environment/> tags. It is a good practise to give a module an unique identification, so that it can later be referenced by some other deployable application. This module is in the group org.apache.geronimo.samples. The path specified in the <context-root> tag will be the entry point of this web application. Therefore you can access this web application at http://<hostname>:<port>/ejbtimer-javaee6.

xmlgeronimo-web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1" xmlns:naming="http://geronimo.apache.org/xml/ns/naming-1.2" xmlns:sec="http://geronimo.apache.org/xml/ns/security-2.0" xmlns:sys="http://geronimo.apache.org/xml/ns/deployment-1.2"> <sys:environment> <sys:moduleId> <sys:groupId>org.apache.geronimo.samples</sys:groupId> <sys:artifactId>cviewer-javaee6</sys:artifactId> <sys:version>${version}</sys:version> <sys:type>car</sys:type> </sys:moduleId> <sys:dependencies/> <sys:hidden-classes/> <sys:non-overridable-classes/> </sys:environment> <context-root>/ejbtimer-javaee6</context-root> </web-app>

ShowLog.java is a servlet component which is annotated with @WebServlet and defines the url pattern using urlPatterns attribute. And a business interface of the session bean logFacade is injected using @ejb annotation so that the servlet could invoke count() and findAll() methods from logFacade.

  • @WebServlet
    The WebServlet annotation is used to annotate a servlet to respond to certain requests on a particular web url in the application. A class annotated with @WebServlet extends the class javax.servlet.http.ServletContextListener and must have the urlPatterns or value attribute specified.
javaShowLog.java @WebServlet(name = "showLog", urlPatterns = { "/showLog" }) public class showLog extends HttpServlet { @EJB private logFacade facade; protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); try { out.println("<html>"); out.println("<head>"); out.println("<title>Servlet showLog</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>Currently,there are " + facade.count() + " log records.</h1>"); List<Log> logList = facade.findAll(); out.println("<table border=1>"); out.println("<tr><th>Log ID</th><th>Event Time</th><th>Event</th></tr>"); for (Log log : logList) { out.println("<tr><td>" + log.getId() + "</td><td>" + log.getCreateTime() + "</td><td>" + log.getEvent() + "</td></tr>"); } out.println("</table>"); out.println("</body>"); out.println("</html>"); } finally { out.close(); } }

scheduleTask is a stateless session bean with multiple methods annotated with @Schedule annotations. Each method will be invoked according to the attributes specified to @Schedule. Also, there are two specified methods logIntoDB(String event) and clearLogs() to perform actions on an entity EJBTimerPU injected with @PersistenceContext annotation.

xmlscheduleTask.java @Stateless public class scheduleTask { @PersistenceContext(unitName = "EJBTimerPU") private EntityManager em; @Schedule(minute = "*/3",hour = "*") public void beginNew() { clearLogs(); logIntoDB("Begin new logs in the next 3 minutes."); } @Schedule(second = "*/7", minute = "*", hour = "*") public void test_automatic_timer() { logIntoDB("Every 7 seconds,backup the system"); } // wake you up everyMorning at 7:50 from Monday to Friday @Schedule(minute = "50", hour = "7", dayOfWeek = "Mon,Tue,Wed,Thu,Fri") public void wakeup() { logIntoDB("wake you up@7:50"); } @Schedule(minute = "*/2", hour = "*") public void backup() { logIntoDB("Send a mail every two minites"); } @Schedule(second = "*/15", minute = "*", hour = "*") public void attack() { logIntoDB("Try to connect or attack a website every 15 seconds"); } @Schedule(hour = "14", dayOfMonth = "last") public void cleanup() { logIntoDB("clean up all the dirty info in DB at 2:00pm of the end of month"); } @Schedule(hour = "15/1", dayOfWeek = "Sat,Sun") public void nofifyFifteen() { logIntoDB("On Sat and Sunday,from 3:00 pm, you will get notified every hour "); } // Fool friends at each April 1st. @Schedule(dayOfMonth = "1", month = "Apr") public void foolFriends() { logIntoDB("Today is fool's day.All your friends will get this information"); } public void logIntoDB(String event) { Date dt = new Date(); DateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); String nowTime = df.format(dt); Log log = new Log(); log.setCreateTime(nowTime); log.setEvent(event); System.out.println("event"); em.persist(log); } public void clearLogs() { Query query = em.createQuery("select l from Log l"); List result = query.getResultList(); Iterator<Log> iterator = result.iterator(); while (iterator.hasNext()) { Log log = iterator.next(); em.remove(log); } em.flush(); logIntoDB("Logs of the last 3 minutes have been cleared."); } }

logFacade is a stateless session bean to define another two actions on an entity EJBTimerPU, where both methods are invoked from the servlet component ShowLog.

javalogFacade.java @Stateless public class logFacade { @PersistenceContext(unitName = "EJBTimerPU") private EntityManager em; public List<Log> findAll() { CriteriaQuery cq = em.getCriteriaBuilder().createQuery(); cq.select(cq.from(Log.class)); return em.createQuery(cq).getResultList(); } public int count() { CriteriaQuery cq = em.getCriteriaBuilder().createQuery(); Root<Log> rt = cq.from(Log.class); cq.select(em.getCriteriaBuilder().count(rt)); Query q = em.createQuery(cq); return ((Long) q.getSingleResult()).intValue(); } }

persistence.xml is the configuration file to define a persistence unit named EJBTimerPU, which represents a table named OPENJPASEQ in a derby database ejbtimerdb.

xmlpersistence.xml <?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="EJBTimerPU" transaction-type="JTA"> <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider> <class>org.apache.geronimo.samples.javaee6.ejbtimer.entity.Log</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> <property name="openjpa.jdbc.DBDictionary " value="derby"/> <property name="openjpa.ConnectionURL" value="jdbc:derby://localhost:1527/ejbtimerdb"/> <property name="openjpa.ConnectionDriverName" value="org.apache.derby.jdbc.ClientDriver"/> <property name="openjpa.ConnectionUserName" value="app"/> <property name="openjpa.ConnectionPassword" value="app"/> <property name="openjpa.Sequence" value="table(Table=OPENJPASEQ, Increment=1)"/> <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/> <property name="openjpa.Log" value="DefaultLevel=WARN, Tool=INFO"/> </properties> </persistence-unit> </persistence>

Log.java is an entity bean representing a primary key class of the database table. A primary key class must implement the hashCode() and equals(Object object) methods.

javaLog.java @Entity public class Log implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; String createTime; String event; public String getCreateTime() { return createTime; } public void setCreateTime(String createTime) { this.createTime = createTime; } public String getEvent() { return event; } public void setEvent(String event) { this.event = event; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Override public int hashCode() { int hash = 0; hash += (id != null ? id.hashCode() : 0); return hash; } @Override public boolean equals(Object object) { // TODO: Warning - this method won't work in the case the id fields are // not set if (!(object instanceof Log)) { return false; } Log other = (Log) object; if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) { return false; } return true; } @Override public String toString() { return "com.test.entity.Log[id=" + id + "]"; } }

Get the source code

Please reference Samples General Information for information on obtaining and building the source for this and other samples.

Build the web application

Once all the sources get checked out the next step is to build ejbtimer-javaee6. It requires Maven 2 for building the binaries.

From the <ejbtimer-javaee6_home> directory run the following command.

mvn clean install

This process will take a couple of minutes. The binaries will be generated in the corresponding target directory .

Deploy the web application

Deploying sample application is pretty straight forward as we are going to use the Geronimo Console.

  1. Scroll down to Deploy New from the Console Navigation panel.
  2. Load ejbtimer-javaee6-war-3.0-SNAPSHOT.war from ejbtimer-javaee6-war/target folder in to the Archive input box.
  3. Press Install button to deploy application in the server.

Test the web application

The app is visible at http://localhost:8080/ejbtimer-javaee6/

This page is about what kind of timers defined in the sample application and for each task, an log entry is created.

Click Check the log list, you will see all log info with specific time and event details.