process builder to run multi-platform postgres import

We saw how to clone a postgresql database for testing cleanly in an earlier blog post. The next step is to do so from Java so it can be part of an integration test.

How to run each of 4 DDLs:
Running a DDL file is easy which is good since we have four of them.

importDdlOrSqlFile("initialJForumSchema.ddl");
importDdlOrSqlFile("javaranchCustom.ddl");
importDdlOrSqlFile("users.ddl");
importDdlOrSqlFile("databaseChangesAfterMostRecentInstall.txt");

Ok. So maybe it is easy because all the functional code is in another method.

What is Process Builder?

Process Builder was introduced in Java 5.  The Runtime.exec JavaDoc says

ProcessBuilder.start() is now the preferred way to start a process with a modified environment.

Since I need to set two system properties, this is perfect.

How to create the Process Builder

On Windows, you just pass the command to run at the DOS prompt.  The actual command was shown in the closing a postgresql database blog post.  On UNIX/Mac/etc, you need to create a new shell and pass the command that way.  Luckily, it is easy to check for a Windows operating system:


private ProcessBuilder createProcessBuilder(String command) {
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
return new ProcessBuilder(command);
}
return new ProcessBuilder("sh", "-c", command);
}

How to set system properties

I need to set the user id and password as operating system properties so postgresql doesn’t prompt for them interactively.  Using process builder, I can call environment() to get a map of environmental properties for my process.  Then setting them is simply a matter of setting them in the map.


private void importDdlOrSqlFile(String fileName) throws Exception {
String command = importToPostgresCommand(fileName);
System.out.println(command);
ProcessBuilder processBuilder = createProcessBuilder(command);
Map<String, String> env = processBuilder.environment();
env.put("PGUSER",   SystemGlobals.getValue(DATABASE_CONNECTION_USERNAME));
env.put("PGPASSWORD",  SystemGlobals.getValue(DATABASE_CONNECTION_PASSWORD));
processBuilder.redirectErrorStream(true);
runProcess(fileName, processBuilder);
}

How to run the Process Builder

All ready to run it!   start() kicks it off.  I think read all the output from the commands via the process builder’s input stream and output it to the console.  (I do this since many commands are run and the developer can see what it is up to.)  Finally, I check the error code.  After all, if the database didn’t get created properly, there isn’t much point in having a whole pile of failing tests.


private void runProcess(String fileName, ProcessBuilder processBuilder) throws IOException, InterruptedException {
Process proc = processBuilder.start();
Scanner scanner = new Scanner(proc.getInputStream());
while (scanner.hasNext()) {
String line = scanner.nextLine();
System.out.println("importing data: " + line);
}
int exitVal = proc.waitFor();
System.out.println("Completed loading " + fileName + " Exit value: " + exitVal);
if (exitVal != 0) {
System.out.println("Please fix error in database script and re-run.");
System.exit(1);
}

}

Testing

This code was tested on multiple developer’s machines including Windows and Mac.

junit suite wide setup (not @BeforeClass)

Problem

How do I run setup/teardown for my whole suite, not just one class/test?

Impact of Problem

JUnit offers @Before to run a method before each test and @BeforeClass to run a method once before a class.  For a small suite, @BeforeClass may be enough.  For a large integration test suite, setting up the database is a common task that should be done once for scores of tests.  Having everything in one class is not optimal.  Nor is manually listing all the tests.

Requirements

  1. Continue being able to use ClasspathSuite to gather tests in a subdirectory at runtime.
  2. Run a method before the first of these tests is run
  3. Run a method after the last of these tests is run
  4. Take advantage of JUnit’s runner for running all the tests

Solution

package com.javaranch.test.functional;

import static org.junit.extensions.cpsuite.SuiteType.*;

import org.junit.extensions.cpsuite.*;
import org.junit.extensions.cpsuite.ClasspathSuite.*;
import org.junit.runner.*;

// use cpsuite to dynamically list out tests
@RunWith(ClasspathSuite.class)
@ClassnameFilters( { "com.javaranch.*test.*Test", "net.jforum.*test.*Test" })
// include in case have a parameterized test case
@SuiteTypes( { RUN_WITH_CLASSES, TEST_CLASSES, JUNIT38_TEST_CLASSES })
public class All_JForum_Functional_Tests {
public static void main(String[] args) throws Exception {
setUp();
JUnitCore.main("com.javaranch.test.functional.All_JForum_Functional_Tests");
tearDown();
}

private static void setUp() {
// create the database
}

private static void tearDown() {
// destroy the database
}
}

If you’ve been reading my blog, you’ll know I am doing this to integration test the back end of JavaRanch’s JForum install.  I started by cloning a database and have now moved on to the integration test framework.  Next I will describe the actual database setup.

cropping video fast for dummies

I wanted to edit a three minute video down to less than 15 seconds.  I’ve never done this before and don’t have any special software.  And I needed to do it in an hour.  What to do?  What to do?

Why the urgency?

I was giving an Ignite style presentation on Stuy Pulse’s journey this season (FIRST Robotics team #694).  Since Ignite slides are 15 seconds in length, I originally decided to go with a static picture.  The night before my presentation, an alum of the team sent out a really good 3 minute video.  I thought it would make my presentation much better to include one 15 second “slide” of video.

Where I started

The original video is 3 minutes and 36 seconds.  I decided it would be nice to show kicking a goal in autonomous (no humans involved), driving over the bump/ramp and hanging.

How I did it

  1. Note that I have Windows Movie Maker on my machine which I can use for basic editing.  The shortcut disappeared, but I can create a new one pointing to C:\Program Files\Movie Maker\moviemk.exe.
  2. Download the video using ClipNabber so I would have a copy of it locally.  This downloaded the clip as an .mp4 file.
  3. Since Windows media player doesn’t support .mp4 files, I needed to convert it to another format.  I downloaded the free QuickMedia converter which was a 45 MB file.  Thanks to the Microsoft forum for the idea.  Converting the file from .mp4 to .wmv took 2 minutes.
  4. In Windows Movie Maker, import the .wmv file.
  5. Play the video using the navigation icons to split the video into pieces.  The relevant buttons were:
    1. Play – to start it
    2. Split – to create a clip boundary (start of end the clip)
    3. Previous/Next frame for precision
  6. Drag the three completed clips to the storyboard
  7. File > Save movie file

How did it work?

This process was good for some rough editing.  I met my goal of having a clip under 15 seconds showing these three things.  For “real” editing, you’d want a better product of course.

The final product

The completed video does show what I wanted.  I didn’t edit out the sound because I knew the speakers would be off during my presentation.  The words that went with that slide were:

red al-liance! ,<clap><clap>, <clap><clap><clap>

blue al-liance! ,<clap><clap>, <clap><clap><clap>

hang! hang! hang!

if 694 wins this, we go to nationals!

<pause>

Then the next slide is a screenshot of the congratulations message; the one at the beginning of this post.

And yes, I got permission from the video creator to do this and blog about it.