re: Why Do Java Developers Like to Make Things So Hard?

James Turner, a committer on the Struts project and a Senior Editor at LinuxWorld Magazine, wrote an article for the magazine a couple days ago that caught the eye of a couple bloggers (Beattie, Colburn). There are a bunch of interesting comments on Russell’s blog in reference to his commens on the article. Notable among the comments:

… the difference between “Computer Science” and “Software Engineering” – the former being concerned with fundamental constructs and abstractions, the latter being concerned with putting them together into useful things — sort of like the distinction between Physics and Mechanical Engineering (or perhaps Civil Engineering), although much the way Computer Science is an abuse of the term Science, Software Engineering mistreats the term Engineering…. CS gives us things like Boyer-Moore search, Bloom filters, and LZ compression; SE gives us things like Apache and Google

— a link to an article that Joel Spolsky wrote back in 2001 (Don’t Let Architecture Astronauts Scare You)
— Carlos Perez chewed on the usuability of API’s for a bit (Even More Wisdom on Designing Usable APIs), which I found interesting because he talks about how Microsoft actually has done research into the usability of API’s (cognitive dimensions framework).

I think Russell misses the point; he brings up Bill Day using a PHP weblog solution as proof that Java is too hard. I use Moveable Type for my weblog, but that doesn’t mean I’d write a banking application in Perl or PHP. With that said, I completely agree with Mr. Turner’s assessment of the Bouncy Castle Crypto API. I tried to use it for the exact same thing that James did last week and I never did get it working. I bet we both would be using the Bouncy Castle API had they taken a couple hours to write a short and sweet introduction to the API.

External Applications & Java’s Runtime.exec()

Follow up to the last entry on Java & PGP, I found this article on Java World entitled “When Runtime.exec() won’t” that made a couple of great points. First, in reference to the 2 methods available to developers working with the Process class (waitFor() and exitValue()), he said:

If an external process has not yet completed, the exitValue() method will throw an IllegalThreadStateException; that’s why this program failed. While the documentation states this fact, why can’t this method wait until it can give a valid answer?

A more thorough look at the methods available in the Process class reveals a waitFor() method that does precisely that. In fact, waitFor() also returns the exit value, which means that you would not use exitValue() and waitFor() in conjunction with each other, but rather would choose one or the other. The only possible time you would use exitValue() instead of waitFor() would be when you don’t want your program to block waiting on an external process that may never complete. Instead of using the waitFor() method, I would prefer passing a boolean parameter called waitFor into the exitValue() method to determine whether or not the current thread should wait. A boolean would be more beneficial because exitValue() is a more appropriate name for this method, and it isn’t necessary for two methods to perform the same function under different conditions. Such simple condition discrimination is the domain of an input parameter.

Does the above mean that if you want to execute or invoke a long running external process using Java, you should simply call the exitValue() method on the process immediately after calling Runtime.exec() and then ignore the IllegalThreadStateException exception that gets thrown?

Second, he mentions:

One final pitfall to cover with Runtime.exec() is mistakenly assuming that exec() accepts any String that your command line (or shell) accepts. Runtime.exec() is much more limited and not cross-platform. This pitfall is caused by users attempting to use the exec() method to accept a single String as a command line would. The confusion may be due to the fact that command is the parameter name for the exec() method. Thus, the programmer incorrectly associates the parameter command with anything that he or she can type on a command line, instead of associating it with a single program and its arguments.

The call to the PGP executable I wrote a couple days ago does work, but it could be improved by breaking up the program (pgp.exe) from the arguments (-eatw c:\pgp6.5.8\tempfile.txt aaron.s.johnson@gmail.com) like this:

String[] args = {"c:\\pgp6.5.8\\pgp", "-eatw", "c:\\pgp6.5.8\\tempfile.txt", "aaron.s.johnson@gmail.com"};
Process process = rt.exec(args);

Other links:
Java World: When Runtime.exec() won’t
Mountain Storm:Java’s Runtime.exec() and External Applications

Java & PGP

One of the Java projects I’m working on required that the application encrypted certain pieces of information (not files, but strings) using PGP, and from what I can tell, there aren’t a whole lot of libraries and/or examples out there. The one I saw mentioned most frequently was the Bouncy Castle Crypto API, but in the short time that I looked through the documentation and the examples (org.bouncycastle.openpgp.examples), I saw nothing that looked like it would help me. So I downloaded PGP 6.5.8 (the version we’ve standardized on at work) from pgpi.org and hacked away at a version that works from the command line. Here’s the result:

String information = "The random text information I want to encrypt.";
String filename = "tempfile.txt";
// path to where I have pgp installed
String directory = "c:\\pgp6.5.8\\";
// my pgp key
String pgpkey = "aaron.s.johnson@gmail.com";
// create a file and write the string to it
File outputfile = new File(directory + filename);
FileWriter out = new FileWriter(outputfile);
out.write(information.toCharArray());
out.close();
// get a runtime object
Runtime rt = Runtime.getRuntime();
// execute pgp from the command line
// e=encrypt a=ascii t=text file w=wipe the file
Process process = rt.exec(directory + "pgp -eatw " + directory + filename + " " + pgpkey);
// wait for the execution to end
process.waitFor();
// read the armored ASCII file
File inputfile = new File(directory + filename + ".asc");
BufferedReader isr = new BufferedReader(new FileReader(inputfile));
StringBuffer decrypted = new StringBuffer();
String line = "";
while ((line = isr.readLine()) != null) {
  decrypted.append(line + "\n");
}
// close the reader
isr.close();
inputfile.delete();
// print out the encrypted string for kicks
System.out.println(decrypted.toString());

A quick summary. The PGP executable assumes that you’re encrypting and decrypting files, so I first take the string that I want to encrypt and write it to a text file using the File and FileWriter classes. Then I use the Runtime class to execute PGP from the command line, which encrypts the file and deletes the original plain text unencrypted file that I just created. I call the waitFor() method on the Process to make sure that the execution is complete, and then I read in resulting armored ASCII file using the File, FileReader and BufferedReader classes. Finally, I delete the armored ASCII file. Obviously in production you’d want to use a unique name for the file so that you don’t overwrite or delete a file that another thread just created. Other than that, are there any issues that I missed?

Scripting in ASP with Java

I’m working on a project right now that involves a store written in Java using Struts and a sister site written in ASP. One of the features of the store requires that the sister site use some logic written in Java, which you might think is impossible. Turns out (doesn’t it always?) that you can quite easily use simple Java methods and objects within ASP from VBScript. I found two articles (and really only 2) that introduced the use of a simple Java class from ASP (which you can read here and here). Here’s a Hello World example:

package org.mycompany;
public class TestClass {
 public String sayHello(String name) {
   return "Hello " + name;
 }
}

compile this and then you save the resulting class file to:
%Win%/Java/TrustLib/%package%/%classname%.class
So the above example would result in a file saved as:
%Win%/Java/TrustLib/org/mycompany/TestClass.class
From ASP, you can then use the following syntax:

Dim obj
set obj = GetObject("java:org.comcompany.TestClass")
result = obj.sayHello("Aaron Johnson");
Response.Write(result)
set obj = nothing

Couple of items of note:

a) the use of what Microsoft calls a “Java Moniker” allows you to use a Java class without first registering it with the system, which is nice (so you got that going for ya),

b) just like a servlet container, if you make changes to the Java class file while the application is running, you must restart the container, which in this case is IIS,

c) you must (as I mentioned before) make sure to place the compiled class file in the appropriately named subdirectory of %Win%/Java/TrustLib/, where %Win% is usually C:\windows\ or C:\winnt\,

d) you can’t use static methods in your Java class if you want to be able to call those methods from VBScript. It appears (from my quick attempts) that the VBScript engine first creates an object using the default constructor and then calls the given method on that instance. Modifiying the method to be static resulted in a runtime error, and finally

e) your code must work in the Microsoft JVM (I think), which isn’t being supported past September 2004.

Using iText PDF & ColdFusion

Mike Steele sent me an email in reference to an article I wrote for the ColdFusion Developer’s Journal a year or so ago. In the email, he mentions that he is trying to use the iText Java-PDF library with ColdFusion MX:

… The getInstance method is static and according to your July 2003 CFDJ article, you can’t instantiate an object in CF this way.

In the article I said this:

… using the CreateObject() function does not get you access to an instance of an object. In order to access a Java object, you must either a) first call the CreateObject() method and then the init() method, which in the above example, maps to the default constructor in Java, or b) call any nonstatic method on the object, which causes ColdFusion to then instantiate the object for you.

I guess this statement needs to be amended to include a third possible, but not always valid solution: call a static method on the class which returns an instance of the object in question. In this case the API designer included a static method ‘getInstance()’ on the PDFWriter class. Given that news, you can take the quick example that the author of the iText library gives here to create a PDF in a snap using ColdFusion:

<cfscript>
// create a 'Document' object
document = CreateObject("java", "com.lowagie.text.Document");
document.init();
// get an outputstream for the PDF Writer
fileIO = CreateObject("java", "java.io.FileOutputStream");
// call the constructor, pass the location where you want
// the pdf to be created
fileIO.init("C:\myhost.com\somedir\test.pdf");
// get a PDF Writer var
writer = CreateObject("java", "com.lowagie.text.pdf.PdfWriter");
// call the static 'getInstance' factory method
writer.getInstance(document, fileIO);
// open the document
document.open();
// create a new paragraph
paragraph = CreateObject("java", "com.lowagie.text.Paragraph");
paragraph.init("Hello World!");
// add the paragraph
document.add(paragraph);
// close the document (PDF Writer is listening and will automatically
// create the PDF for us
document.close();
</cfscript>

Copy that code into a cfml page and make sure you’ve downloaded the iText jar to the /lib/ directory of your ColdFusion server and you should be able to create PDF’s in a jiffy!

Full source code available here.

Cool URIs don’t change…

Tim Berners Lee wrote this essay years ago (1998 in fact), and it’s a good one. In short, the message is this:

… many, many things can change and your URIs can and should stay the same. They only can if you think about how you design them.

Why bring it up now? I got an email from Jens Anders Bakke a couple weeks ago, in it he asked what “… we regular users can do about …” the fact that Macromedia Forums was recently moved (from http://webforums.macromedia.com/ to http://www.macromedia.com/support/forums/). He brought up the fact that alot of people link to the forums when discussing a bug or a problem and because of the move, none of those links that matter (ie: the links that actually point to something besides the forums homepage) work (I’ve done it myself in multiple places). In fact, Google can find about 7,400 links to webforums.macromedia.com. Some of those don’t work anymore. It’s a small thing, but seriously, how hard would it have been to add a couple lines of mod_write kung foo to your Apache conf?

IE Greeting Card Exploit Post Mortem

From the interesting people list back a couple weeks ago, an analysis of an E-card hijack spam.

I downloaded a.exe out of curiousity, and have been analysing it. The file contains a number of very interesting strings, which make it quite obvious that this program attempts to hijack the user’s personal login information as they log in to various popular Internet banking services.

This article scared me into using Firefox.

Struts & Java Tips: Issue #1

The “Issue” thing is a joke. I don’t know what else to call this. I’ve been thoroughly enjoying the last couple weeks I’ve been spending with Struts, I learn something new everyday. One of the things that I happened upon today was a tip from Ted Husted buried deep in his overview of Struts design patterns and strategies page (a great resource btw) which suggests using the LabelValueBean as a core value object class:

When a good number of drop-down controls are being used, standardize on the LabelValueBean object provided in the Struts example. This is an easy way to create both the Label and Value collections the Struts options tag expects.

One of the things that I really like about Struts is the strict separation between presentation, business logic and model. I’ll spend a couple hours writing Action classes, some ActionForms, maybe a utility class or two and then switch over to implementing the JSP using JSTL (and very little time working with the model since I’m using Hibernate, but that’s anothe post). I’m never writing directly to the response with the Action classes, the ActionForms, etc… all of the presentation is done using JSP. The JSP’s become so much more simple. The first couple sites I wrote using servlets & JSP were (and for the most part still are) a complete mishmash of JSP’s with embedded SQL, buggy tags, and scriplets. With Struts, for the most part you don’t have to use scriptlets, you’re left with clean template-like code that the Actions provide data for.

So now I’ve come full circle. The LabelValueBean is an example of the data that the Actions provide to the JSP’s and they become a very useful tool when you’ve got to populate month select boxes, year select boxes, state select boxes, etc., etc. This morning I started out by creating a Month bean (which had only label and value properties), a Year bean (with only label and properties) , and so on… a definite trend. I created a factory class that handled the creation of those beans and returned a collection to the Action instance, which then put the collection into a request attribute for retrieval by the JSP. The code looked something like this:

// code in the factory class
public static Collection getYears() {
 Calendar c = Calendar.getInstance();
 Collection years = new ArrayList();
 int year = c.get(Calendar.YEAR);
 int endyear = year + 10;
 for (int i=year; i<endyear; i++) {
  years.add(new Year(String.valueOf(i), String.valueOf(i)));
 }
 return years;
}

// code in the Action class
Collection years = YearFactory.getYears();
request.setAttribute("years", years);

// code in the JSP
<html:select property="payment_year">
<html:options collection="years" property="value" labelProperty="label" />
</html:select>

There are a couple things in the above code that can be improved. First, like I mentioned before, I should have used the LabelValueBean instead of creating my own Year bean. Because the presentation is completely independent of the business logic, I need only change a single line of code (and an import for you sticklers out there). This:

  years.add(new Year(String.valueOf(i), String.valueOf(i)));

becomes this:

  years.add(new LabelValueBean(String.valueOf(i), String.valueOf(i)));

Next (at this point I should probably mention that I’ve been poring over Effective Java while exercising at night), performance savvy programmers probably winced at the number of unnecessary objects (Item #4) I’ll end up creating with the getYears() method. What I should have done instead was create the years collection and collection elements in a static constructor and store the result as a private static, returning the result when the getYears() method is called. So the above example is refactored to this:

private static Collection years = new ArrayList();
 static {
  Calendar c = Calendar.getInstance();
  int year = c.get(Calendar.YEAR);
  int endyear = year + 10;
  for (int i=year; i<endyear; i++) {
   years.add(new LabelValueBean(String.valueOf(i), String.valueOf(i)));
  }
 }
public static Collection getYears() {
 return years;
}

Finally, a small touch that I learned (and am attempting to use faithfully) from Item #34, “Refer to objects by their interfaces.” In the code examples above I could have declared the return type and the private static to be an ArrayList:

// private static declaration
private static ArrayList years = new ArrayList();
// factory method
public static ArrayList getYears() {

Changing the implementation from an ArrayList to a Vector would have required changes to any of the classes that use this factory, which makes my program less flexible. Instead, using the Collection interface, my program becomes easier to use and to modify:

private static Collection years = new ArrayList();
// could also be this with no changes to the public API
private static Collection years = new Vector();

I’m always interested in your feedback! Thanks for listening.

Web Server Log Parser

From Dominic @ fusetalk, the IIS Log Parser tool:

Log Parser 2.0 is a powerful, versatile tool that makes it possible to run SQL-like queries against log files of almost any format and produce the desired information either on the screen, in a file of any desired format or into a SQL database. Log Parser is available as a command-line tool and as a set of scriptable COM objects.

Related:

Forensic Log Parsing with Microsoft’s LogParser

Tomcat Session Replication/Clustering

I’m considering whether or not to use the new session clustering capabilities of Tomcat 5. Unfortunately there isn’t much information out there on the subject. I found a short mention in this “What’s New in Tomcat 5” article on OnJava and a relatively thorough article on the Tomcat site “Clustering/Session Replication How-To“. Is there anyone out that a) has implemented it and can offer some validation that it works as advertised or b) that has more information beyond what is in the above mentioned articles?

I’m specifically interested in opinions on:

a) Beyond the obvious, what are the implications of using the ‘useDirtyFlag’ in server.xml? How much does it affect performance? Which did you decide to use and why? The comments in server.xml provide the best description of the ‘useDirtyFlag’ I’ve seen yet. For those who haven’t peeked:

true means that we only replicate a session after setAttribute,removeAttribute has been called.
false means to replicate the session after each request.
false means that replication would work for the following piece of code:
<%
HashMap map = (HashMap)session.getAttribute(“map”);
map.put(“key”,”value”);
%>

Setting ‘useDirtyFlag’ to false sounds like it would cause a ton of extra work. Setting it to true just means you have to be more intentional when you want to save data to the session. Thoughts?
b) Which persistence mechanism did you choose (PersistenceManager, JDBCManager, SimpleTcpCluster)?

Also, does anyone know if the Tomcat book that Oreilly pushed out in June of last year covers Tomcat 5? The article above seems to imply that it does, but I looked at a hardcopy at Barnes & Noble and that only covers Tomcat 4.x.