Archive for the ‘Java’ Category

Java and command-tab fixed?

Tuesday, September 30th, 2008

I might be smokin’ crack, but I think that todays (September 30th, 2008) Java update from Apple finally fixed the command-tab issue. I haven’t verified it with different apps yet, but the ones I use regularly seem to be working as expected when you command-tab to them.

Restoring a SubVersion repository from an old backup

Monday, July 28th, 2008

I have recently gone through the exercise of restoring a medium sized SubVersion repository from an older backup and wanted to share my experience with everyone. First, the problem:

The problem

After you restore the older backup, if any work was performed between the last backup and when the repository crashed, the repository will be “older” than what developers have on their boxes. Here is an example:

  • Let’s say you have a backup from Monday evening
  • The repository crashed sometime Tuesday
  • There was work done during the day Monday

Now, let’s say there is a project A that looks like this:

  • The last change to the project was at revision 100 just before the repository crashed
  • The last change to the project from the backup was 80
  • Frank’s computer contains a checkout of the project at revision 85
  • Mary’s computer contains a checkout of the project at revision 100

This means that both Frank and Mary’s computers contain newer code than the repository, but not the latest code. Mary’s computer contains newer code than the repository, but might not be a complete snapshot of what version 100 was before the repository was corrupt. The reason why Mary’s computer might not be 100% correct is that Mary might have committed files to the repository but not performed a “svn update” prior to committing.

SubVersion is like CVS in that each file contains a version number. So, you might have a local checkout that contains version 100 for one file and 90 of another file. Therefore, you might be missing an updated version of the file from revision 93 when it was checked in.

Okay, now onto the fix:

The fix

Each developer’s computer must be analyzed before anything new is put into the repository. You must have a complete picture of the entire company, otherwise you might miss some changes. These changes can be merged in by hand from each developers machine, but this could be error prone and lengthy process. It is usually better to script out as much as possible.

Step 1

In order to determine the local “revision” of a project on a developers computer, you will need to look at each file in the checkout. You can run an ’svn stat’ on each file to determine the version number of that file. Write a script to output a file like this for each local checked out project on all developers machines:

src/java/foo.java: 90

The first part is the file and the second part is the revision of that file.

Next, once you have the complete list of revisions for all projects on all developer’s computers in the entire company, you can compare each file with the current revision in the restored repository to determine if the developer has a later version of a file than the repository. This should ignore all files that the developer has modified locally, but not committed.

This comparison will look like this:

Restored repository
src/java/foo.java: 80

Mary's checkout
src/java/foo.java: 90

Mary has a later version of foo.java!

You should script all of these comparisons out. If a developer doesn’t have later revisions than the repository or any locally modified files, they can safely take these steps:

  1. Make a backup of the local checkout
  2. Delete the local checkout
  3. Re-checkout the project
  4. Don’t do anything until the restore is complete

Step 2

The next step is to make a list of the revision that each file in the project was lasted changed on in the restored repository. This report will look like this:

build.xml: 10
src/java/main/foo.java: 16293
src/conf/main/logging.properties: 12093

Next, for each project, collect all of the revision reports from the previous step into a single location. These reports look like this:

frank-project-a-report.txt
build.xml: 10
src/java/main/foo.java: 16301
src/conf/main/logging.properties: 16405
mary-project-a-report.txt
build.xml: 10
src/java/main/foo.java: 16410
src/conf/main/logging.properties: 16321

Combine each of the developer reports into a global report that gives you the revision number for each file on every developers computer. Next, use this global developer report to determine whose computer contains the latest version for each file in the project. Based on the examples above, you can see that build.xml didn’t change recently enough to matter since the version in the repository is the same as the version on Frank’s and Mary’s computers. However, Frank made the most recent commit in revision 16405 to logging.properties and Mary made the most recent commit in revision 16410 to foo.java. Both of these files are more current that the repository and therefore need to be re-committed.

Step 3

Finally, setup a staging area that contains a copy of every checked out project from every developers computer who has a later revision than the repository (from step 1). This will be pretty large, but necessary. Based on the results from step 2, copy the latest version of each file over to a clean checkout of the project from the restored repository. Once you have all of the changes copied over for a single project, commit all of those files for that project back to TRUNK.

You should now have a fully restored repository based on the files from various developers computers.

Java, SSL and self-signed certificates

Saturday, July 26th, 2008

Depending on the API you are using or how you are using SSL, you might have received an error stating that the certificate is invalid, not path to certificate, invalid certificate chain, no chain found, PKIK error, or something similar. This occurs when the certificate is self-signed or signed by an authority that has not been verified by the JDK you are using.

There is a simple way to handle this for self-signed certificates:

  1. Open Firefox
  2. Go to the site that is using SSL (i.e. https://svn.example.com)
  3. Click on the lock down in the lower right corner of the browser window
  4. Click the “View certificate” button
  5. Click the details tab
  6. Click the export button to export the certificate
  7. Save the certificate in x.509 (PEM) format
  8. Go to a command prompt
  9. Add the certificate to the keystore

Here is the command to add the certificate to your global keystore:

*nix

$ keytool -import -keystore $JAVA_HOME/lib/security/cacerts -file <your-pem-export>
-alias <anything>

Windows

c:\> keytool -import -keystore %JAVA_HOME%/lib/security/cacerts -file <your-pem-export>
-alias <anything>

How generics can pay dividends

Thursday, June 19th, 2008

One of the things I’ve noticed lately are some discussions regarding how cumbersome generics can be. They can take time to get right or figure out and some folks have gone as far as to stipulate that if you can’t do it without generics then something is borked.

While reading a lot of this, I’ve also being writing the MVC for JCatapult. I’m a big generic fan and I’m on the opposite side of the fence from a lot of the folks that have been generic bashing lately. I think that if you can’t get rid of all the unchecked warnings and use generics everywhere, you’re probably not doing something correctly. Of course this isn’t always possible, but I try to get there.

I’ve done some Rails work and some Grails work over the past few years. When it comes to dynamic languages, you are almost always getting the incoming HTTP request parameters into your actions as simple Strings. Therefore, if you want to do some math or pass them along, you might have to convert them a bit. This is how most first generation Java MVCs also worked. A few more modern MVCs did it a bit better. Struts2 for example uses OGNL and can populate JavaBeans with the values using a specific syntax like this:

user.address.city

These MVCs also go so far as to provide type conversion support. If you have an action like this:

public class MyAction {
  private int age;

  public int getAge() {...}
  public void setAge(int age) {...}
}

you can pass in the age parameter and the MVC will convert it to an integer. Most of these also handle type conversion failures decently well. Here is an example URL:

http://www.example.com/my-action?age=42

In many cases, these more modern MVCs will also instantiate classes for you and set them into JavaBean properties. The user.address.city example might map to this code (getters and setters have been left out):

public class MyAction {
  private User user;
}

public class User {
  private Address address;
}

public class Address {
  private String city;
}

Since the MyAction member variable named user is null, the MVC will instantiate the User class and set it into the MyAction class. Most of these MVCs hit a limitation when it comes to complex object modeling that uses collections. One of the main reasons is that from a legacy perspective (i.e.JDK 1.4) it was impossible to know what types of objects were being stored in a collection. Here’s an example:

public class MyAction {
  private User user;
}

public class User {
  private Map addresses;
}

public class Address {
  private String city;
}

There was no way for the MVC to understand that the Map contains addresses and that the keys are Strings like home and work. However, if you changed this code like this:

public class MyAction {
  private User user;
}

public class User {
  private Map<String, Address> addresses;
}

public class Address {
  private String city;
}

some modern MVCs can figure it out. The issue is that they don’t do a good job and many times fail horribly. So, I decided for JCatapult to fix this. JCatapult supports all flavors of generic programming when it is converting HTTP request parameters into objects. It supports arrays, Collections, Lists, Sets, SortedSets, Queues, and Maps. It also handles nested collections like:

Map > crazyAddresses;

It also supports handling multiple request parameters of the same name and converting them into generic collections. Let’s say you want to pass in a list of IDs using checkboxes like this:

<input type="checkbox" name="ids" value="1"/>Choice 1
<input type="checkbox" name="ids" value="2"/>Choice 2
<input type="checkbox" name="ids" value="3"/>Choice 3

These will come into the Servlet container as a single parameter that is an array of Strings. Your action can then look like this:

public class MyAction {
  private Set ids;
}

You could also nest these IDs inside another class. The nice thing about this is that using generics can reduce the amount of code you have to write to get access to a Set of Integers.

So, the moral of the blog post, generics are good things and can reduce overhead considerably.

Lenovo X300 is a BIT over-price

Friday, April 11th, 2008

Found this funny. Looks like Lenovo has some issues in their pricing application today. I was planning on purchasing an X300 at some point, but with their new price tag of $11,000, I just don’t think I can afford it. Haha

Lenovo Crazy Price