Hanumant’s Java Workshop

Turbo Charged Java Development!

Continuous Integration using Perforce and Hudson

A little background

The basic premise of Continuous Integration is simple. You want to know, as soon as possible, whether the the code that you just checked into the source control is breaking anything or not. So, as soon as you checkin your code, the build server gets all your latest code and all other code that depends on your code and builds all the affected projects. Compilation error or failure of any of the test cases should raise an alarm (i.e. send an email to the group).

We are using Perforce as the source control and Hudson as our build server. All of our projects are Mavenized.  We have set up a trigger on our Depo in Perforce such that whenever anything is committed to our Depo, it makes an HTTP request with parameters such as the changelist number, clientspec, and userid.

When I joined this project, I inherited a small but a very smartly written servlet that handled the HTTP requests made by Perforce upon any commit. This servlet would:

  1. get the changelist number (from the HTTP parameters)
  2. get the list of files committed under that changelist by executing the perforce client (p4.exe): p4.exe -p p4server:port -u p4userid -P p4passwd fstat @1234,@1234
  3. Identify the projects affected by these files, and
  4. Kickoff Hudson build projects to do the build(s).

The catch was that this small code was written in Groovy (apparantly, it was small because it was written in Groovy) and nobody knew Groovy in our team. All of our projects are in Java and it doesn’t make sense to add a completely new programming language to the mix just to save a about 50 lines of code, when there is 1000s of lines of Java code base lying around.  So we wanted to convert this Groovy servlet into Java.

This post is about the problem that I faced in step 2 above (retrieving file names committed under a given change list id).

The problem

Even after setting the userid and password flags ( -u and -P) while calling p4.exe and even after setting P4USER and P4PASSWD environment variable, Perforce would not return any data. It would just send back an error message saying: “P4PASSWD is wrong or is unset.”

As it turns out, for some reason, you need first execute p4 login command before calling the p4 fstat command. And p4 client does not accept the password provided in the -P flag or P4PASSWD env variable. When you call p4 login, it asks for the password and waits on the stdin for the user to enter the password. Obviously, this is no good for the continuous integration. This process must execute without any manual intervention.

The solution

The following is the code snippet that did the trick for me.

//the following code is executed once to login
StringBuilder sb = new StringBuilder();
String loginCmd = "p4 -u " + this.userid + " -P " + this.passwd + " -p " + this.host + " login";

Runtime runtime = Runtime.getRuntime();
Process p = runtime.exec(loginCmd);
OutputStream os = p.getOutputStream();
int returncode = p.waitFor();
getOutput(stringBuilder, p.getInputStream()); 

if (returncode != 0) {
   throw new Exception("Problem in login. Return code: " + returncode + " Output:" + sb);


//In another method that gets the fstat output for a given changelist
Runtime runtime = Runtime.getRuntime();
String fstatCmd = "p4 fstat @" + changeListId + ",@" + changeListId;
Process p = runtime.exec(fstatCmd);
getOutput(sb, p.getInputStream());
int returncode = p.waitFor();
if (returncode != 0) {
      throw new Exception("Problem in running fstat. Return code: " + returncode + " Output:" + sb);



June 19, 2010 - Posted by | Java

1 Comment »

  1. Store the password in the environment variable P4PASSWD and then do a echo $P4PASSWD | p4 login. This will not prompt for your password and also it will be stored in the build server which I assume is secure.

    Comment by Anand Parthasarathy | October 14, 2013 | Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: