Tom's Blog
Rise of the Scripting Language
Published by Tom |
March 19, 2005 07:50 PM EST |
Are the scripting languages threatening Java?
A posting Friday on TheServerSide defending Java against Ruby on Rails made me realize that some Java programmers seem to be feeling threatened by Ruby and its Rails framework. The concern seems to be Ruby, or another scripting languages like PHP, makes developing web applications easier than using Java and one of its many web frameworks. The result being Java will start to die out and really will become the next COBOL.
Granted, there's a lot of hype right now about Ruby and Rails. We all read or heard about the article in January on the O'Reilly ONLamp web site by Curt Hibbs saying Ruby on Rails will let you develop a web application 10 times faster than using Java. That article seemed to strike a chord among Java developers. A lot of blogs have been discussing RoR and why it's the best way to go for developing web applications, or a big step backward for separation of concerns and good design, depending on whom you read.
And there's even been recent hype about PHP as a fast way to develop web applications. IBM last month, announced it will work on products to bring the "do it yourself" simplicity of PHP to products like Zend Core for IBM. The headline on one story proclaimed "IBM Bets PHP Is Open Source's Next Big Thing." IBM accompanied its announcement with a new developerWorks section devoted to all things PHP. This month, IBM developerWorks announced new blogs, by the likes of Sam Ruby, focusing on the benefits of PHP.
Does this mean Java is on the way out for developing web applications? Who knows? But why worry? New languages and new web frameworks will have to prove themselves. They're not going to steamroll over Java without some real projects proving their mettle over Java in the long term.
I do have a concern that some software development managers, in their quest for Cheaper, Faster, Lighter software, might fall for the hype of the scripting language du jour and hire inexperienced developers ("Hey, they're right out of college but they can program in PHP!") to write web applications in PHP or Perl because they've heard these languages will result in faster delivery. The result could indeed be fast delivery -- of horrendously complex, intertwined, unmaintainable code.
But how is that any different than hiring an inexperienced Java developer to do the same thing? I've seen a lot of inexpensively developed Java code that was horrendously complex, tightly coupled and expensive to enhance and maintain. (OK, there is a difference. In the latter case, I can get hired to come in and fix it at a nice rate.)
If the scripting languages and their frameworks like Ruby on Rails really do make developing web applications easier, sign me up. Ruby seems like an elegant, expressive language that allows for good object-oriented design. Exaggerated claims about a language or framework are no reason to dismiss it. If features of Ruby or Rails really make developing software easier, faster and more maintainable, Java and its frameworks eventually will adopt similar features. And if they don't, Java deserves to fade.
I'm not worried about Java fading soon. Java has been evolving since it began, learning from other languages and frameworks (even .NET). The EJB remote-object overkill was solved in EJB 2.0. Web services got easier to develop in J2EE 1.4. Annotations were added in JDK 5 and will be expanded in J2EE 5. Object-relational mapping is supposed to get better with EJB 3.0.
But what makes me believe Ruby, Python and PHP won't kill Java is that they haven't been able to do it in almost a decade. Object-oriented scripting languages, even Ruby, have been around for years. Most predate Java. If they were so uber-language powerful, why does Java (currently, at least) enjoy such a large developer and CTO mind share? What I think we're seeing in the Rise of the Scripting Language is that Java is overkill for a lot of projects. Just like we all accepted a couple of years ago that EJB is overkill for a lot of projects. The interest in scripting languages could be a trend similar to the growing interest in Spring and Hibernate to help us simplify our applications.
The interest in scripting languages among Java developers actually seemed to start a few years ago. I remember hearing Bruce Eckel in 2001, saying how Python, with its OO features and dynamic typing, allow him to write software faster and more elegantly. He said in an interview on Artima developer that:
I feel Python was designed for the person who is actually doing the programming, to maximize their productivity. And that just makes me feel warm and fuzzy all over.Since about 2000, Dave Thomas has been saying how Ruby does the same for him. Here's an excerpt from an article he wrote for Linux Magazine in September, 2002:
Ruby is concise (like Python), fully object-oriented (like SmallTalk), and powerful (like Perl). In addition, Ruby is a remarkably capable language for building Internet applications. Ruby's libraries and built-in networking support make networked applications (such as email clients, SOAP servers, and distributed processing) easy to write and easy to maintain and extend.But the interest in scripting languages among Java developers really seemed to begin in the past few months with all the talk about Ruby on Rails. It seemed to start with Curt Hibbs's O'Reilly ONLamp article, the one in which he said:
What would you think if I told you that you could develop a web application at least ten times faster with Rails than you could with a typical Java framework? You can--without making any sacrifices in the quality of your application!The next month, Bruce Tate said in a February blog that Ruby on Rails "is beautiful, simple, and has a little bit of magic to it." He said he loves Ruby.
The Rails lovefest hasn't gone by without some cricism. JavaServer Faces expert David Geary countered Hibbs's claim that Ruby on Rails beats Java hands down:
...ROR is no match for a Java-based web app six pack of JSF-Shale-Tiles-SiteMesh-Hibernate-Spring .... I'm not going to use the default views generated by ROR (nobody is, except for simple UI mockups) and implementing my own views in ROR looks mighty ugly to me. And am I going to just throw away the incredibly rich collection of open-source Java software, like JSF, Tiles and SiteMesh? No way. ... [Y]ou take this ROR koolaid. I'll stick with the JSF flavor.Still, after getting an email from Bruce Tate, who raved to him about Ruby on Rails, Geary responded last week in his blog that he would take a closer look at Ruby on Rails before criticizing further.
I'm going to bet that the use of scripting languages like Ruby, and scripting-language based frameworks like Ruby on Rails, will increase in the coming years. Still, I don't think Java will fade as a result. I think the increase in scripting languages will help developers refine their decisions on where the power or maturity of Java is needed, and where it's not.
And by the way, where's Groovy (JSR 241)? Last year, I heard from a developer that he's several times more productive writing in Groovy than Java, and had several thousand lines of Groovy code under his belt to bolster his comparison. Yet I don't hear developers talking about Groovy to the same level as other scripting languages. Maybe once Groovy reaches its 1.0 milestone, we'll start to hear how Groovy can make us 10 times more productive as developers.
Saturday March 19, 2005 Permalink
Comments [12]
Using Java shutdown hooks to process records cleanly
Published by Tom |
December 22, 2004 08:06 PM EST |
I recently had to write a quick standalone Java application to
manipulate data so it could be imported to Excel.
I wanted to ensure only full records would be output even if
the user hit Control-C during processing.
I knew Java had the notion of a "shutdown hook" you could register with the Java virtual machine to allow code to cleanup and close resources during a "Control-C" interrupt. After I wrote the application, I wrote this little demo application to show one way shutdown hooks could be used to help ensure records are processed atomically, and any resources could be cleaned up before the JVM exits.
Java shutdown hooks allow code to perform some processing after Control-C is pressed, or while the VM is shutting down for other controllable reason, even
System.exit.
A shutdown hook is a Thread that hasn't been started.
The JVM starts the thread during the shutdown process
to allow the thread to perform cleanup work needed before the JVM exits.
The JVM starts all shutdown hooks concurrently and allows them
to complete before continuing with other shutdown actions,
such as running object finalizers.
It's a nice feature added in Java 1.3,
certainly not as powerful as being able to trap all
operating-system signals and running code to handle them,
but at least it works across all platforms.
In the case of this demo application, the shutdown hook gets started after the user presses Control-C, then mostly just waits until the latest record being processed finishes. The shutdown hook sets an instance variable flag to tell the main processing loop that a JVM shutdown is in progress -- that way, it can stop processing cleanly.
The main processing loop checks after processing each record to see whether the JVM is being shut down abnormally, such as the user hitting Control-C or the user logging off without quitting the application. If a shutdown is in progress, it breaks out of the processing loop to avoid having the next record being corrupted when the operating system decides the application isn't responding quickly enough to the Control-C and kills the JVM outright.
That is one of the unknowns of shutdown hooks: How long can cleanup code run before the operating system decides the application is an uncooperative rogue process that must be killed? Generally, I wouldn't want to risk more than few seconds for Windows to intervene, or for a Unix user to intervene with "kill -9".
This demo application is pretty simple. It adds "ing" to a list of strings stored in a StringBuffer array. To simulate slow, multi-step processing, that is, something that could get interrupted, the application adds each character individually -- i, n, g -- and takes an entire second to do so.
Here is the complete application: CleanShutdownDemo.java. When you run the application and hit Control-C before the program completes normally, it'll dump the state of its data so you can see whether the data got "corrupted" by having some records getting a partial "ing" added. I'll summarize what the methods are doing, below.
Once you download and compile it, there are two ways to run it: the clean way and the dirty way. If you run this program with the command-line argument "clean", it ensures "ing" is added cleanly to the current string being processed, even if the user hits Control-C during processing. If you run the program without an argument or with an argument other than "clean", it runs in "dirty" mode in which a Control-C leaves the currently processed string in an uncertain state. That is, it could:
- have been left unprocessed
- have had an "i" appended.
- have had an "in" appended
- have been fully processed by having an "ing" appended
> java -cp . com.mcqueeney.demo.CleanShutdownDemo dirty Registering shutdown hook Starting processing About to add 'i' to show...added About to add 'n' to showi...added About to add 'g' to showin...added About to add 'i' to cod...added About to add 'n' to codi...added About to add 'g' to codin...added About to add 'i' to thread...added About to add 'n' to threadi...added About to add 'g' to threadin...added About to add 'i' to blogg...added About to add 'n' to bloggi^C <-- HIT CONTROL-C Record 0: showing <-- THESE LINES PRINTED BY SHUTDOWN HOOK Record 1: coding Record 2: threading Record 3: bloggi Record 4: vacationYou'll see that I hit ^C after "i" was added to "blogg" but before the "n" got added. The data dump at the end shows that blogg was corrupted by having only an "i" added. That's the purpose of the "clean" mode, to ensure records get a full "ing" added, or they are left completely unprocessed, in their original state.
Now, for the "clean" way. Running the program with the argument "clean" ensures no record is left in an indeterminate state:
> java -cp . com.mcqueeney.demo.CleanShutdownDemo clean Registering shutdown hook Starting processing About to add 'i' to show...added About to add 'n' to showi...added About to add 'g' to showin...added About to add 'i' to cod...added About to add 'n' to codi...added About to add 'g' to codin...added About to add 'i' to thread...added About to add 'n' to threadi...added About to add 'g' to threadin...added About to add 'i' to blogg^C <-- HIT CONTROL-C Shutdown hook: Waiting to exit ...added About to add 'n' to bloggi...added About to add 'g' to bloggin...added Process interrupted. Shutting down after processing 4 records. Unregistering shutdown hook Finished comparison. Processed 4 records. Record 0: showing Record 1: coding Record 2: threading Record 3: blogging Record 4: vacationYou'll see that after hitting ^C, the main thread continues executing. The
addIngToString method was able to complete
adding "ing" to the word "blogg" even after ^C was hit.
The main thread was able to complete its work because
the shutdown hook (thread) was running and waiting
for the method to complete before returning.
The shutdown hook in this demo application "guards"
against the JVM stopping the main thread prematurely.
The shutdown hook code gets added in the
registerShutdownHook method:
private void registerShutdownHook() {
System.out.println("Registering shutdown hook");
this.shutdownThread = new Thread("myhook") {
public void run() {
// For demonstration purposes: Don't give chance to
// shutdown unless flag is set. Just show data.
if (!runningInCleanMode) {
showData();
return;
}
synchronized(this) {
if (!readyToExit) {
isVMShuttingDown = true;
System.out.println("Shutdown hook: Waiting to exit");
try {
// Wait up to 1.5 secs for a record to be processed.
wait(1500);
} catch (InterruptedException ignore) {
}
if (!readyToExit) {
System.out.println(
"Main processing interrupted." +
" Data corruption possible."
);
}
}
}
showData(); // To demo current state of data.
}
/**
* For demo purposes: Show data to see whether it is "corrupted"
*/
private void showData() {
for (int i = 0, j = dataToProcess.length; i < j; i++) {
System.err.println(
"Record " + i + ": " + dataToProcess[i]
);
}
}
};
Runtime.getRuntime().addShutdownHook(this.shutdownThread);
}
This method creates (but does not start) a new thread,
then registers that thread as a shutdown hook with the Java runtime.
The shutdown thread uses two instance boolean variables to communicate
with the main thread: readyToExit and isVMShuttingDown.
If the main thread has already set readToExit to true,
the shutdown hook knows the main thread has finished
its processing and doesn't need to be "guarded" against JVM shutdown.
If readyToExit is false, the run method sets the isVMShuttingDown flag to true to tell the main thread that it better finish what it's doing (processing the current string record) and then exit -- to avoid being killed by the operating system in mid-record. After setting that flag, it waits for up to 1.5 seconds for the main thread to finish. If the main thread hasn't set the readyToExit flag after waiting, the shutdown hook thread prints a warning to say the data might indeed get corrupted.
Most of the other code in the shutdown hook thread is there for demonstration purpose: to alter behavior depending on whether we are running in "clean" or "dirty" mode, and to print the data being processed in the
showData method so we can see for
ourselves whether the data has been "corrupted."
In fact,
the only reason the
dataToProcess variable is an instance
variable is so the shutdown thread can see it for demonstration purposes.
The other method that cooperates with the shutdown thread is
startProcessing.
This method checks whether a JVM shutdown is in progress
after fully processing one record
(which the addIngToString performs).
public void startProcessing(StringBuffer[] records) {
this.dataToProcess = records; // Store for demo purposes.
System.out.println("Starting processing");
int recordsProcessed = 0;
try {
for (int i = 0, j = records.length; i < j; i++) {
// Process this next record but don't let ^C interrupt
// unless it takes more than 1.5 seconds.
addIngToString(records[i]);
++recordsProcessed;
// Don't continue if VM is trying to shut down.
if (this.isVMShuttingDown) {
System.out.println(
"Process interrupted. Shutting down after processing " +
recordsProcessed + " records."
);
signalReadyToExit();
break;
}
} // end while.
// Tell shutdown hook we're done then unregister it.
signalReadyToExit(); // In case shutdown thread already running.
unregisterShutdownHook();
System.out.println(
"Finished comparison. Processed " + recordsProcessed +
" records."
);
} catch (RuntimeException rte) {
System.err.println(
"Got unexpected runtime exception: " + rte.getMessage()
);
throw rte;
} finally {
// Cleanup, assuming we had resources to close.
}
}
You can see that after each call to
addIngToString,
the "if" statement:
// Don't continue if VM is trying to shut down.
if (this.isVMShuttingDown) {
System.out.println(
"Process interrupted. Shutting down after processing " +
recordsProcessed + " records."
);
signalReadyToExit();
break;
}
checks to see if the shutdown thread has warned us that
the JVM is being shutdown early for some reason.
If so, it calls
signalReadyToExit
to tell the shutdown thread that we've acknowledged
the JVM shutdown and we are NOT in the middle of processing a record,
so it is OK to exit and allow the JVM to complete shutdown processing.
It then breaks out of the "for" loop to skip processing further records.
As a side note, the check of the isVMShuttingDown variable should be in a synchronized block for complete thread safety, especially on a multi-CPU system. The Java memory model guarantees cooperating threads can see changes to shared data only when a thread owns the shared lock. I left it out of the above code for ease of reading.
The last method we'll call out for special attention is the method we are trying to ensure runs atomically. The
addIngToString
simulates the method that performs some important processing that,
if interrupted by a JVM shutdown,
we still want it to complete processing.
private void addIngToString(StringBuffer buffer) {
char[] toAppend = { 'i', 'n', 'g' };
for (int i = 0, j = toAppend.length; i < j; i++) {
System.out.print(
"About to add '" + toAppend[i] + "' to " + buffer
);
sleep(333); // Sleep to simulate long processing
buffer.append(toAppend[i]);
System.out.println("...added");
}
}
This method slowly adds "ing" to the given string buffer argument.
The sleep method performs the obvious Thread.sleep call.
Although this demonstration program has a lot of code, most of it is there for verbosity. The extra code allows us to watch what is happening and be able to set the two different runtime modes to see how the data can get "corrupted" if not being guarded by the shutdown hook. The actual code to protect against data corruption is quite small: 14 real lines of code in the shutdown hook and about six lines in the main application to set and check the shutdown flags being set and watched by the shutdown hook.
Once you get used to the threading issues, adding shutdown hooks to applications for cleaner handling of JVM exits is easy, and helps insulate applications against unexpected interruptions.
Wednesday December 22, 2004 Permalink
Comments [3]
Firefox browser upgrade blues
Published by Tom |
November 23, 2004 06:34 PM EST |
I momentarily got the Firefox upgrade blues when I upgraded my Pre 1 browser to the 1.0 release. As has happened nearly every time I've upgraded Firefox, my installed extensions break.
I figured this upgrade probably didn't change a whole lot on how Firefox handles extensions, so I thought I could rifle through the extension XPI files and tell them it's OK to run in 1.0. Thirty seconds later, I said, "that was easy!" and I figure I'd write the instructions here for other folks whose extensions stopped working after they upgraded to Firefox 1.0.
Before I went to the trouble to write the instructions, I checked to see if there already were instructions out there to forcibly "upgrade" browser extensions. Um, yeah, a few, including comments on several extension pages whose authors hadn't yet upgraded the XPI files.
The first set of instructions I found using Google were from Liew Cheon Fong. So why repeat his work?
I wonder though, rather than unzipping the XPI file, editing the install.rdf file, then rezipping everything back into an XPI file, would it work to edit the exploded XPI file in my Firefox profile directory? I haven't tried it yet, but I think it should work.
Tuesday November 23, 2004 Permalink
Comments [2]
Laptop search continues
Published by Tom |
November 15, 2004 11:40 PM EST |
Despite
Chris
and his Powerbook coming to my rescue when my company-owned Wintel laptop couldn't connect to a VGA overhead projector at last Wednesday's Denver JUG meeting, I'm still concerned the Mac won't work for me. I wouldn't be able to run JDK 5.0 for some time, and that generally seems to be true for a lot of software: It comes out on the Mac much later or not at all.
Then there's the $700 to $800 "penalty" for buying a Mac, for which Chris had a great response: How much is my time worth when I waste it getting Windows or Windows apps to cooperate.
I did check out the Powerbook at a computer store. The user interface seemed to act sluggish, and I don't think it was just because I was biased by Matt Raible's regular rags about the slow Powerbook. Nothing jumped out at me as being impressive. I certainly did not put the Powerbook through its paces, so in no way was I being fair to the Mac. But the big price tag, and the concern that, say, WebLogic 9 won't run on it makes me want to steer clear for now.
I appreciate the many people who tried to get me to see the light. When I have enough money to afford a second laptop, it'll probably be a Mac just so I can experience what everyone tells me is the one, true way.
Monday November 15, 2004 Permalink
Comments [1]
Laptop shopping: Is a Mac worth it?
Published by Tom |
October 31, 2004 04:59 PM EST |
I'm in the market for a new laptop.
Many developers I know and respect own an Apple Powerbook.
They say the usability is much better than Windows XP.
Friends also recommend the Powerbook.
One of them,
Chris
Huston,
said there is no contest between the Powerbook/OS X and a Windows XP laptop.
He said it won't be one big Powerbook feature that will blow me away.
It will be 1,000 little features that will
continue to impress me every day.
But I've never owned a Mac. I'm a long-time user of Windows, since the 3.1 days, and MSDOS before that. I think I've discovered every keyboard shortcut possible in Windows, and I've banished the Office paperclip and the scratching/sniffing Search puppy to the Recycle Bin. And, yes, I can write rudimentary Windows shell scripts, even though I'd much prefer BASH or CSH. So using Windows isn't a problem for me.
But I also like Unix, so I don't foresee the OS X command line as seeming strange. In fact, I've used Unix longer than any other operating system, starting with BSD Unix at college. I've used System V, HP-UX, AIX, and Solaris. And I've been using Linux on development boxes at home for more than five years, including customizing my own Linux and BSD kernels.
So I priced a 15-inch Powerbook at the Apple web site to see how feasible buying a Mac would be. Ouch. It would cost me $800 more for a Powerbook than a similarly equipped Dell. Is the quality of the Powerbook hardware and software that much better? Or does Apple take advantage of its loyal customer base and the fact it has really no competition for non-Windows laptops?
What I'm looking for is a laptop that has:
- A fast processor for development, but not so fast that a high-speed fan system is needed to cool it. (The fans in my company-issued Pentium 4 laptop make a racket. When I run Ant/Maven or launch something huge like WebLogic, I keep expecting Newton's third law to send it flying across my desk.)
- A 15-inch screen is probably big enough
- At least 1 GB of RAM, expandable to 2 GB
- Hard drive 60+ GB
- A non-fancy video card. I'm not a gamer or plan to watch movies from my laptop.
- WiFi and USB 2.0 (almost standard nowadays)
- CD burner, DVD reader.
- Software to read and write Microsoft Word and Powerpoint files.
My current question is, for my needs, do the features and usability of OS X really warrant the extra $800. Not to mention the extra frustration I will undergo getting applications like WebLogic 8.1 installed under OS X. (Folks at BEA say it is possible, they just don't support it or make it easy.)
Sunday October 31, 2004 Permalink
Comments [6]


