azkaban-developers

javaprocess classpath improvements (#1567) - Tests for

3/24/2019 2:59:07 AM

Details

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);
+  }
+
 }