From d8da44cc929dd2acfda6ac64b567c93ec6bfbc02 Mon Sep 17 00:00:00 2001 From: dsyer Date: Thu, 24 Jan 2008 12:49:36 +0000 Subject: [PATCH] RESOLVED - issue BATCH-312: Fix JMX demo now that JobIdentifier has been replaced with JobParameters http://jira.springframework.org/browse/BATCH-312 Implemented ExportedJobLauncher and exposed in JMX --- .../support/ExportedJobLauncher.java | 17 +- .../bootstrap/support/JobPropertyEditor.java | 77 +++++ .../support/SimpleExportedJobLauncher.java | 184 +++++++++++ .../support/JobPropertyEditorTests.java | 76 +++++ .../.settings/jmxLauncher.launch | 2 + .../src/main/resources/jobs/adhocLoopJob.xml | 288 +++++++++--------- 6 files changed, 494 insertions(+), 150 deletions(-) create mode 100644 spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/JobPropertyEditor.java create mode 100644 spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/SimpleExportedJobLauncher.java create mode 100644 spring-batch-execution/src/test/java/org/springframework/batch/execution/bootstrap/support/JobPropertyEditorTests.java diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/ExportedJobLauncher.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/ExportedJobLauncher.java index 2a72da8af..655d11ce4 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/ExportedJobLauncher.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/ExportedJobLauncher.java @@ -39,24 +39,27 @@ public interface ExportedJobLauncher { * @param name the name of the job to launch * @return a representation of the {@link JobExecution} returned by a * {@link JobLauncher}. - * - * @see #run() */ String run(String name); /** - * Stop all running jobs. + * Launch a job with the given name and parameters. * - * @see JobLauncher#stop() + * @param name the name of the job to launch + * @return a representation of the {@link JobExecution} returned by a + * {@link JobLauncher}. + */ + String run(String name, String params); + + /** + * Stop all running jobs. */ void stop(); /** - * Enquire if any jobs are still running. + * Enquire if any jobs launched here are still running. * * @return true if any jobs are running. - * - * @see JobLauncher#isRunning() */ boolean isRunning(); diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/JobPropertyEditor.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/JobPropertyEditor.java new file mode 100644 index 000000000..2a35112d5 --- /dev/null +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/JobPropertyEditor.java @@ -0,0 +1,77 @@ +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed 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.springframework.batch.execution.bootstrap.support; + +import java.beans.PropertyEditor; +import java.beans.PropertyEditorSupport; + +import org.springframework.batch.core.domain.Job; +import org.springframework.batch.core.domain.JobLocator; +import org.springframework.batch.core.domain.NoSuchJobException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; + +/** + * A {@link PropertyEditor} that delegates to a {@link JobLocator}. + * @author Dave Syer + * + */ +public class JobPropertyEditor extends PropertyEditorSupport implements InitializingBean { + + private JobLocator jobLocator; + + /* (non-Javadoc) + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + Assert.notNull(jobLocator, "JobLocator is required"); + } + + /** + * Accept job name and convert to {@link Job} through the injected {@link JobLocator}. + * + * @see java.beans.PropertyEditorSupport#setAsText(java.lang.String) + */ + public void setAsText(String text) throws IllegalArgumentException { + try { + setValue(jobLocator.getJob(text)); + } + catch (NoSuchJobException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * Extract the name from the {@link JobIdentifier}. + * + * @see java.beans.PropertyEditorSupport#getAsText() + */ + public String getAsText() { + Job job = (Job) getValue(); + if (job == null) { + return null; + } + return job.getName(); + } + + /** + * Public setter for the {@link JobLocator}. + * @param jobLocator the jobLocator to set + */ + public void setJobLocator(JobLocator jobLocator) { + this.jobLocator = jobLocator; + } +} \ No newline at end of file diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/SimpleExportedJobLauncher.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/SimpleExportedJobLauncher.java new file mode 100644 index 000000000..675b21ebf --- /dev/null +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/SimpleExportedJobLauncher.java @@ -0,0 +1,184 @@ +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed 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.springframework.batch.execution.bootstrap.support; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Properties; + +import org.springframework.batch.core.domain.Job; +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.JobLocator; +import org.springframework.batch.core.domain.JobParameters; +import org.springframework.batch.core.domain.NoSuchJobException; +import org.springframework.batch.core.domain.StepExecution; +import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; +import org.springframework.batch.core.runtime.JobParametersFactory; +import org.springframework.batch.execution.launch.JobLauncher; +import org.springframework.batch.support.PropertiesConverter; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; + +/** + * @author Dave Syer + * + */ +public class SimpleExportedJobLauncher implements ExportedJobLauncher, InitializingBean { + + private JobLauncher launcher; + + private JobLocator jobLocator; + + private Map registry = new HashMap(); + + private JobParametersFactory jobParametersFactory = new DefaultJobParametersFactory(); + + /* (non-Javadoc) + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + Assert.notNull(launcher, "JobLauncher must be provided."); + Assert.notNull(jobLocator, "JobLocator must be provided."); + } + + /** + * Public setter for the {@link JobLauncher}. + * @param launcher the launcher to set + */ + public void setLauncher(JobLauncher launcher) { + this.launcher = launcher; + } + + /** + * Public setter for the JobLocator. + * @param jobLocator the jobLocator to set + */ + public void setJobLocator(JobLocator jobLocator) { + this.jobLocator = jobLocator; + } + + /** + * Public setter for the JobParametersFactory. + * @param jobParametersFactory the jobParametersFactory to set + */ + public void setJobParametersFactory(JobParametersFactory jobParametersFactory) { + this.jobParametersFactory = jobParametersFactory; + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.execution.bootstrap.support.ExportedJobLauncher#getStatistics() + */ + public Properties getStatistics() { + Properties result = new Properties(); + int i = 0; + for (Iterator iterator = registry.keySet().iterator(); iterator.hasNext();) { + String key = (String) iterator.next(); + JobExecution execution = (JobExecution) registry.get(key); + addStatistics(result, execution, "job" + i + "."); + i++; + } + return result; + } + + /** + * @param result + * @param execution + */ + private void addStatistics(Properties result, JobExecution execution, String prefix) { + int i = 0; + for (Iterator iterator = execution.getStepExecutions().iterator(); iterator.hasNext();) { + StepExecution stepExecution = (StepExecution) iterator.next(); + Properties statistics = stepExecution.getStatistics(); + for (Iterator iter = statistics.keySet().iterator(); iter.hasNext();) { + String key = (String) iter.next(); + result.setProperty(prefix + "step" + i + "." + key, statistics.getProperty(key)); + } + } + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.execution.bootstrap.support.ExportedJobLauncher#isRunning() + */ + public boolean isRunning() { + for (Iterator iterator = registry.keySet().iterator(); iterator.hasNext();) { + String key = (String) iterator.next(); + JobExecution execution = (JobExecution) registry.get(key); + if (execution.isRunning()) { + return true; + } + } + return false; + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.execution.bootstrap.support.ExportedJobLauncher#run(java.lang.String) + */ + public String run(String name) { + return run(name, null); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.execution.bootstrap.support.ExportedJobLauncher#run(java.lang.String, + * java.lang.String) + */ + public String run(String name, String params) { + + Job job; + try { + job = jobLocator.getJob(name); + } + catch (NoSuchJobException e) { + return e.getClass().getName() + ": " + e.getMessage(); + } + + JobParameters jobParameters = new JobParameters(); + if (params != null) { + jobParameters = jobParametersFactory.getJobParameters(PropertiesConverter.stringToProperties(params)); + } + + JobExecution execution; + try { + execution = launcher.run(job, jobParameters); + } + catch (JobExecutionAlreadyRunningException e) { + return e.getClass().getName() + ": " + e.getMessage(); + } + + registry.put(name + params, execution); + + return execution.toString(); + + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.execution.bootstrap.support.ExportedJobLauncher#stop() + */ + public void stop() { + for (Iterator iterator = registry.keySet().iterator(); iterator.hasNext();) { + String key = (String) iterator.next(); + JobExecution execution = (JobExecution) registry.get(key); + execution.stop(); + } + registry.clear(); + } + +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/bootstrap/support/JobPropertyEditorTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/bootstrap/support/JobPropertyEditorTests.java new file mode 100644 index 000000000..d62f826ad --- /dev/null +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/bootstrap/support/JobPropertyEditorTests.java @@ -0,0 +1,76 @@ +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed 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.springframework.batch.execution.bootstrap.support; + +import junit.framework.TestCase; + +import org.springframework.batch.core.domain.Job; +import org.springframework.batch.core.domain.JobLocator; +import org.springframework.batch.core.domain.NoSuchJobException; + +/** + * @author Dave Syer + * + */ +public class JobPropertyEditorTests extends TestCase { + + private JobPropertyEditor editor = new JobPropertyEditor(); + private Job job = new Job(); + + /* (non-Javadoc) + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + editor.setJobLocator(new JobLocator() { + public Job getJob(String name) throws NoSuchJobException { + job.setName(name); + return job; + } + }); + } + + public void testMandatoryProperties() throws Exception { + editor = new JobPropertyEditor(); + try { + editor.afterPropertiesSet(); + fail("Expected IllegalArgumentException"); + } + catch (IllegalArgumentException e) { + // expected + } + } + + /** + * Test method for + * {@link org.springframework.batch.execution.bootstrap.support.JobParametersPropertyEditor#setAsText(java.lang.String)}. + */ + public void testSetAsTextString() { + editor.setAsText("foo"); + Job job = (Job) editor.getValue(); + assertEquals(job, job); + } + + /** + * Test method for + * {@link org.springframework.batch.execution.bootstrap.support.JobParametersPropertyEditor#getAsText()}. + */ + public void testGetAsText() { + editor.setAsText("foo"); + assertEquals("foo", editor.getAsText()); + } + +} diff --git a/spring-batch-samples/.settings/jmxLauncher.launch b/spring-batch-samples/.settings/jmxLauncher.launch index 2d54a277c..d3b19648a 100644 --- a/spring-batch-samples/.settings/jmxLauncher.launch +++ b/spring-batch-samples/.settings/jmxLauncher.launch @@ -8,6 +8,8 @@ + + diff --git a/spring-batch-samples/src/main/resources/jobs/adhocLoopJob.xml b/spring-batch-samples/src/main/resources/jobs/adhocLoopJob.xml index 62d21e823..13dd2baaa 100644 --- a/spring-batch-samples/src/main/resources/jobs/adhocLoopJob.xml +++ b/spring-batch-samples/src/main/resources/jobs/adhocLoopJob.xml @@ -1,153 +1,155 @@ - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - org.springframework.batch.execution.bootstrap.support.ExportedJobLauncher - - - - - - - - - - - - - - org.springframework.batch.sample.ExportedJobLoader - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.springframework.batch.sample.ExportedJobLoader + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +