You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@click.apache.org by me...@apache.org on 2009/05/13 15:45:16 UTC
svn commit: r774364 - in /incubator/click/trunk/click: ./
documentation/docs/ examples/ examples/src/
examples/src/org/apache/click/examples/page/quartz/
examples/src/org/apache/click/examples/quartz/
examples/src/org/apache/click/examples/util/ exampl...
Author: medgar
Date: Wed May 13 13:45:15 2009
New Revision: 774364
URL: http://svn.apache.org/viewvc?rev=774364&view=rev
Log:
added Quartz scheduler integration example
Added:
incubator/click/trunk/click/examples/src/org/apache/click/examples/page/quartz/
incubator/click/trunk/click/examples/src/org/apache/click/examples/page/quartz/QuartzJobAndTriggerPage.java
incubator/click/trunk/click/examples/src/org/apache/click/examples/page/quartz/QuartzJobSchedulerPage.java
incubator/click/trunk/click/examples/src/org/apache/click/examples/page/quartz/package.html
incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/
incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/ExampleJob.java
incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/JobAndSimpleTrigger.java
incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/SchedulerService.java
incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/package.html
incubator/click/trunk/click/examples/src/org/apache/click/examples/util/DatabaseInitListener.java
- copied, changed from r769101, incubator/click/trunk/click/examples/src/org/apache/click/examples/util/DatabaseInitFilter.java
incubator/click/trunk/click/examples/src/quartz.properties
incubator/click/trunk/click/examples/webapp/quartz/
incubator/click/trunk/click/examples/webapp/quartz/quartz-job-and-trigger.htm
incubator/click/trunk/click/examples/webapp/quartz/quartz-job-scheduler.htm
Removed:
incubator/click/trunk/click/examples/src/org/apache/click/examples/util/DatabaseInitFilter.java
Modified:
incubator/click/trunk/click/.classpath
incubator/click/trunk/click/documentation/docs/roadmap-changes.html
incubator/click/trunk/click/examples/build.xml
incubator/click/trunk/click/examples/src/click-page.properties
incubator/click/trunk/click/examples/webapp/WEB-INF/lib/ (props changed)
incubator/click/trunk/click/examples/webapp/WEB-INF/menu.xml
incubator/click/trunk/click/examples/webapp/WEB-INF/web.xml
Modified: incubator/click/trunk/click/.classpath
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/.classpath?rev=774364&r1=774363&r2=774364&view=diff
==============================================================================
--- incubator/click/trunk/click/.classpath (original)
+++ incubator/click/trunk/click/.classpath Wed May 13 13:45:15 2009
@@ -31,5 +31,6 @@
<classpathentry kind="lib" path="lib/velocity-1.6.2.jar"/>
<classpathentry kind="lib" path="examples/webapp/WEB-INF/lib/geronimo-annotation_1.0_spec-1.1.1.jar"/>
<classpathentry kind="lib" path="examples/webapp/WEB-INF/lib/acegi-security-1.0.7.jar"/>
+ <classpathentry kind="lib" path="examples/webapp/WEB-INF/lib/quartz-all-1.6.3.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
Modified: incubator/click/trunk/click/documentation/docs/roadmap-changes.html
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/documentation/docs/roadmap-changes.html?rev=774364&r1=774363&r2=774364&view=diff
==============================================================================
--- incubator/click/trunk/click/documentation/docs/roadmap-changes.html (original)
+++ incubator/click/trunk/click/documentation/docs/roadmap-changes.html Wed May 13 13:45:15 2009
@@ -117,6 +117,10 @@
Reusable Panel</a> is an example of a reusable Panel
which provides a Form for capturing Client details.
</li>
+ <a target="_blank" class="external" href="http://www.avoka.com/click-examples/quartz/quartz-job-scheduler.htm">
+ Quartz Job Scheduler</a> is an example demonstrating how to integrate the Quartz Job Scheduling framework
+ into a Click application.
+ </li>
</ul>
<div style="margin-left: -2em; margin-top: 1.5em; margin-bottom: 1em;">
Modified: incubator/click/trunk/click/examples/build.xml
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/build.xml?rev=774364&r1=774363&r2=774364&view=diff
==============================================================================
--- incubator/click/trunk/click/examples/build.xml (original)
+++ incubator/click/trunk/click/examples/build.xml Wed May 13 13:45:15 2009
@@ -37,6 +37,7 @@
<property name="jar.log4j" value="log4j-1.2.14.jar"/>
<property name="jar.logging" value="commons-logging-1.0.4.jar"/>
<property name="jar.poi" value="poi-3.0-FINAL.jar"/>
+ <property name="jar.quartz" value="quartz-all-1.6.3.jar"/>
<property name="jar.oro" value="oro-2.0.8.jar"/>
<property name="jar.servlet" value="servlet-api-2.3.jar"/>
<property name="jar.spring" value="spring-2.5.6.jar"/>
@@ -171,6 +172,10 @@
dest="${dir.weblib}/${jar.annotation}"
verbose="true"
usetimestamp="true"/>
+ <get src="http://mirrors.ibiblio.org/pub/mirrors/maven2/opensymphony/quartz-all/1.6.3/${jar.quartz}"
+ dest="${dir.weblib}/${jar.quartz}"
+ verbose="true"
+ usetimestamp="true"/>
</target>
Modified: incubator/click/trunk/click/examples/src/click-page.properties
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/src/click-page.properties?rev=774364&r1=774363&r2=774364&view=diff
==============================================================================
--- incubator/click/trunk/click/examples/src/click-page.properties (original)
+++ incubator/click/trunk/click/examples/src/click-page.properties Wed May 13 13:45:15 2009
@@ -17,6 +17,10 @@
version=2.1.0
+deleteConfirm=Are you sure you want to remove this {0}?
+
invalid.form.submit=You have made an invalid form submission.
+jobSchedulerNotAvailableMsg=The job scheduler is not available
+
usernameExistsError=Username already exists, please select another account username
\ No newline at end of file
Added: incubator/click/trunk/click/examples/src/org/apache/click/examples/page/quartz/QuartzJobAndTriggerPage.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/src/org/apache/click/examples/page/quartz/QuartzJobAndTriggerPage.java?rev=774364&view=auto
==============================================================================
--- incubator/click/trunk/click/examples/src/org/apache/click/examples/page/quartz/QuartzJobAndTriggerPage.java (added)
+++ incubator/click/trunk/click/examples/src/org/apache/click/examples/page/quartz/QuartzJobAndTriggerPage.java Wed May 13 13:45:15 2009
@@ -0,0 +1,220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.click.examples.page.quartz;
+
+import javax.servlet.ServletContext;
+
+import org.apache.click.ActionListener;
+import org.apache.click.Control;
+import org.apache.click.control.FieldSet;
+import org.apache.click.control.Form;
+import org.apache.click.control.Option;
+import org.apache.click.control.Select;
+import org.apache.click.control.Submit;
+import org.apache.click.control.TextField;
+import org.apache.click.examples.page.BorderPage;
+import org.apache.click.examples.quartz.JobAndSimpleTrigger;
+import org.apache.click.examples.quartz.SchedulerService;
+import org.apache.click.extras.control.DateField;
+import org.quartz.JobDetail;
+import org.quartz.ee.servlet.QuartzInitializerListener;
+import org.quartz.impl.StdSchedulerFactory;
+
+/**
+ * Provides a Quartz Job and Simple Trigger edit page.
+ *
+ * @author Malcolm Edgar
+ */
+public class QuartzJobAndTriggerPage extends BorderPage {
+
+ private Form form = new Form("form");
+ private TextField nameField = new TextField("name", true);
+ private TextField classnameField = new TextField("classname", true);
+ private TextField descriptionField = new TextField("description");
+ private DateField startDateField = new DateField("startDate", true);
+ private DateField endDateField = new DateField("endDate");
+ private Select repeatCountField = new Select("repeatCount", "Repeat");
+ private Select repeatIntervalField = new Select("repeatInterval");
+
+ private SchedulerService schedulerService;
+
+ public QuartzJobAndTriggerPage() {
+
+ // Form
+ addControl(form);
+ form.setDefaultFieldSize(80);
+
+ FieldSet fieldSet = new FieldSet("Job and Trigger");
+ form.add(fieldSet);
+
+ nameField.setMaxLength(80);
+ fieldSet.add(nameField);
+
+ fieldSet.add(classnameField);
+
+ descriptionField.setMaxLength(120);
+ fieldSet.add(descriptionField);
+
+ fieldSet.add(startDateField);
+
+ fieldSet.add(endDateField);
+
+ repeatCountField.add(new Option("-1", "Run continuously"));
+ repeatCountField.add(new Option("0", "Run once"));
+ repeatCountField.add(new Option("1", "Repeat 1"));
+ repeatCountField.add(new Option("2", "Repeat 2"));
+ repeatCountField.add(new Option("3", "Repeat 3"));
+ repeatCountField.add(new Option("4", "Repeat 4"));
+ repeatCountField.add(new Option("5", "Repeat 5"));
+ repeatCountField.add(new Option("10", "Repeat 10"));
+ repeatCountField.add(new Option("20", "Repeat 20"));
+ repeatCountField.setValue("-1");
+ fieldSet.add(repeatCountField);
+
+ repeatIntervalField.add(new Option("60000", "1 minute"));
+ repeatIntervalField.add(new Option("120000", "2 minutes"));
+ repeatIntervalField.add(new Option("300000", "5 minutes"));
+ repeatIntervalField.add(new Option("600000", "10 minutes"));
+ repeatIntervalField.add(new Option("900000", "15 minutes"));
+ repeatIntervalField.add(new Option("1800000", "30 minutes"));
+ repeatIntervalField.add(new Option("3600000", "1 hour"));
+ repeatIntervalField.add(new Option("7200000", "2 hours"));
+ repeatIntervalField.add(new Option("10800000", "3 hours"));
+ repeatIntervalField.add(new Option("21600000", "6 hours"));
+ repeatIntervalField.add(new Option("43200000", "12 hours"));
+ repeatIntervalField.add(new Option("86400000", "24 hours"));
+ repeatIntervalField.setValue("3600000");
+ fieldSet.add(repeatIntervalField);
+
+ Submit saveSubmit = new Submit("Save");
+ saveSubmit.setActionListener(new ActionListener(){
+ public boolean onAction(Control source) {
+ return onSaveClick();
+ }
+ });
+ form.add(saveSubmit);
+
+ Submit cancelSubmit = new Submit("Cancel");
+ cancelSubmit.setActionListener(new ActionListener(){
+ public boolean onAction(Control source) {
+ setRedirect(QuartzJobSchedulerPage.class);
+ return false;
+ }
+ });
+ form.add(cancelSubmit);
+ }
+
+ // Event Handlers ---------------------------------------------------------
+
+ @Override
+ public void onInit() {
+ super.onInit();
+
+ if (getSchedulerService() != null) {
+ String name = getContext().getRequestParameter("job.name");
+ if (name != null) {
+ JobAndSimpleTrigger jat = getSchedulerService().getJobAndTrigger(name);
+
+ if (jat != null) {
+ nameField.setReadonly(true);
+ nameField.setAttribute("class", "readonly");
+ form.copyFrom(jat.getJob());
+ classnameField.setValue(jat.getJob().getJobClass().getName());
+ startDateField.setDate(jat.getTrigger().getStartTime());
+ endDateField.setDate(jat.getTrigger().getEndTime());
+ repeatCountField.setValue("" + jat.getTrigger().getRepeatCount());
+ repeatIntervalField.setValue("" + jat.getTrigger().getRepeatInterval());
+ }
+ }
+
+ } else {
+ setFlashMessage(getMessage("jobSchedulerNotAvailableMsg"));
+ form.setDisabled(true);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public boolean onSaveClick() {
+ if (form.isValid()) {
+ String name = nameField.getValue();
+
+ Class jobClass = null;
+ try {
+ jobClass = Class.forName(classnameField.getValue());
+ } catch (Exception e) {
+ classnameField.setError("Could not find class for classname");
+ return true;
+ }
+
+ if (getSchedulerService().getJobDetail(name) != null) {
+ getSchedulerService().deleteJob(name);
+ }
+
+ JobDetail jobDetail = new JobDetail();
+ form.copyTo(jobDetail);
+ jobDetail.setJobClass(jobClass);
+
+ long intervalMs = Long.parseLong(repeatIntervalField.getValue());
+
+ getSchedulerService().scheduleJob(jobDetail,
+ startDateField.getDate(),
+ endDateField.getDate(),
+ Integer.parseInt(repeatCountField.getValue()),
+ intervalMs);
+
+ setFlashMessage("Saved job '" + jobDetail.getName() + "'");
+
+ setRedirect(QuartzJobSchedulerPage.class);
+ return false;
+ }
+ return true;
+ }
+
+ // Protected Methods ------------------------------------------------------
+
+ /**
+ * Set a flash attribute message with the given message string.
+ *
+ * @param message the flash attribute message to display
+ */
+ protected void setFlashMessage(String message) {
+ getContext().setFlashAttribute("flash", message);
+ }
+
+ /**
+ * Return the scheduler service.
+ *
+ * @return the scheduler service
+ */
+ protected SchedulerService getSchedulerService() {
+ if (schedulerService == null) {
+ ServletContext servletContext = getContext().getServletContext();
+
+ StdSchedulerFactory schedulerFactory = (StdSchedulerFactory)
+ servletContext.getAttribute(QuartzInitializerListener.QUARTZ_FACTORY_KEY);
+
+ if (schedulerFactory != null) {
+ schedulerService = new SchedulerService(schedulerFactory);
+ }
+ }
+
+ return schedulerService;
+ }
+
+}
Added: incubator/click/trunk/click/examples/src/org/apache/click/examples/page/quartz/QuartzJobSchedulerPage.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/src/org/apache/click/examples/page/quartz/QuartzJobSchedulerPage.java?rev=774364&view=auto
==============================================================================
--- incubator/click/trunk/click/examples/src/org/apache/click/examples/page/quartz/QuartzJobSchedulerPage.java (added)
+++ incubator/click/trunk/click/examples/src/org/apache/click/examples/page/quartz/QuartzJobSchedulerPage.java Wed May 13 13:45:15 2009
@@ -0,0 +1,310 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.click.examples.page.quartz;
+
+import java.util.Collections;
+import java.util.List;
+
+import javax.servlet.ServletContext;
+
+import org.apache.cayenne.query.Ordering;
+import org.apache.click.ActionListener;
+import org.apache.click.Context;
+import org.apache.click.Control;
+import org.apache.click.control.ActionButton;
+import org.apache.click.control.ActionLink;
+import org.apache.click.control.Column;
+import org.apache.click.control.Decorator;
+import org.apache.click.control.PageLink;
+import org.apache.click.control.Table;
+import org.apache.click.examples.page.BorderPage;
+import org.apache.click.examples.quartz.JobAndSimpleTrigger;
+import org.apache.click.examples.quartz.SchedulerService;
+import org.apache.click.util.HtmlStringBuffer;
+import org.quartz.Trigger;
+import org.quartz.ee.servlet.QuartzInitializerListener;
+import org.quartz.impl.StdSchedulerFactory;
+
+/**
+ * Provides a Quartz Job Schedule search page.
+ *
+ * @author Malcolm Edgar
+ */
+public class QuartzJobSchedulerPage extends BorderPage {
+
+ private static final String DATE_FORMAT = "{0,date,hh:mm a d MMM yy }";
+
+ /** The auto bound refresh button. */
+ public ActionButton refresh = new ActionButton("refresh");
+
+ // Private Variables ------------------------------------------------------
+
+ private Table table = new Table("table");
+ private PageLink editLink = new PageLink("edit", QuartzJobAndTriggerPage.class);
+ private ActionLink pauseLink = new ActionLink("pause");
+ private ActionLink resumeLink = new ActionLink("resume");
+ private ActionLink triggerLink = new ActionLink("trigger");
+ private ActionLink interruptLink = new ActionLink("interrupt");
+ private ActionLink deleteLink = new ActionLink("delete");
+ private ActionButton newJob = new ActionButton("newJob");
+
+ private SchedulerService schedulerService;
+
+ // Constructor ------------------------------------------------------------
+
+ public QuartzJobSchedulerPage() {
+
+ // Table
+ addControl(table);
+ table.setAttribute("class", Table.CLASS_SIMPLE);
+ table.setSortable(true);
+ table.setStyle("margin-left", "0.25em;");
+
+ // Define columns
+
+ Column column = new Column("job.name", "Job Name");
+ column.setTitleProperty("job.description");
+ table.addColumn(column);
+
+ final Column statusColumn = new Column("triggerStateAsString", "Status");
+ statusColumn.setEscapeHtml(false);
+ statusColumn.setDecorator(new Decorator() {
+ public String render(Object row, Context context) {
+ JobAndSimpleTrigger jobAndTrigger = (JobAndSimpleTrigger) row;
+ switch(jobAndTrigger.getTriggerState()){
+ case Trigger.STATE_NONE:
+ return "<span style='color:red'>None</span>";
+ case Trigger.STATE_NORMAL:
+ return "<span style='color:blue'>Normal</span>";
+ case Trigger.STATE_PAUSED:
+ return "<span style='color:red'>Paused</span>";
+ case Trigger.STATE_BLOCKED:
+ return "<span style='color:green'>Running</span>";
+ case Trigger.STATE_COMPLETE:
+ return "<span style='color:black'>Complete</span>";
+ case Trigger.STATE_ERROR:
+ return "<span style='color:red'>Error</span>";
+ }
+ return "Unknown";
+ }
+ });
+ table.addColumn(statusColumn);
+
+ table.addColumn(new Column("interval"));
+
+ column = new Column("trigger.nextFireTime", "Next Run");
+ column.setFormat(DATE_FORMAT);
+ table.addColumn(column);
+
+ column = new Column("trigger.startTime", "First Run");
+ column.setFormat(DATE_FORMAT);
+ table.addColumn(column);
+
+ column = new Column("trigger.previousFireTime", "Last Run");
+ column.setFormat(DATE_FORMAT);
+ table.addColumn(column);
+
+ // Initialized action column links
+
+ editLink.setAttribute("class", "actionIcon");
+ editLink.setTitle("Edit Job");
+ addControl(editLink);
+
+ pauseLink.setAttribute("class", "actionIcon");
+ pauseLink.setTitle("Pause Job");
+ pauseLink.setActionListener(new ActionListener(){
+ public boolean onAction(Control source) {
+ String name = pauseLink.getValue();
+ getSchedulerService().pauseJob(name);
+ setFlashMessage("Paused job '" + name + "'");
+ return true;
+ }
+ });
+ addControl(pauseLink);
+
+ interruptLink.setAttribute("class", "actionIcon");
+ interruptLink.setTitle("Interrupt Running Job");
+ interruptLink.setActionListener(new ActionListener(){
+ public boolean onAction(Control source) {
+ String name = interruptLink.getValue();
+ if (getSchedulerService().interuptJob(name)) {
+ setFlashMessage("Interrupted job '" + name + "'");
+ } else {
+ setFlashMessage("Could not interrupt job '" + name + "'");
+ }
+ return true;
+ }
+ });
+ addControl(interruptLink);
+
+ triggerLink.setAttribute("class", "actionIcon");
+ triggerLink.setTitle("Trigger Job");
+ triggerLink.setActionListener(new ActionListener(){
+ public boolean onAction(Control source) {
+ String name = triggerLink.getValue();
+ getSchedulerService().triggerJob(name);
+ setFlashMessage("Triggered job '" + name + "'");
+ return true;
+ }
+ });
+ addControl(triggerLink);
+
+ resumeLink.setAttribute("class", "actionIcon");
+ resumeLink.setTitle("Resume Job");
+ resumeLink.setActionListener(new ActionListener(){
+ public boolean onAction(Control source) {
+ String name = resumeLink.getValue();
+ getSchedulerService().resumeJob(name);
+ setFlashMessage("Resumed job '" + name + "'");
+ return true;
+ }
+ });
+ addControl(resumeLink);
+
+ deleteLink.setAttribute("class", "actionIcon");
+ deleteLink.setTitle("Delete Job");
+ String confirmMessage = getMessage("deleteConfirm", "Job");
+ deleteLink.setAttribute("onclick", "return window.confirm('" + confirmMessage + "')");
+ deleteLink.setActionListener(new ActionListener(){
+ public boolean onAction(Control source) {
+ String name = deleteLink.getValue();
+ if (getSchedulerService().deleteJob(name)) {
+ setFlashMessage("Deleted job '" + name + "'");
+ } else {
+ setFlashMessage("Could not delete " + name);
+ }
+ return true;
+ }
+ });
+ addControl(deleteLink);
+
+ // Add table action column if user has edit or delete permissions
+ final Column actionColumn = new Column("action");
+
+ // Render action controls based on users permission
+ actionColumn.setDecorator(new Decorator() {
+ public String render(Object object, Context context) {
+ JobAndSimpleTrigger jobAndTrigger = (JobAndSimpleTrigger) object;
+
+ HtmlStringBuffer buffer = new HtmlStringBuffer();
+
+ editLink.setParameter("job.name", jobAndTrigger.getJob().getName());
+ editLink.render(buffer);
+
+ buffer.append(" | ");
+ deleteLink.setValue(jobAndTrigger.getJob().getName());
+ deleteLink.render(buffer);
+
+ if (!getSchedulerService().isPaused()) {
+
+ if (jobAndTrigger.getTriggerState() == Trigger.STATE_PAUSED) {
+ buffer.append(" | ");
+ resumeLink.setValue(jobAndTrigger.getJob().getName());
+ resumeLink.render(buffer);
+
+ } else {
+ buffer.append(" | ");
+ pauseLink.setValue(jobAndTrigger.getJob().getName());
+ pauseLink.render(buffer);
+ }
+
+ buffer.append(" | ");
+ triggerLink.setValue(jobAndTrigger.getJob().getName());
+ triggerLink.render(buffer);
+
+ if (jobAndTrigger.getTriggerState() == Trigger.STATE_BLOCKED) {
+ buffer.append(" | ");
+ interruptLink.setValue(jobAndTrigger.getJob().getName());
+ interruptLink.render(buffer);
+ }
+ }
+
+ return buffer.toString();
+ }
+
+ });
+ actionColumn.setSortable(false);
+ table.addColumn(actionColumn);
+
+ // Add Control Buttons.
+
+ newJob.setActionListener(new ActionListener(){
+ public boolean onAction(Control source) {
+ setRedirect(QuartzJobAndTriggerPage.class);
+ return false;
+ }
+ });
+ addControl(newJob);
+ }
+
+ // Event Handlers ---------------------------------------------------------
+
+ @Override
+ public void onInit() {
+ super.onInit();
+ if (getSchedulerService() == null) {
+ setFlashMessage(getMessage("jobSchedulerNotAvailableMsg"));
+ newJob.setDisabled(true);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void onRender() {
+ super.onRender();
+
+ if (getSchedulerService() != null) {
+ List<JobAndSimpleTrigger> rowList = getSchedulerService().getJobAndTriggerList();
+ Collections.sort(rowList, new Ordering("job.name", Ordering.ASC));
+ table.setRowList(rowList);
+ }
+ }
+
+ // Protected Methods ------------------------------------------------------
+
+ /**
+ * Set a flash attribute message with the given message string.
+ *
+ * @param message the flash attribute message to display
+ */
+ protected void setFlashMessage(String message) {
+ getContext().setFlashAttribute("flash", message);
+ }
+
+ /**
+ * Return the scheduler service.
+ *
+ * @return the scheduler service
+ */
+ protected SchedulerService getSchedulerService() {
+ if (schedulerService == null) {
+ ServletContext servletContext = getContext().getServletContext();
+
+ StdSchedulerFactory schedulerFactory = (StdSchedulerFactory)
+ servletContext.getAttribute(QuartzInitializerListener.QUARTZ_FACTORY_KEY);
+
+ if (schedulerFactory != null) {
+ schedulerService = new SchedulerService(schedulerFactory);
+ }
+ }
+
+ return schedulerService;
+ }
+
+}
Added: incubator/click/trunk/click/examples/src/org/apache/click/examples/page/quartz/package.html
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/src/org/apache/click/examples/page/quartz/package.html?rev=774364&view=auto
==============================================================================
--- incubator/click/trunk/click/examples/src/org/apache/click/examples/page/quartz/package.html (added)
+++ incubator/click/trunk/click/examples/src/org/apache/click/examples/page/quartz/package.html Wed May 13 13:45:15 2009
@@ -0,0 +1,22 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<body>
+Provides the example Quartz scheduler integration page classes.
+</body>
\ No newline at end of file
Added: incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/ExampleJob.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/ExampleJob.java?rev=774364&view=auto
==============================================================================
--- incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/ExampleJob.java (added)
+++ incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/ExampleJob.java Wed May 13 13:45:15 2009
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.click.examples.quartz;
+
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+
+/**
+ * Provides a simple example Quartz Job class which writes 'Hello World' to
+ * System.out and then counts to 10.
+ *
+ * @author Malcolm Edgar
+ */
+public class ExampleJob implements Job {
+
+ /**
+ * {@link org.quartz.Job#execute(JobExecutionContext)
+ */
+ public void execute(JobExecutionContext context) throws JobExecutionException {
+ System.out.println("Hello World from " + getClass().getSimpleName() + "@" + hashCode());
+ System.out.println("I can count to 10.");
+
+ for (int i = 1; i <= 10; i++) {
+ System.out.print(i + " ");
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ie) {
+ }
+ }
+
+ System.out.println("\nSee I did it.");
+ }
+
+}
Added: incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/JobAndSimpleTrigger.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/JobAndSimpleTrigger.java?rev=774364&view=auto
==============================================================================
--- incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/JobAndSimpleTrigger.java (added)
+++ incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/JobAndSimpleTrigger.java Wed May 13 13:45:15 2009
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.click.examples.quartz;
+
+import java.util.Iterator;
+
+import org.quartz.JobDetail;
+import org.quartz.JobExecutionContext;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.quartz.SimpleTrigger;
+import org.quartz.Trigger;
+
+/**
+ * Provides a Quartz Job and Simple Trigger display class.
+ *
+ * @author Malcolm Edgar
+ */
+public class JobAndSimpleTrigger {
+
+ private static final long MS_TO_MINS = 1000L * 60;
+
+ private final JobDetail jobDetail;
+ private final SimpleTrigger trigger;
+ private final Scheduler scheduler;
+
+ public JobAndSimpleTrigger(JobDetail jobDetail, SimpleTrigger trigger, Scheduler scheduler) {
+ this.jobDetail = jobDetail;
+ this.trigger = trigger;
+ this.scheduler = scheduler;
+ }
+
+ public JobDetail getJob() {
+ return jobDetail;
+ }
+
+ public SimpleTrigger getTrigger() {
+ return trigger;
+ }
+
+ public int getTriggerState(){
+ try {
+ return scheduler.getTriggerState(trigger.getName(), trigger.getGroup());
+ } catch(Throwable th) {
+ return Trigger.STATE_NONE;
+ }
+ }
+
+ public String getTriggerStateAsString(){
+ switch(getTriggerState()){
+ case Trigger.STATE_NONE:
+ return "None";
+ case Trigger.STATE_NORMAL:
+ return "Normal";
+ case Trigger.STATE_PAUSED:
+ return "Paused";
+ case Trigger.STATE_BLOCKED:
+ return "Running";
+ case Trigger.STATE_COMPLETE:
+ return "Complete";
+ case Trigger.STATE_ERROR:
+ return "Error";
+ }
+ return "Unknown";
+ }
+
+ public String getRepeat() {
+ long count = trigger.getRepeatCount();
+
+ if (count == -1) {
+ return "Continously";
+
+ } else if (count == 0) {
+ return "Run once";
+
+ } else if (count == 1) {
+ return "Repeat once";
+
+ } else {
+ return "Repeat " + count;
+ }
+ }
+
+ public String getInterval() {
+ long interval = trigger.getRepeatInterval() / MS_TO_MINS;
+
+ if (interval == 1) {
+ return "1 min";
+
+ } else if (interval < 60) {
+ return "" + interval + " mins";
+
+ } else if (interval == 60) {
+ return "1 hour";
+
+ } else {
+ return "" + interval / 60 + " hours";
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public boolean isExecuting() throws SchedulerException {
+ for (Iterator i = scheduler.getCurrentlyExecutingJobs().iterator(); i.hasNext();) {
+ JobExecutionContext context = (JobExecutionContext) i.next();
+ if (context.getJobDetail().getFullName().equals(jobDetail.getFullName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
Added: incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/SchedulerService.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/SchedulerService.java?rev=774364&view=auto
==============================================================================
--- incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/SchedulerService.java (added)
+++ incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/SchedulerService.java Wed May 13 13:45:15 2009
@@ -0,0 +1,357 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.click.examples.quartz;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.click.extras.cayenne.CayenneTemplate;
+import org.apache.commons.lang.Validate;
+import org.quartz.JobDetail;
+import org.quartz.JobExecutionContext;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.quartz.SimpleTrigger;
+import org.quartz.TriggerUtils;
+import org.quartz.impl.StdSchedulerFactory;
+
+/**
+ * Provides a service wrapper class around the Quartz scheduler class.
+ *
+ * @author Malcolm Edgar
+ */
+public class SchedulerService extends CayenneTemplate {
+
+ /** The scheduler group name. */
+ private static final String GROUP_NAME = "click-examples";
+
+ /** The scheduler trigger group name. */
+ private static final String TRIGGER_GROUP_NAME = "click-examples-trigger-group";
+
+ /** The quartz scheduler instance. */
+ private final Scheduler scheduler;
+
+ // Constructor ------------------------------------------------------------
+
+ /**
+ * Create a new scheduler service with the given Quartz Scheduler Factory.
+ *
+ * @param schedulerFactory the Quartz Scheduler Factory
+ */
+ public SchedulerService(StdSchedulerFactory schedulerFactory) {
+ Validate.notNull(schedulerFactory, "Null schedulerFactory param");
+
+ try {
+ scheduler = schedulerFactory.getScheduler();
+
+ } catch (SchedulerException se) {
+ String msg = "Could not obtain Quartz Scheduler instance";
+ throw new RuntimeException(msg);
+ }
+ }
+
+ // Public Methods ---------------------------------------------------------
+
+ /**
+ * Schedule a new quartz job with the given job details, start and end date,
+ * repeat count and repeat interval.
+ *
+ * @param jobDetail the quartz job detail
+ * @param startDate the start date of the job
+ * @param endDate the end date of the job
+ * @param repeatCount the repeat count
+ * @param repeatInterval the job repeat interval in milliseconds
+ */
+ public void scheduleJob(JobDetail jobDetail, Date startDate, Date endDate, int repeatCount, long repeatInterval) {
+ Validate.notNull(jobDetail, "Null jobDetail parameter");
+
+ // get a "nice round" time a few seconds in the future....
+ long ts = TriggerUtils.getNextGivenSecondDate(null, 10).getTime();
+
+ if (startDate == null || startDate.before(new Date())) {
+ startDate = new Date(ts);
+ }
+
+ jobDetail.setGroup(GROUP_NAME);
+
+ SimpleTrigger trigger =
+ new SimpleTrigger(jobDetail.getName(),
+ TRIGGER_GROUP_NAME,
+ jobDetail.getName(),
+ jobDetail.getGroup(),
+ startDate,
+ endDate,
+ repeatCount,
+ repeatInterval);
+
+ try {
+ getScheduler().scheduleJob(jobDetail, trigger);
+
+ } catch (SchedulerException se) {
+ throw new RuntimeException( "Could not obtain schedule job " + jobDetail);
+ }
+ }
+
+ /**
+ * Return true if the scheduler is paused.
+ *
+ * @return true if the scheduler is paused
+ */
+ public boolean isPaused() {
+ try {
+ return getScheduler().isInStandbyMode();
+
+ } catch (SchedulerException se) {
+ throw new RuntimeException( "Could not determine if scheduler is in standby mode");
+ }
+ }
+
+ /**
+ * Pause all the scheduled jobs, and interrupt any currently executing jobs.
+ */
+ @SuppressWarnings("unchecked")
+ public void pauseAll() {
+ try {
+ for (Iterator i = scheduler.getCurrentlyExecutingJobs().iterator(); i.hasNext();) {
+ JobExecutionContext context = (JobExecutionContext) i.next();
+ interuptJob(context.getJobDetail().getName());
+ }
+
+ getScheduler().pauseAll();
+
+ } catch (SchedulerException se) {
+ String msg = "Could not pause all jobs";
+ throw new RuntimeException(msg, se);
+ }
+ }
+
+ /**
+ * Resume all paused jobs.
+ */
+ public void resumeAll() {
+ try {
+ getScheduler().resumeAll();
+
+ } catch (SchedulerException se) {
+ String msg = "Could not resume all jobs";
+ throw new RuntimeException(msg, se);
+ }
+ }
+
+ /**
+ * Pause the job for the given name.
+ *
+ * @param jobName the name of the job to pause
+ */
+ public void pauseJob(String jobName) {
+ try {
+ getScheduler().pauseJob(jobName, GROUP_NAME);
+
+ } catch (SchedulerException se) {
+ String msg = "Could not pause Quartz Scheduler job: " + jobName;
+ throw new RuntimeException(msg, se);
+ }
+ }
+
+ /**
+ * Resume the job for the given name.
+ *
+ * @param jobName the name of the job to resume
+ */
+ public void resumeJob(String jobName) {
+ try {
+ getScheduler().resumeJob(jobName, GROUP_NAME);
+
+ } catch (SchedulerException se) {
+ String msg = "Could not resume Quartz Scheduler job: " + jobName;
+ throw new RuntimeException(msg, se);
+ }
+ }
+
+ /**
+ * Trigger the job for the given name.
+ *
+ * @param jobName the name of the job to trigger
+ */
+ public void triggerJob(String jobName) {
+ try {
+ getScheduler().triggerJob(jobName, GROUP_NAME);
+
+ } catch (SchedulerException se) {
+ String msg = "Could not resume Quartz Scheduler job: " + jobName;
+ throw new RuntimeException(msg, se);
+ }
+ }
+
+ /**
+ * Interupt the job for the given name, return true if the job was found.
+ *
+ * @param jobName the name of the job to interupt
+ */
+ public boolean interuptJob(String jobName) {
+ try {
+ return getScheduler().interrupt(jobName, GROUP_NAME);
+
+ } catch (SchedulerException se) {
+ String msg = "Could not obtain Quartz Scheduler JobDetails";
+ throw new RuntimeException(msg, se);
+ }
+ }
+
+ /**
+ * Delete the job for the given name, return true if the job was found.
+ *
+ * @param jobName the name of the job to delete
+ * @return true if the Job was found and deleted.
+ */
+ public boolean deleteJob(String jobName) {
+ try {
+ return getScheduler().deleteJob(jobName, GROUP_NAME);
+
+ } catch (SchedulerException se) {
+ String msg = "Could not obtain Quartz Scheduler JobDetails";
+ throw new RuntimeException(msg, se);
+ }
+ }
+
+ /**
+ * Return the list of scheduled JobDetails for the group name: "click-group".
+ *
+ * @return the list of scheduled JobDetails for the group name: "click-group"
+ */
+ public List<JobDetail> getJobDetailList() {
+ try {
+ List<JobDetail> list = new ArrayList<JobDetail>();
+
+ String[] jobNames = getScheduler().getJobNames(GROUP_NAME);
+
+ for (int i = 0; i < jobNames.length; i++) {
+ list.add(getScheduler().getJobDetail(jobNames[i], GROUP_NAME));
+ }
+
+ return list;
+
+ } catch (SchedulerException se) {
+ String msg = "Could not obtain Quartz Scheduler JobDetails";
+ throw new RuntimeException(msg, se);
+ }
+ }
+
+ /**
+ * Return the JobDetail for the given name and group name: "click-group".
+ *
+ * @return the JobDetail for the given name and group name: "click-group".
+ */
+ public JobDetail getJobDetail(String jobName) {
+ try {
+ return getScheduler().getJobDetail(jobName, GROUP_NAME);
+
+ } catch (SchedulerException se) {
+ String msg = "Could not obtain Quartz Scheduler JobDetail";
+ throw new RuntimeException(msg, se);
+ }
+ }
+
+ /**
+ * Return true if the scheduler has the named job.
+ *
+ * @param jobName the name of the job
+ * @return true if the scheduler has the named job
+ */
+ public boolean hasJob(String jobName) {
+ try {
+ return (getScheduler().getJobDetail(jobName, GROUP_NAME) != null);
+
+ } catch (SchedulerException se) {
+ String msg = "Could not obtain Quartz Scheduler JobDetail";
+ throw new RuntimeException(msg, se);
+ }
+ }
+
+ /**
+ * Return the list of JobDetail and Trigger associations.
+ *
+ * @return the list of JobDetail and Trigger associations
+ */
+ public List<JobAndSimpleTrigger> getJobAndTriggerList() {
+ try {
+ List<JobAndSimpleTrigger> list = new ArrayList<JobAndSimpleTrigger>();
+
+ String[] jobNames = getScheduler().getJobNames(GROUP_NAME);
+
+ for (int i = 0; i < jobNames.length; i++) {
+ String jobName = jobNames[i];
+
+ JobDetail jobDetail = getJobDetail(jobName);
+
+ SimpleTrigger trigger = (SimpleTrigger) getScheduler().getTrigger(jobName, TRIGGER_GROUP_NAME);
+
+ list.add(new JobAndSimpleTrigger(jobDetail, (SimpleTrigger) trigger, getScheduler()));
+ }
+
+ return list;
+
+ } catch (SchedulerException se) {
+ String msg = "Could not obtain Quartz Scheduler JobAndTriggerList";
+ throw new RuntimeException(msg, se);
+ }
+ }
+
+ /**
+ * Return the Job and Trigger for the given job name
+ *
+ * @param jobName the name of the job
+ * @return the Job and Trigger for the given job name
+ */
+ public JobAndSimpleTrigger getJobAndTrigger(String jobName) {
+ Validate.notNull(jobName, "Null jobName parameter");
+
+ try {
+ JobDetail jobDetail = getJobDetail(jobName);
+
+ if (jobDetail != null) {
+ SimpleTrigger trigger = (SimpleTrigger)
+ getScheduler().getTrigger(jobName, TRIGGER_GROUP_NAME);
+
+ return new JobAndSimpleTrigger(jobDetail, (SimpleTrigger) trigger, getScheduler());
+
+ } else {
+ return null;
+ }
+
+ } catch (SchedulerException se) {
+ String msg = "Could not obtain Quartz Scheduler JobAndTrigger";
+ throw new RuntimeException(msg, se);
+ }
+ }
+
+ // Private Methods --------------------------------------------------------
+
+ /**
+ * Return the schduler instance.
+ *
+ * @return the schduler instance
+ */
+ private Scheduler getScheduler() {
+ return scheduler;
+ }
+
+}
Added: incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/package.html
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/package.html?rev=774364&view=auto
==============================================================================
--- incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/package.html (added)
+++ incubator/click/trunk/click/examples/src/org/apache/click/examples/quartz/package.html Wed May 13 13:45:15 2009
@@ -0,0 +1,22 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<body>
+Provides the example Quartz scheduler integration classes.
+</body>
\ No newline at end of file
Copied: incubator/click/trunk/click/examples/src/org/apache/click/examples/util/DatabaseInitListener.java (from r769101, incubator/click/trunk/click/examples/src/org/apache/click/examples/util/DatabaseInitFilter.java)
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/src/org/apache/click/examples/util/DatabaseInitListener.java?p2=incubator/click/trunk/click/examples/src/org/apache/click/examples/util/DatabaseInitListener.java&p1=incubator/click/trunk/click/examples/src/org/apache/click/examples/util/DatabaseInitFilter.java&r1=769101&r2=774364&rev=774364&view=diff
==============================================================================
--- incubator/click/trunk/click/examples/src/org/apache/click/examples/util/DatabaseInitFilter.java (original)
+++ incubator/click/trunk/click/examples/src/org/apache/click/examples/util/DatabaseInitListener.java Wed May 13 13:45:15 2009
@@ -30,18 +30,9 @@
import java.util.Timer;
import java.util.TimerTask;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-
-import org.apache.click.examples.domain.Customer;
-import org.apache.click.examples.domain.PostCode;
-import org.apache.click.examples.domain.SystemCode;
-import org.apache.click.examples.domain.User;
-import org.apache.click.util.ClickUtils;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
import org.apache.cayenne.access.DataContext;
import org.apache.cayenne.access.DataDomain;
@@ -52,20 +43,31 @@
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.query.SelectQuery;
import org.apache.click.examples.domain.Course;
+import org.apache.click.examples.domain.Customer;
+import org.apache.click.examples.domain.PostCode;
import org.apache.click.examples.domain.StudentHouse;
+import org.apache.click.examples.domain.SystemCode;
+import org.apache.click.examples.domain.User;
+import org.apache.click.examples.quartz.ExampleJob;
+import org.apache.click.examples.quartz.SchedulerService;
+import org.apache.click.util.ClickUtils;
import org.apache.commons.lang.WordUtils;
+import org.quartz.JobDetail;
+import org.quartz.ee.servlet.QuartzInitializerListener;
+import org.quartz.impl.StdSchedulerFactory;
/**
- * Provides a database initialization filter. This servlet filter creates a
- * examples database schema using the Cayenne {@link DbGenerator} utility class,
- * and loads data files into the database.
+ * Provides a database initialization servlet context listener. This listener
+ * creates a examples database schema using the Cayenne {@link DbGenerator}
+ * utility class, and loads data files into the database. This class also
+ * adds an ExampleJob to the Quartz Scheduler.
* <p/>
- * This filter also provides a customer reloading task which runs every 15
+ * This listener also provides a customer reloading task which runs every 15
* minutes.
*
* @author Malcolm Edgar
*/
-public class DatabaseInitFilter implements Filter {
+public class DatabaseInitListener implements ServletContextListener {
private static final long RELOAD_TIMER_INTERVAL = 1000 * 60 * 5;
@@ -76,10 +78,12 @@
// --------------------------------------------------------- Public Methods
/**
- * @see Filter#init(javax.servlet.FilterConfig)
+ * @see ServletContextListener#contextInitialized(ServletContextEvent)
*/
- public void init(FilterConfig config) throws ServletException {
- ServletUtil.initializeSharedConfiguration(config.getServletContext());
+ public void contextInitialized(ServletContextEvent sce) {
+ ServletContext servletContext = sce.getServletContext();
+
+ ServletUtil.initializeSharedConfiguration(servletContext);
try {
DataDomain cayenneDomain =
@@ -91,29 +95,26 @@
loadDatabase();
- reloadTimer.schedule(new ReloadTask(), 10000, RELOAD_TIMER_INTERVAL);
+ StdSchedulerFactory schedulerFactory = (StdSchedulerFactory)
+ servletContext.getAttribute(QuartzInitializerListener.QUARTZ_FACTORY_KEY);
+
+ SchedulerService schedulerService = new SchedulerService(schedulerFactory);
+
+ loadQuartzJobs(schedulerService);
+
+ reloadTimer.schedule(new ReloadTask(schedulerService), 10000, RELOAD_TIMER_INTERVAL);
+
} catch (Exception e) {
e.printStackTrace();
- throw new ServletException("Error creating database", e);
+ throw new RuntimeException("Error creating database", e);
}
}
-
/**
- * @see Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
- */
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain filterChain) throws IOException, ServletException {
- filterChain.doFilter(request, response);
- }
-
- /**
- * Cancel the reload timer.
- *
- * @see Filter#destroy()
+ * @see ServletContextListener#contextDestroyed(ServletContextEvent)
*/
- public void destroy() {
+ public void contextDestroyed(ServletContextEvent sce) {
reloadTimer.cancel();
}
@@ -172,7 +173,7 @@
private static void loadFile(String filename, DataContext dataContext,
LineProcessor lineProcessor) throws IOException {
- InputStream is = ClickUtils.getResourceAsStream(filename, DatabaseInitFilter.class);
+ InputStream is = ClickUtils.getResourceAsStream(filename, DatabaseInitListener.class);
if (is == null) {
throw new RuntimeException("classpath file not found: " + filename);
@@ -311,10 +312,6 @@
});
}
- private static interface LineProcessor {
- public void processLine(String line, DataContext dataContext);
- }
-
private static String next(StringTokenizer tokenizer) {
String token = tokenizer.nextToken().trim();
if (token.startsWith("\"")) {
@@ -334,15 +331,45 @@
}
}
+ private static void loadQuartzJobs(SchedulerService schedulerService) {
+
+ // Create Submission Synchronize Job
+ if (!schedulerService.hasJob(ExampleJob.class.getSimpleName())) {
+ JobDetail jobDetail = new JobDetail();
+
+ jobDetail.setName(ExampleJob.class.getSimpleName());
+ jobDetail.setDescription("Demonstration job write Hello World");
+ jobDetail.setJobClass(ExampleJob.class);
+
+ // 5 minute interval
+ final long fiveMinutesInMs = 24 * 60 * 60 * 1000;
+
+ schedulerService.scheduleJob(jobDetail, new Date(), null, -1, fiveMinutesInMs);
+ }
+ }
+
+ // Inner Classes ----------------------------------------------------------
+
+ private static interface LineProcessor {
+ public void processLine(String line, DataContext dataContext);
+ }
+
private static class ReloadTask extends TimerTask {
+ private SchedulerService schedulerService;
+
+ public ReloadTask(SchedulerService schedulerService) {
+ this.schedulerService = schedulerService;
+ }
+
+ @SuppressWarnings("unchecked")
public void run() {
DataContext dataContext = null;
try {
dataContext = DataContext.createDataContext();
SelectQuery query = new SelectQuery(Customer.class);
- List list = dataContext.performQuery(query);
+ List<Customer> list = dataContext.performQuery(query);
if (list.size() < 60) {
dataContext.deleteObjects(list);
@@ -352,6 +379,8 @@
dataContext.commitChanges();
}
+ loadQuartzJobs(schedulerService);
+
} catch (Throwable t) {
t.printStackTrace();
@@ -360,6 +389,5 @@
}
}
}
-
}
}
Added: incubator/click/trunk/click/examples/src/quartz.properties
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/src/quartz.properties?rev=774364&view=auto
==============================================================================
--- incubator/click/trunk/click/examples/src/quartz.properties (added)
+++ incubator/click/trunk/click/examples/src/quartz.properties Wed May 13 13:45:15 2009
@@ -0,0 +1,9 @@
+#
+# Quartz Scheduler configuration properties
+#
+org.quartz.scheduler.instanceName = DefaultQuartzScheduler
+org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
+org.quartz.threadPool.threadCount = 5
+org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore
+org.quartz.jobStore.misfireThreshold = 60000
+
Propchange: incubator/click/trunk/click/examples/webapp/WEB-INF/lib/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Wed May 13 13:45:15 2009
@@ -33,3 +33,4 @@
geronimo-annotation_1.0_spec-1.1.1.jar
spring-2.5.6.jar
acegi-security-1.0.7.jar
+quartz-all-1.6.3.jar
Modified: incubator/click/trunk/click/examples/webapp/WEB-INF/menu.xml
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/webapp/WEB-INF/menu.xml?rev=774364&r1=774363&r2=774364&view=diff
==============================================================================
--- incubator/click/trunk/click/examples/webapp/WEB-INF/menu.xml (original)
+++ incubator/click/trunk/click/examples/webapp/WEB-INF/menu.xml Wed May 13 13:45:15 2009
@@ -139,10 +139,12 @@
<menu separator="true"/>
<menu label="Apache Cayenne Form" path="cayenne/cayenne-form-page.htm"/>
<menu label="Cayenne Tabbed Form" path="cayenne/tabbed-cayenne-form-page.htm"/>
- <menu label="Accommodation Demo <br> (one-to-many)" path="cayenne/accommodation-demo.htm"/>
- <menu label="Enrollment Demo <br> (many-to-many)" path="cayenne/enrollment-demo.htm"/>
+ <menu label="PropertySelect Demo (1-to-*)" path="cayenne/accommodation-demo.htm"/>
+ <menu label="PickList Demo (*-to-*)" path="cayenne/enrollment-demo.htm"/>
<menu separator="true"/>
<menu label="Apache POI Excel Export" path="general/excel-export.htm"/>
+ <menu separator="true"/>
+ <menu label="Quartz Scheduler" path="quartz/quartz-job-scheduler.htm"/>
</menu>
</menu>
Modified: incubator/click/trunk/click/examples/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/webapp/WEB-INF/web.xml?rev=774364&r1=774363&r2=774364&view=diff
==============================================================================
--- incubator/click/trunk/click/examples/webapp/WEB-INF/web.xml (original)
+++ incubator/click/trunk/click/examples/webapp/WEB-INF/web.xml Wed May 13 13:45:15 2009
@@ -1,156 +1,165 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
--->
-
-<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
- version="2.4">
-
- <display-name>Click Examples</display-name>
-
- <!--
- Spring configuration location.
- -->
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>WEB-INF/spring-beans.xml</param-value>
- </context-param>
-
- <!--
- Provides an in memory databae initialization filter. In a production
- application a separate database would be used, and this filter would not
- be needed.
- -->
- <filter>
- <filter-name>DatabaseInitFilter</filter-name>
- <filter-class>org.apache.click.examples.util.DatabaseInitFilter</filter-class>
- </filter>
-
- <!--
- Provides a thread local Cayenne DataContext filter.
- -->
- <filter>
- <filter-name>DataContextFilter</filter-name>
- <filter-class>org.apache.click.extras.cayenne.DataContextFilter</filter-class>
- <init-param>
- <param-name>session-scope</param-name>
- <param-value>false</param-value>
- </init-param>
- </filter>
-
- <!--
- Provides a web application performance filter which compresses the response
- and sets the Expires header on selected static resources.
- The "cachable-paths" init parameter tells the filter resources can have
- their Expires header set so the browser will cache them.
- The "excludes-path" init parameter tells the filter which requests should
- be ignored by the filter.
- -->
- <filter>
- <filter-name>PerformanceFilter</filter-name>
- <filter-class>org.apache.click.extras.filter.PerformanceFilter</filter-class>
- <init-param>
- <param-name>cachable-paths</param-name>
- <param-value>/assets/*</param-value>
- </init-param>
- <init-param>
- <param-name>exclude-paths</param-name>
- <param-value>*/excel-export.htm</param-value>
- </init-param>
- </filter>
-
- <!--
- Provides a ACEGI Security filter.
- -->
- <filter>
- <filter-name>FilterToBeanProxy</filter-name>
- <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
- <init-param>
- <param-name>targetClass</param-name>
- <param-value>org.acegisecurity.util.FilterChainProxy</param-value>
- </init-param>
- </filter>
-
- <filter-mapping>
- <filter-name>FilterToBeanProxy</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
-
- <filter-mapping>
- <filter-name>DatabaseInitFilter</filter-name>
- <servlet-name>ClickServlet</servlet-name>
- </filter-mapping>
-
- <filter-mapping>
- <filter-name>DataContextFilter</filter-name>
- <servlet-name>ClickServlet</servlet-name>
- </filter-mapping>
-
- <filter-mapping>
- <filter-name>PerformanceFilter</filter-name>
- <servlet-name>ClickServlet</servlet-name>
- </filter-mapping>
-
- <filter-mapping>
- <filter-name>PerformanceFilter</filter-name>
- <url-pattern>*.css</url-pattern>
- </filter-mapping>
-
- <filter-mapping>
- <filter-name>PerformanceFilter</filter-name>
- <url-pattern>*.js</url-pattern>
- </filter-mapping>
-
- <filter-mapping>
- <filter-name>PerformanceFilter</filter-name>
- <url-pattern>*.gif</url-pattern>
- </filter-mapping>
-
- <filter-mapping>
- <filter-name>PerformanceFilter</filter-name>
- <url-pattern>*.png</url-pattern>
- </filter-mapping>
-
- <!--
- The Spring Context Loader which initializes the Spring runtime.
- -->
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
-
- <!--
- The Spring Click Servlet which handles *.htm requests.
- -->
- <servlet>
- <servlet-name>ClickServlet</servlet-name>
- <servlet-class>org.apache.click.extras.spring.SpringClickServlet</servlet-class>
- <load-on-startup>0</load-on-startup>
- </servlet>
-
- <servlet-mapping>
- <servlet-name>ClickServlet</servlet-name>
- <url-pattern>*.htm</url-pattern>
- </servlet-mapping>
-
- <welcome-file-list>
- <welcome-file>redirect.html</welcome-file>
- </welcome-file-list>
-
-</web-app>
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+ version="2.4">
+
+ <display-name>Click Examples</display-name>
+
+ <!--
+ Spring configuration location.
+ -->
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>WEB-INF/spring-beans.xml</param-value>
+ </context-param>
+
+ <!-- Filters -->
+
+ <!--
+ Provides a thread local Cayenne DataContext filter.
+ -->
+ <filter>
+ <filter-name>DataContextFilter</filter-name>
+ <filter-class>org.apache.click.extras.cayenne.DataContextFilter</filter-class>
+ <init-param>
+ <param-name>session-scope</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ </filter>
+
+ <!--
+ Provides a web application performance filter which compresses the response
+ and sets the Expires header on selected static resources.
+ The "cachable-paths" init parameter tells the filter resources can have
+ their Expires header set so the browser will cache them.
+ The "excludes-path" init parameter tells the filter which requests should
+ be ignored by the filter.
+ -->
+ <filter>
+ <filter-name>PerformanceFilter</filter-name>
+ <filter-class>org.apache.click.extras.filter.PerformanceFilter</filter-class>
+ <init-param>
+ <param-name>cachable-paths</param-name>
+ <param-value>/assets/*</param-value>
+ </init-param>
+ <init-param>
+ <param-name>exclude-paths</param-name>
+ <param-value>*/excel-export.htm</param-value>
+ </init-param>
+ </filter>
+
+ <!--
+ Provides a ACEGI Security filter.
+ -->
+ <filter>
+ <filter-name>FilterToBeanProxy</filter-name>
+ <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
+ <init-param>
+ <param-name>targetClass</param-name>
+ <param-value>org.acegisecurity.util.FilterChainProxy</param-value>
+ </init-param>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>FilterToBeanProxy</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <filter-mapping>
+ <filter-name>DataContextFilter</filter-name>
+ <servlet-name>ClickServlet</servlet-name>
+ </filter-mapping>
+
+ <filter-mapping>
+ <filter-name>PerformanceFilter</filter-name>
+ <servlet-name>ClickServlet</servlet-name>
+ </filter-mapping>
+
+ <filter-mapping>
+ <filter-name>PerformanceFilter</filter-name>
+ <url-pattern>*.css</url-pattern>
+ </filter-mapping>
+
+ <filter-mapping>
+ <filter-name>PerformanceFilter</filter-name>
+ <url-pattern>*.js</url-pattern>
+ </filter-mapping>
+
+ <filter-mapping>
+ <filter-name>PerformanceFilter</filter-name>
+ <url-pattern>*.gif</url-pattern>
+ </filter-mapping>
+
+ <filter-mapping>
+ <filter-name>PerformanceFilter</filter-name>
+ <url-pattern>*.png</url-pattern>
+ </filter-mapping>
+
+ <!-- Listeners -->
+
+ <!--
+ The Quartz initialization listenger which loads the Quartz scheduler.
+ -->
+ <listener>
+ <listener-class>org.quartz.ee.servlet.QuartzInitializerListener</listener-class>
+ </listener>
+
+ <!--
+ The Spring Context Loader which initializes the Spring runtime.
+ -->
+ <listener>
+ <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+ </listener>
+
+ <!--
+ Provides an in memory databae initialization listener. In a production
+ application a separate database would be used, and this listener would not
+ be needed.
+ -->
+ <listener>
+ <listener-class>org.apache.click.examples.util.DatabaseInitListener</listener-class>
+ </listener>
+
+ <!-- Servlets -->
+
+ <!--
+ The Spring Click Servlet which handles *.htm requests.
+ -->
+ <servlet>
+ <servlet-name>ClickServlet</servlet-name>
+ <servlet-class>org.apache.click.extras.spring.SpringClickServlet</servlet-class>
+ <load-on-startup>0</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>ClickServlet</servlet-name>
+ <url-pattern>*.htm</url-pattern>
+ </servlet-mapping>
+
+ <!-- Wecome Files -->
+
+ <welcome-file-list>
+ <welcome-file>redirect.html</welcome-file>
+ </welcome-file-list>
+
+</web-app>
Added: incubator/click/trunk/click/examples/webapp/quartz/quartz-job-and-trigger.htm
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/webapp/quartz/quartz-job-and-trigger.htm?rev=774364&view=auto
==============================================================================
--- incubator/click/trunk/click/examples/webapp/quartz/quartz-job-and-trigger.htm (added)
+++ incubator/click/trunk/click/examples/webapp/quartz/quartz-job-and-trigger.htm Wed May 13 13:45:15 2009
@@ -0,0 +1,8 @@
+#set ($flash = "")
+#set ($flash = $session.flash)
+#if ($flash != "")
+ <b>Flash Message:</b>
+ <p class="infoMsg">$flash</p>
+#end
+
+$form
Added: incubator/click/trunk/click/examples/webapp/quartz/quartz-job-scheduler.htm
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/webapp/quartz/quartz-job-scheduler.htm?rev=774364&view=auto
==============================================================================
--- incubator/click/trunk/click/examples/webapp/quartz/quartz-job-scheduler.htm (added)
+++ incubator/click/trunk/click/examples/webapp/quartz/quartz-job-scheduler.htm Wed May 13 13:45:15 2009
@@ -0,0 +1,24 @@
+
+<p>
+This example shows you how to integrate the
+<a -target="blank" href="http://www.opensymphony.com/quartz/">Quartz</a>
+job scheduling framework into a Click application. The
+<a target="blank" href="http://localhost:9090/click-examples/source-viewer.htm?filename=WEB-INF/classes/org/apache/click/examples/quartz/ExampleJob.java">ExampleJob</a>
+below was added to Quartz by the Click Examples DatabaseInitListener.
+</p>
+
+#set ($flash = "")
+#set ($flash = $session.flash)
+#if ($flash != "")
+ <p class="infoMsg">$flash</p>
+#end
+
+$table
+
+## Render the control buttons
+<div style="margin-top:0.75em;margin-left:0.5em;">
+$refresh
+#if ($pauseAllJobs) $pauseAllJobs #end
+#if ($resumeAllJobs) $resumeAllJobs #end
+#if ($newJob) $newJob #end
+</div>