diff --git a/azkaban-common/src/main/java/azkaban/jobExecutor/JavaProcessJob.java b/azkaban-common/src/main/java/azkaban/jobExecutor/JavaProcessJob.java
index 21974c5..024fdc1 100644
--- a/azkaban-common/src/main/java/azkaban/jobExecutor/JavaProcessJob.java
+++ b/azkaban-common/src/main/java/azkaban/jobExecutor/JavaProcessJob.java
@@ -59,7 +59,7 @@ public class JavaProcessJob extends ProcessJob {
command += getJVMArguments() + " ";
command += "-Xms" + getInitialMemorySize() + " ";
command += "-Xmx" + getMaxMemorySize() + " ";
- command += "-cp " + createArguments(getClassPaths(), ":") + " ";
+ command += getClassPathParam();
command += getJavaClass() + " ";
command += getMainArguments();
@@ -73,7 +73,8 @@ public class JavaProcessJob extends ProcessJob {
protected String getClassPathParam() {
final List<String> classPath = getClassPaths();
if (classPath == null || classPath.size() == 0) {
- return "";
+ throw new IllegalArgumentException(
+ "No classpath defined and no .jar files found in job directory. Can't run java command.");
}
return "-cp " + createArguments(classPath, ":") + " ";
@@ -94,7 +95,7 @@ public class JavaProcessJob extends ProcessJob {
}
}
- if (classPaths == null) {
+ if (classPaths == null || classPaths.isEmpty()) {
final File path = new File(getPath());
// File parent = path.getParentFile();
getLog().info(
diff --git a/azkaban-common/src/main/java/azkaban/jobExecutor/ProcessJob.java b/azkaban-common/src/main/java/azkaban/jobExecutor/ProcessJob.java
index 357249a..7f83608 100644
--- a/azkaban-common/src/main/java/azkaban/jobExecutor/ProcessJob.java
+++ b/azkaban-common/src/main/java/azkaban/jobExecutor/ProcessJob.java
@@ -198,7 +198,7 @@ public class ProcessJob extends AbstractProcessJob {
try {
commands = getCommandList();
} catch (final Exception e) {
- handleError("Job set up failed " + e.getCause(), e);
+ handleError("Job set up failed: " + e.getMessage(), e);
}
final long startMs = System.currentTimeMillis();
@@ -386,8 +386,8 @@ public class ProcessJob extends AbstractProcessJob {
}
/**
- * Changes permissions on file/directory so that the file/directory is owned by the user and
- * the group remains the azkaban service account name.
+ * Changes permissions on file/directory so that the file/directory is owned by the user and the
+ * group remains the azkaban service account name.
*
* Leverages execute-as-user with "root" as the user to run the command.
*
diff --git a/azkaban-common/src/test/java/azkaban/jobExecutor/JavaProcessJobTest.java b/azkaban-common/src/test/java/azkaban/jobExecutor/JavaProcessJobTest.java
index ccbbf62..37494aa 100644
--- a/azkaban-common/src/test/java/azkaban/jobExecutor/JavaProcessJobTest.java
+++ b/azkaban-common/src/test/java/azkaban/jobExecutor/JavaProcessJobTest.java
@@ -16,11 +16,15 @@
package azkaban.jobExecutor;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import azkaban.jobExecutor.utils.process.ProcessFailureException;
import azkaban.utils.Props;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.Properties;
+import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.junit.After;
import org.junit.AfterClass;
@@ -63,6 +67,7 @@ public class JavaProcessJobTest {
public TemporaryFolder temp = new TemporaryFolder();
private JavaProcessJob job = null;
private Props props = null;
+ private File workingDir;
@BeforeClass
public static void init() throws IOException {
@@ -95,11 +100,11 @@ public class JavaProcessJobTest {
@Before
public void setUp() throws IOException {
- final File workingDir = this.temp.newFolder("testJavaProcess");
+ this.workingDir = this.temp.newFolder("testJavaProcess");
// Initialize job
this.props = AllJobExecutorTests.setUpCommonProps();
- this.props.put(AbstractProcessJob.WORKING_DIR, workingDir.getCanonicalPath());
+ this.props.put(AbstractProcessJob.WORKING_DIR, this.workingDir.getCanonicalPath());
this.props.put("type", "java");
this.job = new JavaProcessJob("testJavaProcess", this.props, this.props, this.log);
@@ -122,6 +127,44 @@ public class JavaProcessJobTest {
}
@Test
+ public void noClassPath() throws Exception {
+ copyJarToJobDirectory();
+ this.props.put(JavaProcessJob.JAVA_CLASS, "azkaban.jobExecutor.WordCountLocal");
+ assertThatThrownBy(() -> this.job.run())
+ .isInstanceOf(RuntimeException.class)
+ .hasCauseInstanceOf(ProcessFailureException.class);
+ }
+
+ @Test
+ public void emptyClassPath() throws Exception {
+ copyJarToJobDirectory();
+ this.props.put(JavaProcessJob.JAVA_CLASS, "azkaban.jobExecutor.WordCountLocal");
+ this.props.put("classpath", "");
+ assertThatThrownBy(() -> this.job.run())
+ .isInstanceOf(RuntimeException.class)
+ .hasCauseInstanceOf(ProcessFailureException.class);
+ }
+
+ @Test
+ public void noClassPathNoJar() throws Exception {
+ this.props.put(JavaProcessJob.JAVA_CLASS, "azkaban.jobExecutor.WordCountLocal");
+ assertThatThrownBy(() -> this.job.run())
+ .isInstanceOf(Exception.class)
+ .hasMessageContaining("No classpath defined and no .jar files found")
+ .hasCauseInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void emptyClassPathNoJar() throws Exception {
+ this.props.put(JavaProcessJob.JAVA_CLASS, "azkaban.jobExecutor.WordCountLocal");
+ this.props.put("classpath", "");
+ assertThatThrownBy(() -> this.job.run())
+ .isInstanceOf(Exception.class)
+ .hasMessageContaining("No classpath defined and no .jar files found")
+ .hasCauseInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
public void testJavaJobHashmap() throws Exception {
// initialize the Props
this.props.put(JavaProcessJob.JAVA_CLASS,
@@ -147,4 +190,12 @@ public class JavaProcessJobTest {
Assert.assertTrue(true);
}
}
+
+ private void copyJarToJobDirectory() throws IOException {
+ // this jar doesn't really contain any class with a main() method
+ // so the job will fail - this is just so that javaprocess finds it and sets '-cp test.jar'
+ FileUtils.copyFileToDirectory(new File("src/test/resources/project/testfailure/test.jar"),
+ this.workingDir);
+ }
+
}