You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@batchee.apache.org by rm...@apache.org on 2015/12/02 17:39:10 UTC
incubator-batchee git commit: adding StepExecutions command and
handling required @Options
Repository: incubator-batchee
Updated Branches:
refs/heads/master 2d63aa14b -> d24d2ef09
adding StepExecutions command and handling required @Options
Project: http://git-wip-us.apache.org/repos/asf/incubator-batchee/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-batchee/commit/d24d2ef0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-batchee/tree/d24d2ef0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-batchee/diff/d24d2ef0
Branch: refs/heads/master
Commit: d24d2ef09358e9c42bb049e820bf271deccd47c8
Parents: 2d63aa1
Author: Romain Manni-Bucau <rm...@gmail.com>
Authored: Wed Dec 2 17:39:03 2015 +0100
Committer: Romain Manni-Bucau <rm...@gmail.com>
Committed: Wed Dec 2 17:39:03 2015 +0100
----------------------------------------------------------------------
.../java/org/apache/batchee/cli/BatchEECLI.java | 168 ++++++-------------
.../batchee/cli/command/CliConfiguration.java | 30 ----
.../apache/batchee/cli/command/Executions.java | 11 +-
.../batchee/cli/command/JobOperatorCommand.java | 10 +-
.../batchee/cli/command/StepExecutions.java | 93 ++++++++++
.../cli/command/api/CliConfiguration.java | 29 ++++
.../internal/DefaultCliConfiguration.java | 122 ++++++++++++++
.../java/org/apache/batchee/cli/MainTest.java | 28 +++-
8 files changed, 338 insertions(+), 153 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/d24d2ef0/tools/cli/src/main/java/org/apache/batchee/cli/BatchEECLI.java
----------------------------------------------------------------------
diff --git a/tools/cli/src/main/java/org/apache/batchee/cli/BatchEECLI.java b/tools/cli/src/main/java/org/apache/batchee/cli/BatchEECLI.java
index 55f084b..6fb656e 100644
--- a/tools/cli/src/main/java/org/apache/batchee/cli/BatchEECLI.java
+++ b/tools/cli/src/main/java/org/apache/batchee/cli/BatchEECLI.java
@@ -17,19 +17,21 @@
package org.apache.batchee.cli;
import org.apache.batchee.cli.command.Abandon;
-import org.apache.batchee.cli.command.CliConfiguration;
import org.apache.batchee.cli.command.Eviction;
import org.apache.batchee.cli.command.Executions;
-import org.apache.batchee.cli.command.api.Exit;
import org.apache.batchee.cli.command.Instances;
import org.apache.batchee.cli.command.Names;
import org.apache.batchee.cli.command.Restart;
import org.apache.batchee.cli.command.Running;
import org.apache.batchee.cli.command.Start;
import org.apache.batchee.cli.command.Status;
+import org.apache.batchee.cli.command.StepExecutions;
import org.apache.batchee.cli.command.Stop;
+import org.apache.batchee.cli.command.api.CliConfiguration;
import org.apache.batchee.cli.command.api.Command;
+import org.apache.batchee.cli.command.api.Exit;
import org.apache.batchee.cli.command.api.UserCommand;
+import org.apache.batchee.cli.command.internal.DefaultCliConfiguration;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
@@ -38,17 +40,12 @@ import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
-import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -56,68 +53,12 @@ import java.util.Map;
import java.util.ServiceLoader;
import java.util.TreeMap;
-import static java.lang.ClassLoader.getSystemClassLoader;
import static java.util.Arrays.asList;
public class BatchEECLI {
public static void main(final String[] args) {
final Iterator<CliConfiguration> configuration = ServiceLoader.load(CliConfiguration.class).iterator();
- final CliConfiguration cliConfiguration = configuration.hasNext() ? configuration.next() : new CliConfiguration() {
- @Override
- public String name() {
- return "batchee";
- }
-
- @Override
- public String description() {
- return "BatchEE CLI";
- }
-
- @Override
- public boolean addDefaultCommands() {
- return true;
- }
-
- @Override
- public Iterator<Class<? extends UserCommand>> userCommands() {
- final Collection<Class<? extends UserCommand>> classes = new ArrayList<Class<? extends UserCommand>>();
- try { // read manually cause we dont want to instantiate them there, so no ServiceLoader
- final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
- final ClassLoader loader = tccl != null ? tccl : getSystemClassLoader();
- final Enumeration<URL> uc = loader.getResources("META-INF/services/org.apache.batchee.cli.command.UserCommand");
- while (uc.hasMoreElements()) {
- final URL url = uc.nextElement();
- BufferedReader r = null;
- try {
- r = new BufferedReader(new InputStreamReader(url.openStream()));
- String line;
- while ((line = r.readLine()) != null) {
- if (line.startsWith("#") || line.trim().isEmpty()) {
- continue;
- }
- classes.add(Class.class.cast(loader.loadClass(line.trim())));
- }
- } catch (final IOException ioe) {
- throw new IllegalStateException(ioe);
- } catch (final ClassNotFoundException cnfe) {
- throw new IllegalArgumentException(cnfe);
- } finally {
- if (r != null) {
- r.close();
- }
- }
- }
- } catch (final IOException e) {
- throw new IllegalStateException(e);
- }
- return classes.iterator();
- }
-
- @Override
- public Runnable decorate(final Runnable task) {
- return task;
- }
- };
+ final CliConfiguration cliConfiguration = configuration.hasNext() ? configuration.next() : new DefaultCliConfiguration();
final Map<String, Class<? extends Runnable>> commands = new TreeMap<String, Class<? extends Runnable>>();
if (cliConfiguration.addDefaultCommands()) {
@@ -127,7 +68,7 @@ public class BatchEECLI {
Status.class, Running.class,
Stop.class, Abandon.class,
Instances.class, Executions.class,
- Eviction.class)) {
+ StepExecutions.class, Eviction.class)) {
addCommand(commands, type);
}
}
@@ -174,58 +115,7 @@ public class BatchEECLI {
final CommandLineParser parser = new DefaultParser();
try {
final CommandLine line = parser.parse(options, newArgs.toArray(new String[newArgs.size()]));
-
- final Runnable commandInstance = cmd.newInstance();
- if (!newArgs.isEmpty()) { // we have few commands we can execute without args even if we have a bunch of config
- for (final Map.Entry<String, Field> option : fields.entrySet()) {
- final String key = option.getKey();
- if (key.isEmpty()) { // arguments, not an option
- final List<String> list = line.getArgList();
- if (list != null) {
- final Field field = option.getValue();
- final Type expectedType = field.getGenericType();
- if (ParameterizedType.class.isInstance(expectedType)) {
- final ParameterizedType pt = ParameterizedType.class.cast(expectedType);
- if ((pt.getRawType() == List.class || pt.getRawType() == Collection.class)
- && pt.getActualTypeArguments().length == 1 && pt.getActualTypeArguments()[0] == String.class) {
- field.set(commandInstance, list);
- } else {
- throw new IllegalArgumentException("@Arguments only supports List<String>");
- }
- } else {
- throw new IllegalArgumentException("@Arguments only supports List<String>");
- }
- }
- } else {
- final String value = line.getOptionValue(key);
- if (value != null) {
- final Field field = option.getValue();
- final Class<?> expectedType = field.getType();
- if (String.class == expectedType) {
- field.set(commandInstance, value);
- } else if (long.class == expectedType) {
- field.set(commandInstance, Long.parseLong(value));
- } else if (int.class == expectedType) {
- field.set(commandInstance, Integer.parseInt(value));
- } else if (boolean.class == expectedType) {
- field.set(commandInstance, Boolean.parseBoolean(value));
- } else if (short.class == expectedType) {
- field.set(commandInstance, Short.parseShort(value));
- } else if (byte.class == expectedType) {
- field.set(commandInstance, Byte.parseByte(value));
- } else {
- try {
- field.set(commandInstance, expectedType.getMethod("fromString", String.class)
- .invoke(null, value));
- } catch (final Exception e) {
- throw new IllegalArgumentException(expectedType + " not supported as option with value '" + value + "'");
- }
- }
- }
- }
- }
- }
- cliConfiguration.decorate(commandInstance).run();
+ cliConfiguration.decorate(instantiate(cmd, cliConfiguration, fields, !newArgs.isEmpty(), line)).run();
} catch (final ParseException e) {
printHelp(command, options);
} catch (final RuntimeException e) {
@@ -245,6 +135,44 @@ public class BatchEECLI {
}
}
+ private static Runnable instantiate(final Class<? extends Runnable> cmd,
+ final CliConfiguration configuration,
+ final Map<String, Field> fields,
+ final boolean hasArgs,
+ final CommandLine line) throws InstantiationException, IllegalAccessException {
+ final Runnable commandInstance = cmd.newInstance();
+ if (hasArgs) { // we have few commands we can execute without args even if we have a bunch of config
+ for (final Map.Entry<String, Field> option : fields.entrySet()) {
+ final String key = option.getKey();
+ if (key.isEmpty()) { // arguments, not an option
+ final List<String> list = line.getArgList();
+ if (list != null) {
+ final Field field = option.getValue();
+ final Type expectedType = field.getGenericType();
+ if (ParameterizedType.class.isInstance(expectedType)) {
+ final ParameterizedType pt = ParameterizedType.class.cast(expectedType);
+ if ((pt.getRawType() == List.class || pt.getRawType() == Collection.class)
+ && pt.getActualTypeArguments().length == 1 && pt.getActualTypeArguments()[0] == String.class) {
+ field.set(commandInstance, list);
+ } else {
+ throw new IllegalArgumentException("@Arguments only supports List<String>");
+ }
+ } else {
+ throw new IllegalArgumentException("@Arguments only supports List<String>");
+ }
+ }
+ } else {
+ final String value = line.getOptionValue(key);
+ if (value != null) {
+ final Field field = option.getValue();
+ field.set(commandInstance, configuration.coerce(value, field.getGenericType()));
+ }
+ }
+ }
+ }
+ return commandInstance;
+ }
+
private static void printHelp(final Command command, final Options options) {
new HelpFormatter().printHelp(command.name(), '\n' + command.description() + "\n\n", options, null, true);
}
@@ -262,7 +190,11 @@ public class BatchEECLI {
if (option != null) {
final String name = option.name();
- options.addOption(Option.builder(name).desc(option.description()).hasArg().build());
+ final Option.Builder builder = Option.builder(name).desc(option.description()).hasArg();
+ if (option.required()) {
+ builder.required();
+ }
+ options.addOption(builder.build());
fields.put(name, f);
f.setAccessible(true);
} else if (arguments != null) {
http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/d24d2ef0/tools/cli/src/main/java/org/apache/batchee/cli/command/CliConfiguration.java
----------------------------------------------------------------------
diff --git a/tools/cli/src/main/java/org/apache/batchee/cli/command/CliConfiguration.java b/tools/cli/src/main/java/org/apache/batchee/cli/command/CliConfiguration.java
deleted file mode 100644
index b8a8522..0000000
--- a/tools/cli/src/main/java/org/apache/batchee/cli/command/CliConfiguration.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.batchee.cli.command;
-
-import org.apache.batchee.cli.command.api.UserCommand;
-
-import java.util.Iterator;
-
-public interface CliConfiguration {
- String name();
- String description();
- boolean addDefaultCommands();
- Iterator<Class<? extends UserCommand>> userCommands();
- Runnable decorate(Runnable task);
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/d24d2ef0/tools/cli/src/main/java/org/apache/batchee/cli/command/Executions.java
----------------------------------------------------------------------
diff --git a/tools/cli/src/main/java/org/apache/batchee/cli/command/Executions.java b/tools/cli/src/main/java/org/apache/batchee/cli/command/Executions.java
index dcb4f44..e8ba4c1 100644
--- a/tools/cli/src/main/java/org/apache/batchee/cli/command/Executions.java
+++ b/tools/cli/src/main/java/org/apache/batchee/cli/command/Executions.java
@@ -21,6 +21,7 @@ import org.apache.batchee.cli.command.api.Option;
import org.apache.batchee.container.impl.JobInstanceImpl;
import org.apache.commons.lang3.StringUtils;
+import javax.batch.operations.JobOperator;
import javax.batch.runtime.JobExecution;
import java.util.List;
@@ -29,9 +30,13 @@ public class Executions extends JobOperatorCommand {
@Option(name = "id", description = "instance id", required = true)
private long id;
+ @Option(name = "showSteps", description = "if steps should be dumped as well")
+ private boolean steps;
+
@Override
public void doRun() {
- final List<JobExecution> executions = operator().getJobExecutions(new JobInstanceImpl(id));
+ final JobOperator operator = operator();
+ final List<JobExecution> executions = operator.getJobExecutions(new JobInstanceImpl(id));
if (!executions.isEmpty()) {
info("Executions of " + executions.iterator().next().getJobName() + " for instance " + id);
}
@@ -43,5 +48,9 @@ public class Executions extends JobOperatorCommand {
StringUtils.leftPad(exec.getBatchStatus() != null ? exec.getBatchStatus().toString() : "null", 12),
StringUtils.leftPad(exec.getExitStatus(), 11), exec.getStartTime(), exec.getEndTime()));
}
+
+ if (steps) {
+ new StepExecutions().withOperator(operator).withId(id).run();
+ }
}
}
http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/d24d2ef0/tools/cli/src/main/java/org/apache/batchee/cli/command/JobOperatorCommand.java
----------------------------------------------------------------------
diff --git a/tools/cli/src/main/java/org/apache/batchee/cli/command/JobOperatorCommand.java b/tools/cli/src/main/java/org/apache/batchee/cli/command/JobOperatorCommand.java
index 7357e18..27c9891 100644
--- a/tools/cli/src/main/java/org/apache/batchee/cli/command/JobOperatorCommand.java
+++ b/tools/cli/src/main/java/org/apache/batchee/cli/command/JobOperatorCommand.java
@@ -113,9 +113,15 @@ public abstract class JobOperatorCommand implements Runnable {
@Option(name = "addFolderToLoader", description = "force shared lib and libs folders to be added to the classloader")
private boolean addFolderToLoader = false;
+ protected JobOperator operator;
+
protected JobOperator operator() {
+ if (operator != null) {
+ return operator;
+ }
+
if (baseUrl == null) {
- return BatchRuntime.getJobOperator();
+ return operator = BatchRuntime.getJobOperator();
}
final ClientConfiguration configuration = new ClientConfiguration();
@@ -140,7 +146,7 @@ public abstract class JobOperatorCommand implements Runnable {
security.setPassword(password);
security.setType(type);
- return BatchEEJAXRSClientFactory.newClient(configuration);
+ return operator = BatchEEJAXRSClientFactory.newClient(configuration);
}
protected void info(final String text) {
http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/d24d2ef0/tools/cli/src/main/java/org/apache/batchee/cli/command/StepExecutions.java
----------------------------------------------------------------------
diff --git a/tools/cli/src/main/java/org/apache/batchee/cli/command/StepExecutions.java b/tools/cli/src/main/java/org/apache/batchee/cli/command/StepExecutions.java
new file mode 100644
index 0000000..45a0212
--- /dev/null
+++ b/tools/cli/src/main/java/org/apache/batchee/cli/command/StepExecutions.java
@@ -0,0 +1,93 @@
+/*
+ * 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.batchee.cli.command;
+
+import org.apache.batchee.cli.command.api.Command;
+import org.apache.batchee.cli.command.api.Option;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.batch.operations.JobOperator;
+import javax.batch.runtime.Metric;
+import javax.batch.runtime.StepExecution;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Command(name = "stepExecutions", description = "list step executions for a particular execution")
+public class StepExecutions extends JobOperatorCommand {
+ @Option(name = "id", description = "execution id", required = true)
+ private long id;
+
+ public StepExecutions withId(final long id) {
+ this.id = id;
+ return this;
+ }
+ public StepExecutions withOperator(final JobOperator operator) {
+ this.operator = operator;
+ return this;
+ }
+
+ @Override
+ public void doRun() {
+ final JobOperator operator = operator();
+ final List<StepExecution> executions = operator.getStepExecutions(id);
+ if (executions == null || executions.isEmpty()) {
+ info("Executions of " + id + " not found");
+ return;
+ }
+
+ info("Step executions of " + id);
+
+ final List<Metric.MetricType> metricsOrder = new ArrayList<Metric.MetricType>();
+ final StringBuilder metrics = new StringBuilder();
+ for (final Metric.MetricType type : Metric.MetricType.values()) {
+ metrics.append("\t|\t").append(type.name());
+ metricsOrder.add(type);
+ }
+
+ final DateFormat format = new SimpleDateFormat("YYYYMMdd hh:mm:ss");
+ info(" step id\t|\t step name\t|\t start time \t|\t end time \t|\texit status\t|\tbatch status" + metrics.toString());
+ for (final StepExecution exec : executions) {
+ final StringBuilder builder = new StringBuilder(String.format("%10d\t|\t%s\t|\t%s\t|\t%s\t|\t%s\t|\t%s",
+ exec.getStepExecutionId(),
+ StringUtils.center(exec.getStepName(), 10),
+ format.format(exec.getStartTime()),
+ exec.getEndTime() != null ? format.format(exec.getEndTime()) : "-",
+ StringUtils.center(exec.getExitStatus() == null ? "-" : exec.getExitStatus(), 11),
+ StringUtils.center(String.valueOf(exec.getBatchStatus()), 12)));
+ final Map<Metric.MetricType, Long> stepMetrics = new HashMap<Metric.MetricType, Long>();
+ if (exec.getMetrics() != null) {
+ for (final Metric m : exec.getMetrics()) {
+ stepMetrics.put(m.getType(), m.getValue());
+ }
+ }
+ for (final Metric.MetricType type : metricsOrder) {
+ final Long value = stepMetrics.get(type);
+ builder.append("\t|\t");
+ if (value != null) {
+ builder.append(StringUtils.center(Long.toString(value), type.name().length()));
+ } else {
+ builder.append("-");
+ }
+ }
+ info(builder.toString());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/d24d2ef0/tools/cli/src/main/java/org/apache/batchee/cli/command/api/CliConfiguration.java
----------------------------------------------------------------------
diff --git a/tools/cli/src/main/java/org/apache/batchee/cli/command/api/CliConfiguration.java b/tools/cli/src/main/java/org/apache/batchee/cli/command/api/CliConfiguration.java
new file mode 100644
index 0000000..96d09f2
--- /dev/null
+++ b/tools/cli/src/main/java/org/apache/batchee/cli/command/api/CliConfiguration.java
@@ -0,0 +1,29 @@
+/*
+ * 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.batchee.cli.command.api;
+
+import java.lang.reflect.Type;
+import java.util.Iterator;
+
+public interface CliConfiguration {
+ String name();
+ String description();
+ boolean addDefaultCommands();
+ Iterator<Class<? extends UserCommand>> userCommands();
+ Runnable decorate(Runnable task);
+ Object coerce(String value, Type expected);
+}
http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/d24d2ef0/tools/cli/src/main/java/org/apache/batchee/cli/command/internal/DefaultCliConfiguration.java
----------------------------------------------------------------------
diff --git a/tools/cli/src/main/java/org/apache/batchee/cli/command/internal/DefaultCliConfiguration.java b/tools/cli/src/main/java/org/apache/batchee/cli/command/internal/DefaultCliConfiguration.java
new file mode 100644
index 0000000..08060ac
--- /dev/null
+++ b/tools/cli/src/main/java/org/apache/batchee/cli/command/internal/DefaultCliConfiguration.java
@@ -0,0 +1,122 @@
+/*
+ * 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.batchee.cli.command.internal;
+
+import org.apache.batchee.cli.command.api.CliConfiguration;
+import org.apache.batchee.cli.command.api.UserCommand;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.reflect.Type;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+import static java.lang.ClassLoader.getSystemClassLoader;
+
+public class DefaultCliConfiguration implements CliConfiguration {
+ @Override
+ public String name() {
+ return "batchee";
+ }
+
+ @Override
+ public String description() {
+ return "BatchEE CLI";
+ }
+
+ @Override
+ public boolean addDefaultCommands() {
+ return true;
+ }
+
+ @Override
+ public Iterator<Class<? extends UserCommand>> userCommands() {
+ final Collection<Class<? extends UserCommand>> classes = new ArrayList<Class<? extends UserCommand>>();
+ try { // read manually cause we dont want to instantiate them there, so no ServiceLoader
+ final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+ final ClassLoader loader = tccl != null ? tccl : getSystemClassLoader();
+ final Enumeration<URL> uc = loader.getResources("META-INF/services/org.apache.batchee.cli.command.UserCommand");
+ while (uc.hasMoreElements()) {
+ final URL url = uc.nextElement();
+ BufferedReader r = null;
+ try {
+ r = new BufferedReader(new InputStreamReader(url.openStream()));
+ String line;
+ while ((line = r.readLine()) != null) {
+ if (line.startsWith("#") || line.trim().isEmpty()) {
+ continue;
+ }
+ classes.add(Class.class.cast(loader.loadClass(line.trim())));
+ }
+ } catch (final IOException ioe) {
+ throw new IllegalStateException(ioe);
+ } catch (final ClassNotFoundException cnfe) {
+ throw new IllegalArgumentException(cnfe);
+ } finally {
+ if (r != null) {
+ r.close();
+ }
+ }
+ }
+ } catch (final IOException e) {
+ throw new IllegalStateException(e);
+ }
+ return classes.iterator();
+ }
+
+ @Override
+ public Runnable decorate(final Runnable task) {
+ return task;
+ }
+
+ @Override
+ public Object coerce(String value, Type expected) {
+ if (String.class == expected) {
+ return value;
+ }
+ if (long.class == expected) {
+ return Long.parseLong(value);
+ }
+ if (int.class == expected) {
+ return Integer.parseInt(value);
+ }
+ if (boolean.class == expected) {
+ return Boolean.parseBoolean(value);
+ }
+ if (short.class == expected) {
+ return Short.parseShort(value);
+ }
+ if (byte.class == expected) {
+ return Byte.parseByte(value);
+ }
+ if (char.class == expected) {
+ return value.charAt(0);
+ }
+ if (Class.class.isInstance(expected)) {
+ try {
+ return Class.class.cast(expected).getMethod("fromString", String.class).invoke(null, value);
+ } catch (final Exception e) {
+ // no-op
+ }
+ }
+ throw new IllegalArgumentException(expected + " not supported as option with value '" + value + "'");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-batchee/blob/d24d2ef0/tools/cli/src/test/java/org/apache/batchee/cli/MainTest.java
----------------------------------------------------------------------
diff --git a/tools/cli/src/test/java/org/apache/batchee/cli/MainTest.java b/tools/cli/src/test/java/org/apache/batchee/cli/MainTest.java
index 6139a09..957ab3b 100644
--- a/tools/cli/src/test/java/org/apache/batchee/cli/MainTest.java
+++ b/tools/cli/src/test/java/org/apache/batchee/cli/MainTest.java
@@ -38,6 +38,7 @@ import static org.junit.Assert.assertThat;
public class MainTest {
@Rule
public final StandardOutputStreamLog stdout = new StandardOutputStreamLog();
+
@Rule
public final StandardErrorStreamLog stderr = new StandardErrorStreamLog();
@@ -54,6 +55,7 @@ public class MainTest {
"running: list running batches\n" +
"start: start a batch\n" +
"status: list last batches statuses\n" +
+ "stepExecutions: list step executions for a particular execution\n" +
"stop: stop a batch from its id\n" +
"user1\n" +
"user2\n", stderr.getLog().replace(System.getProperty("line.separator"), "\n"));
@@ -63,8 +65,10 @@ public class MainTest {
public void helpCommand() {
main(new String[] { "help", "evict" }); // using a simple command to avoid a big block for nothing
assertEquals(
- "usage: evict [-until <arg>]\n\n" +
- "remove old data, uses embedded configuration (no JAXRS support yet)\n\n" +
+ "usage: evict -until <arg>\n" +
+ "\n" +
+ "remove old data, uses embedded configuration (no JAXRS support yet)\n" +
+ "\n" +
" -until <arg> date until when the eviction will occur (excluded),\n" +
" YYYYMMDD format\n", stdout.getLog().replace(System.getProperty("line.separator"), "\n"));
}
@@ -208,6 +212,26 @@ public class MainTest {
}
@Test
+ public void stepExecutions() {
+ // ensure we have at least one thing to print
+ final JobOperator jobOperator = BatchRuntime.getJobOperator();
+ final long id = jobOperator.start("sample", null);
+
+ Batches.waitForEnd(jobOperator, id);
+ main(new String[]{"stepExecutions", "-id", Long.toString(id)});
+
+ System.out.println(stdout.getLog());
+ assertThat(stdout.getLog(), containsString(
+ "step id\t|\t step name\t|\t start time \t|\t end time \t|\t" +
+ "exit status\t|\tbatch status\t|\t" +
+ "READ_COUNT\t|\tWRITE_COUNT\t|\tCOMMIT_COUNT\t|\tROLLBACK_COUNT\t|\tREAD_SKIP_COUNT\t|\t" +
+ "PROCESS_SKIP_COUNT\t|\tFILTER_COUNT\t|\tWRITE_SKIP_COUNT"));
+ assertThat(stdout.getLog(), containsString("OK"));
+ assertThat(stdout.getLog(), containsString("sample-step"));
+ assertThat(stdout.getLog(), containsString("COMPLETED"));
+ }
+
+ @Test
public void lifecycle() {
// whatever child of JobOperatorCommand so using running which is simple
main(new String[]{ "running", "-lifecycle", MyLifecycle.class.getName() });