JavaRanch Journal
Volume 6, Number 2 (November 2007)
Managing Editor: Ulf Dittmer

JavaRanch Newsletter Articles in this issue :
Windows Vista Positioning Mistakes Merrill R. Chapman
Printable Version
Ant Task Dependency Graphs Jeanne Boyarsky
Printable Version
Baby Steps With Scriptaculous David O'Meara
Printable Version
Creating Java classes at runtime for evaluating numerical expressions Ulf Dittmer
Printable Version
Using OpenSymphony Quartz Scheduler in Spring Christophe Verré
Printable Version
Interview with Lasse Koskela, author and JavaRanch sheriff Mapraputa Is Printable Version
Interesting stuff elsewhere on the Ranch Ulf Dittmer
Printable Version

WIRE
Windows Vista Positioning Mistakes

Windows Vista Positioning Mistakes

by Merrill R. (Rick) Chapman, Managing Editor, Softletter

Since the release of the first edition of In Search of Stupidity: Over 20 Years of High-Tech Marketing Disasters (a.k.a ISOS) I've been accused by various parties of being an apologist for Microsoft. Much of this criticism has come from various Mac Fan Boys and deranged Microsoft haters, and I've ignored them for the very simple reason that they almost always, without exception, don't know what they're talking about. But the good news for every hardened Redmond loather is that with the introduction of Windows Vista, Microsoft has indulged in the type of high-tech marketing stupidity previously chronicled in ISOS I and II. The Windows Vista launch has been a rolling train wreck, and things have not been getting better. This article reflects my Vista observations and the lessons its disastrous launch teaches.

The industry's biggest software company has, with its latest release, managed to repeat positioning mistakes made almost a quarter century ago by MicroPro, which has earned its own inglorious chapter in ISOS. I'm speaking, of course, of the launch of Windows Vista. Several months after the release of Vista to businesses (the product was released to consumers in January, 2007) the consensus of the market has been that Vista is a flop. It's a peculiar type of flop. Financially, Vista is making a great deal of money for Microsoft. No surprise there; after all, the company has an almost complete monopoly in the desktop OS and main business applications markets and the dominant position in the server OS segment. OEMs are in complete thrall to Microsoft; if you don't offer Windows on your laptop, you've got an unsellable silicon brick in your warehouse (yeah, yeah, I know about Linux. Not a serious option at this time.).

But that said, Vista has failed to meet any of the lofty goals originally set for it. It has failed to excite any segment of the market, including key influencer groups such as the press and the gamers. It is not driving sales of new computers. At retail, the pull figures for Windows out of the channel are dreary and show no signs of changing (we're researching these numbers and will be reporting on them soon in an upcoming issue of Softletter). The blogs are condescending and even many Microsoft devotees are dismayed by what they see and hear. Legitimate copies of Windows XP (and even 2000!) just became more valuable and knuckles will have to be severely cracked before the hands grasping those precious old boxes relax and allow a fresh copy of Vista to be shoved into a reluctant grasp. The fact is, few people see any need or have any desire to buy Vista.

In all fairness, some of the problems that accompanied the Vista launch are beyond Microsoft's control. As the Internet has matured as a development and infrastructure platform, the growth of SaaS and advent of hybrid applications has led to an inevitable challenge to Microsoft's monopolies in OSs and desktop applications. Over the next several years, Microsoft will need to execute the painful chore of chewing off its own two strong revenue arms (but not too quickly) and hope they regenerate into new revenue and profit builders. It's not a tasty task, and you can't really blame the company for avoiding it, necessary though it is.

On the other hand, it's hard to see how they could do a better job of making clear the potential advantages of SaaS if they deliberately tried. At Softletter's recent SaaS seminar in Santa Clara, I felt compelled to add the Vista launch and WGA to the list of factors driving further interest in SaaS. The chief objections to using SaaS in the enterprise include:

  • Reliability and service interruptions. Microsoft helped relieve that SaaS concern with the aforementioned August 2007 bricking of thousands of innocent PCs which were struck down when logged into a WGA server that had faulty code loaded onto it. It took Microsoft 19 hours to fix the problem; in SaaS world, a service interruption of four hours can trigger an escrow demand. SaaS advantage: Check.
  • Privacy concerns. Microsoft is doing a good job of ameliorating this worry with its increasingly aggressive software auditing campaigns driven by its ongoing data mining operations which compare your company's size with the amount of its software Redmond thinks you should own. SaaS advantage: Check.
  • Pricing concerns (as in, is SaaS more expensive than those perpetual licenses). Since Microsoft's current licensing policies are for all practical purposes incomprehensible and increasingly more expensive, SaaS offers (in theory) the virtue of predictability AND knowability. SaaS advantage: Check.
  • Control over your computing environment. Microsoft helped lay this worry to rest with its stealth updates to the Windows update system which occurred despite the fact that supposedly the operating system allowed you to block any such updates. Whoops! THEN the company compounded the problem by either not realizing or telling people that the stealth updates broke XP's repair function. THEN Windows started pushing updates and rebooting systems without, it seems, Microsoft's knowledge! (Since this is the Halloween season, perhaps the update servers have been possessed by evil spirits?) SaaS advantage: Check.
But paradigm shifts and SaaS aside, the biggest problem crippling the Vista rollout was Microsoft's complete bungling of the critical task of properly positioning the product. Vista's marketing identity is a dirty smear in the mind's eye of the public; today, it's almost impossible to find anyone (particularly anyone from Microsoft) who can cleanly and quickly describe why Vista is superior to Windows XP. And a confused buyer is a buyer that does not buy (or one who buys something they can understand).

Microsoft's Positioning Sins

During the Vista rollout, Microsoft committed several positioning sins. Redmond's mistakes begin with the deadly transgression of creating a positioning conflict within its own product lines. It's a surprising mistake. During the history of the Windows 9.X vs. NT product lines, Microsoft was frequently tormented by customers confused by which product to buy, a mistake highlighted by the firm's creation of one of high-tech's dumbest ads, the two nags racing piece which you can see preserved on www.insearchofstupidity.com in the Museum of Stupid High-Tech Marketing. While 9.X and NT both existed, Microsoft frequently had to explain why a customer should buy one product over the other when both were called Windows, looked very much the same, did very much the same thing, and cost pretty much the same. But Microsoft was lucky in that during this period its chief jousting opponent was IBM and OS/2.

But with Vista Microsoft pointed the lance at its own foot, kicked its marketing war horse into action, and firmly pinned its toes to the ground. There are no less than six (actually seven, counting the OEM version. Wait, isn't that eight if you count academic packages? Are we missing some other variants? Probably. Does Windows CE count?) versions of Vista currently available for sale:

  • Vista Starter (which you can't buy unless you live in the Third World, apparently.)
  • Vista Home Basic (which, amazingly, does not include the new UI.)
  • Vista Home Premium
  • Vista Business
  • Vista Enterprise
  • Vista Ultimate
This plethora of choices leads customers to naturally ask a deadly question: Which one do I buy? Before, a consumer only had to compare between Windows XP Home and Professional (Windows Media Edition came along too late in the life cycle of the product to become well-known enough to confuse anyone). To help customers, Microsoft has published a blizzard of collateral, comparison sheets, pricing matrices, etc., etc. Thinking about whether to buy Vista Home Premium vs. Vista for Business? What's Super Fetch worth to you? How about Volume Shadow Copy? But it's good to know the Business version includes Premium Games. Just what a business person is looking for in their business version of Vista. Why not include applications that have some applicability to business concerns? Maybe stock analysis and reporting? Specialized business calculators? Something? Anything?

And making things ever more interesting is that the EULAs accompanying each version are different. Want to create a virtual machine on your PC and run Vista Home in it? You can't! How about Vista Business? You can! Why one and not the other? Who knows.

Moving along down the path of positioning damnation is Microsoft's failure to attach any powerful or desirable image to Windows Vista as a product line. Try to imagine in your mind what memorable picture or capability is associated with Vista. None comes to mind. The product does have a new interface, but Microsoft made no attempt to build a compelling image of usefulness around the AeroGlass UI. Yes, the icons are bigger and the screen savers are prettier, but so what? Microsoft might have discussed how the new desktop gave users X-ray vision like Superman, increasing their day to day productivity while working with Windows, but it didn't. Vista is supposed to be far more secure than XP, and perhaps Microsoft could have discussed Fort Knox, an integrated group of technologies that allowed you to lock up your PC with bank vault tightness, but it didn't. (Given Microsoft's past security woes, it may have lacked the stomach for this gambit.)

By contrast, when Apple released Tiger (OS X 10.4) the market and the press were bombarded with information spotlighting Spotlight, an integrated search utility baked into the new release. Desktop search was by no means new on either Macs or PCs, but the Mac campaign succeeded in making people aware of its usefulness and, more importantly, gave them a mental picture of why they might want to give Tiger a look. With Leopard (OS X 10.5), the emphasis was on Time Machine (integrated backup).

Another key mistake made in launching Vista was to match features to pricing expectations and here Microsoft has also failed, particularly in respect to Windows Ultimate. Ultimate is the kitchen sink of Windows, the one with all the toys and whistles and it's expensive at $450 for a retail version (and pricey at $270 for the upgrade version). But not to worry! With your purchase of Ultimate you're promised all sorts of goodies only you, our ultimate customer, can download. And what are these exciting ultimate premiums? Well, to date, they include fun things like Windows Hold 'Em (a poker game), extra language packs (those squeals of delight are coming from buyers who just unpacked Finnish and Korean) for the Windows multi-language user interface, Secure Online Key Backup, and BitLocker Drive Preparation Tool. (The latter two products are included in other, cheaper versions of Windows.) And oh, let's not forget the new screen saver that let's you use videos. Alas, it's in beta and not due to be finished for a while yet. Ultimate customers, are, of course, delighted with all of this.

In its long and storied history, Microsoft has distinguished itself from its competition by its ability to avoid the self-inflicted wound of stupid marketing. With the release of Windows Vista, this has changed. During the release of Windows Vista, Microsoft has repeated mistakes made by MicroPro (positioning conflict), Borland (positioning conflict, pricing/feature disparity), Novell (positioning conflict), Ashton-Tate (pricing/feature disparity coupled with inept PR) and itself (Windows 9X vs. NT), proving that the company now suffers from the same institutional memory hole that afflicts much of high-tech. The Vista release serves as a valuable and contemporary object lesson in how not to position and launch a new software product.

www.softletter.com
www.aegis-resources.com
www.insearchofstupidity.com

Discuss this article in The Big Moose Saloon!

WIRE
Return to Top
Ant Task Dependency Graphs

Ant Task Dependency Graphs

by Jeanne Boyarsky

When inheriting an Ant build file to maintain, it is useful to get a feel for the flow and structure. Sketching the dependencies between targets is a useful way to do this. While it is time consuming to do so by hand, there are a number of tools to help.

I tried three different tools to generate the output. All of them generate a .dot file which needs to be run through the Graphviz tool to be converted to a useful format. Graphviz can covert to all image formats among many others. Each tool is described below with an example of how to call it. I've also included two sample images: from our build script to Pick Winners in the weekly book/software promotion and a contrived example designed to show how antCall and forEach work.

  1. Ant2Dot - Ant2Dot is an XSLT file that converts your Ant build file into a .dot file. Each target becomes a rectangle and dependencies between targets are shown. The instructions for using it are a bit old and only apply to Java 1.3 and 1.4. They don't work on Java 5/6 without modification. The website lists a "to do" for adding support for Ant 1.6's import and subant features. Similarly, 1.7 features aren't supported yet. Ant2Dot is good for simple build files, but doesn't scale up to handle use advanced features. Running was as simple as downloading a stylesheet and running the command:
    C:\j2re1.4.2_03\bin\java org.apache.xalan.xslt.Process
    			-IN build.xml -XSL ant2dot.xsl -OUT build.dot
    Output of JavaRanch's book promotion pick a winner dependency structure and a contrived sample:
  2. Vizant - Vizant is a Java library that creates a .dot file by using a SAX parser on your Ant build file. Each target becomes an oval and dependencies between targets are shown. Vizant supports antcalls and allows you to drill down to generate only part of the build tree. You can also drill down to show part of your build tree. Vizant was easy to use. I wanted the dependency ordering so continued looking for a library to meet my needs. In order to run Vizant, you need to download a jar containing the source and build it using Ant. They provide the build.xml to do so. Since this is a library for Ant documentation, it is reasonable to assume people know how to run Ant. You also call it through a simple Ant build file:
    <?xml version="1.0"?>
    <project name="Vizant" basedir="." default="vizant">
    	<taskdef name="vizant"
    		classname="net.sourceforge.vizant.Vizant"
    		classpath="build/vizant.jar" />
    
    	<target name="vizant">
    		<vizant antfile="build.xml" outfile="build.dot" uniqueref="true" />
    	</target>
    
    </project>
    Output of JavaRanch's book promotion pick a winner dependency structure and a contrived sample:
  3. Grand - Grand is also a Java library that creates a .dot file. It takes a different approach and actually creates the Ant directory structure using Ant's Java libraries. It can support anything in your classpath including ant-contrib and Ant 1.6's import feature. The logic doesn't capture the subtleties of Ant-Contrib like the forEach loop though. The graph is a bit more detailed. The default target is a yellow hexagon. Targets with a description are marked in blue so you can show entry points. The remaining targets are shown as ovals. You can also drill down to show part of your build tree. You can use a Grand UI tool instead of the dot file, but I wasn't able to get the UI. Like Ant2Dot, dependencies are numbered. Grand was as easy to use as Vizant. They provide you with a jar for download. You call it through a simple Ant build file adding any other jars used to the classpath:
    <?xml version="1.0"?>
    <project name="Grand" basedir="." default="grand">
    
    	<typedef resource="net/ggtools/grand/antlib.xml" classpath="grand.jar" />
    
    	<target name="grand">
    		<grand output="grand-build.dot" buildfile="build.xml" />
    	</target>
    
    </project>
    Output of JavaRanch's book promotion pick a winner dependency structure and a contrived sample:
Comparison of visualization tools
ToolShows dependency orderingFlags default targetFlags main targets
Ant2DotYesYesNo
VizantNoNoNo
GrandYesYesYes

Discuss this article in The Big Moose Saloon!

WIRE
Return to Top
Baby Steps With Scriptaculous

Baby Steps With Scriptaculous

by David O'Meara

I almost missed the boat with this one, heck Bear and company managed to get a book out before I decided to give it a serious look, but finally I have looked.

Introduction

As a quick introduction, Prototype is a JavaScript library that has become quite popular due to the things others have built on top of it. I like to think of Prototype as an extension to JavaScript and inclusion of various best practices. Through it code becomes less cumbersome and unwieldy, and therefore easier to manage. This doesn't sound like much, but I have developed an aversion to JavaScript over my eight years of casual development and Prototype made me much happier. The only Prototype functionality used directly in the following is the $() function, which is a sort of shorthand for document.getElementById(), the rest of Prototype is used under the covers by Scriptaculous. Two additional resources I liked were the online API book and the article How well do you know prototype.

Finishing the introduction, Scriptaculous or script.aculo.us, as it is commonly written to match the URL, is written as an additional layer on Prototype and "provides you with easy-to-use, cross-browser user interface JavaScript libraries to make your web sites and web applications fly". There are few different areas that are enhanced by Scriptaculous, but we're just looking at the animation effects, and the smallest subset, at that.

The Scriptaculous Demos

The demos provided by Scriptaculous show some useful effects, but I will just be looking at two. To get started you need the libraries, but you can get scriptaculous.js and effects.js in the Scriptaculous download, and it contains prototype.js too. It contains some other files too, but we just need the ones listed.

Time for some code. Create a file called test1.html with the following content, make sure the javascript files are in a folder called javascript in the same location.

<html>
<head>
<script type="application/x-javascript" src="javascript/prototype.js"></script>
<script type="application/x-javascript" src="javascript/scriptaculous.js"></script>
</head>
<body>

<div class="space">
<div class="example" id="demo-effect-blinddown" onclick="new Effect.BlindDown(this)">
<div style="width:200px;">
<span>Click for Effect.BlindDown demo</span>
</div>
</div>

</div>
<div class="space">
<div class="example" id="demo-effect-blindup"
    onclick="new Effect.BlindUp(this);
            window.setTimeout('Effect.Appear(\'demo-effect-blindup\', {duration:.3})',2500);">
<span>Click for Effect.BlindUp demo</span>
</div>
</div>

</body>
</html>

Gives us this:

Click for Effect.BlindDown demo
Click for Effect.BlindUp demo

Clicking on the blind-down demo creates a 'BlindDown' effect on that div, same with the blind-up except that it also has a little event that fires off afterwards to show the div again, otherwise we lose it. The code is pretty simple: in each there is an outer div which can be ignored, and an inner div of interest. The two active div's respond to an onclick event, the onclick calls a Scriptaculous effect and passes a reference for the div to Scriptaculous to provide the effect. Hence: onclick, Scriptaculous, 'this', done.

Extending the Demo

Hopefully the example above is pretty self explainatory. To add our own functionality we will add the BlindUp and BlindDown effects to a single div, allowing us to open and close it. Rather than applying the onclick to that div, we'll add it to a second div so that we always have something to click on, even when our 'blind' div is not available. It will start out something like this:

<div class="header">
    Header
</div>
<div class="bodyOpen">
    This is the body part,
    which will do the
    blind-up and blind-down
    effects
</div>
Header
This is the body part, which will do the blind-up and blind-down effects

Unlike the previous example, where the click on the div caused an action on the div, we are going to make a few changes...

  • The onclick event will be on the header, but the effect will be applied to the body
  • We will use naming rules in our element ids to make the logic and control easier
  • We're going to use both effects, BlindUp and BlindDown so that we can open and close the body
  • We will use CSS classes to track the opened or closed state on the body

Naming the Head and Body

Element IDs must be unique. This isn't my rule, it's an XHTML rule. Since you're not allowed to reuse an ID after using it once, it makes them handy for identifying and finding specific items on our page. On our page, we are going to assume that whatever ID the header has, the associated body's ID will have 'Body' added to the end. Hence the associated body for header 'itemOne' is 'itemOneBody'.

Tracking the Body State

The Prototype $() function, mentioned earlier, accepts either an Element or the name of an Element ID, so starting from a reference to the header element, the header ID is header.id, the therefore the ID for the associated body is header.id+'Body' and to get a refernce to that Element we call $(header.id+'Body'). Now we want to know if it has the CSS class 'bodyOpen', and again Prototype comes to our aid with hasClassName('bodyOpen'). There is also a function to add a class name addClassName but I'm going to keep the name of the function used to remove a class name secret for now.

Putting these together, we can write a function which takes the reference to a header as its argument, detects the state of the body and then performs a switch on the class state.

function toggle(header)
{
    if($(header.id+'Body').hasClassName('bodyOpen'))
    {
        // open
        $(header.id+'Body').addClassName('bodyClosed');
        $(header.id+'Body').removeClassName('bodyClosed');
    }
    else
    {
        // close
        $(header.id+'Body').addClassName('bodyClosed');
        $(header.id+'Body').removeClassName('bodyOpen');
    }
}

Adding the Effect

As we saw in the Scriptaculous demos, adding an effect is easy.

function toggle(header)
{
    if($(header.id+'Body').hasClassName('bodyClose'))
    {
        // open
        new Effect.BlindDown($(header.id+'Body'));
        $(header.id+'Body').addClassName('bodyOpen');
        $(header.id+'Body').removeClassName('bodyClosed');
    }
    else
    {
        // close
        new Effect.BlindUp($(header.id+'Body'));
        $(header.id+'Body').addClassName('bodyClosed');
        $(header.id+'Body').removeClassName('bodyOpen');
    }
}

Trying it Out

All that remains now is to add out IDs, plug the function in to the div and give it a try:

<div class="header"
onclick="toggle(this);">
Header
</div>
<div class="bodyOpen">
This is the body part,
which will do the
blind-up and blind-down
effects
</div>
Header
This is the body part, which will do the blind-up and blind-down effects

Now To Make Something Useful

So maybe you're not too impressed so far, but if you put a few in a row, add some nicer styles and realistic content, and you have an easy to maintain accordion panel.

Header
script.aculo.us
JavaRanch
David O'Meara
The JavaRanch Volunteers

I did cheat a little here, if you look at the source code. Firstly the body parts start with the 'bodyClosed' rather than 'bodyOpen' class, and they have an initial style that makes them hidden. Also, the name of the header and body don't have to be numbers, they just need to be unique. It makes life easier if they are also meaningful, as long as you copy and paste them correctly.

Where Do We Go From Here?

If you thought that was too easy, that would be my point! Play with styles, play with storing the open/closed position in a cookie so it is retained between visits, look at rollover effects or different styles for open and closed headers. Keep in mind that now we are finished, the page content, CSS and script are about the same size, and the code knows nothing about the page content and page content just follows some easy class name and ID naming rules.

Discuss this article in The Big Moose Saloon!

WIRE
Return to Top

Creating Java classes at runtime for evaluating numerical expressions

by Ulf Dittmer

This article demonstrates two techniques that are frequently asked about: creating Java classes at runtime, and evaluating a mathematical expression that is given as a string. While these two don't have much to do with one another at first sight, the former can be used to implement a well-performing solution to the latter. Performance matters in this case, because usually formulas must be evaluated repeatedly for a range of parameters, at which point approaches that are based on interpreters quickly become a limiting factor. On the other hand, approaches that compile the formula to a Java class –like the one presented below– will show much better performance.

We start out with creating a basic class that evaluates a formula given a single parameter. Step by step the class is extended to be more developer-friendly and/or more powerful, until at the end it handles multiple parameters while being easy to program with, and easy to extend, at the same time.

The accompagnying zip file contains all example codes and the Javassist library, which is used for dynamically creating classes. Nothing else is needed to get the examples to run.

The Beginning

The following code shows the basic steps to create classes at runtime using the Javassist library. Javassist is part of JBoss these days, but is otherwise independent of it; it can be downloaded from SourceForge.

1) ClassPool pool = ClassPool.getDefault();

2) CtClass evalClass = pool.makeClass("Eval");

3) evalClass.addMethod(
        CtNewMethod.make(
            "public double eval (double x) { return (" + args[0] + ") ; }",
            evalClass));

4) Class clazz = evalClass.toClass();

5) Object obj = clazz.newInstance();

6) Class[] formalParams = new Class[] { double.class };
Method meth = clazz.getDeclaredMethod("eval", formalParams);

7) Object[] actualParams = new Object[] { new Double(17) };
double result = ((Double) meth.invoke(obj, actualParams)).doubleValue();
System.out.println(result);

Let's go through the steps one by one and look briefly at what they do. The following examples are based on it, so it's important to understand the basic concepts now.

1) Javassists's ClassPool represents the set of all classes in a JVM. It needs to be retrieved once, but nothing further is done with it except from adding the new class to it.

2) This creates a new class named 'Eval'. CtClass is the most important of Javassist's classes. It's the equivalent to java.lang.Class, and is used to carry out just about all modifications one might want to apply to a new or existing class.

If the newly created class should be part of a package, then its name must contain the fully qualified class name, like it would be used in an import statement.

3) A method is created and added to the class. The body of the method is

public double eval (double x) { return (" + args[0] + ") ; }

as if it was part of a regular source file. The formula to be evaluated is passed in as an args parameter, and becomes part of the method. The method takes a double parameter and returns a double result.

4) Once we're done creating the class, we can retrieve its java.lang.Class object from the CtClass object. This concludes the use of Javassist - we can now use the new class like we would use any other class that was loaded dynamically.

5) We instantiate it, ...

6) ... use reflection to get a handle to the eval method, ...

7) ... and finally call the method with a parameter of 17 and print the result.

The example can be run using

    make run1

(if you have make available), or directly via

    java -classpath .:javassist-3.4.jar Example1 "x + 42"

The expression to be evaluated is passed to the code as a parameter. If you use this formula, the result should be 59 (= 17 + 42).

Case closed? Of course not. The reflection code is ugly, tedious to write, and –if executed many times– not very performant. We want to write code like result = obj.eval(17) instead. The problem with that is that we can't use the class Eval in the code directly, because the class doesn't yet exist when the code is compiled.

Making It Nice

Interfaces to the rescue! The class we create has only a single method we care about (eval), and we know what its method signature will be. So we can move the method into an interface, and have the to-be-created class implement this interface. Then we can cast the object to the interface in step 5, and call the eval method directly. This is the interface we'll implement:

public interface Evaluator {
    public double eval (double x);
}

This is easy to do with Javassist. The following line declares that our class will implement Evaluator:

evalClass.setInterfaces(
        new CtClass[] { pool.makeClass("Evaluator") });

Then we can cast to it, and call eval:

Evaluator obj = (Evaluator) clazz.newInstance();
double result = obj.eval(17);
System.out.println(result);

This is what Example2 does. It is run in the same way as Example1, except that it also takes the numeric argument from the command line, so that you can evaluate the formula using other values besides 17.

One small additional change is that a timestamp is appended to the classname. This doesn't change anything visibly –because we don't really care about the class name– but it serves as a minimal guard against threading problems in case the class-constructing code is ever run in a multi-threaded environment.

Adding Convenience

After using this code for a while you might want to evaluate more complex formulas, containing constants and functions. No problem – the following lets us use "pi" instead of having to type "3.141592..." in our formulas all the time:

evalClass.addField(
        CtField.make("private double pi = Math.PI;", evalClass));

We can add random numbers by making use of the java.util.Random class. The following lines add a field for a Random object, a constructor that initializes it, and a rnd() method that returns a random number between 0 and 1.

evalClass.addField(
        CtField.make("private java.util.Random rnd;", evalClass));

CtConstructor constr = CtNewConstructor.defaultConstructor(evalClass);
constr.setBody("{ rnd = new java.util.Random(System.currentTimeMillis()); }");
evalClass.addConstructor(constr);

evalClass.addMethod(
        CtNewMethod.make("public double rnd() { return rnd.nextDouble(); }", evalClass));

Example3 shows this in action. Note that both adding a field and adding a body to the default constructor works in much the same way as adding methods: you supply the source code directly to the appropriate make method, and add the result to evalClass.

Even More Convenience

Once you've added a few more functions and constants in the way described above, you're probably wondering if there isn't a more convenient way to do this. Dealing with Javassist's various classes, and having to maintain source code as part of a string inside of other source code is not exactly fun.

Subclassing to the rescue! So far, the code has implemented the Evaluator interface, which didn't allow us to supply any methods to go along with the eval method. But nothing stops us from creating a class that extends some other class that has implementations of all kinds of nifty functions. Look at the source code of the Expr class – it does just that.

Example4 implements this. We just need to get a CtClass object for the Expr class:

CtClass exprClass = pool.get("Expr");

And then make that the superclass of our expression-evaluating class:

evalClass.setSuperclass(exprClass);

That was easy. Now any additional functions can easily be maintained as part of the Expr class. An alternative to implementing Evaluator in this scenario would be to make eval an abstract method of Expr instead. Whether one or the other makes more sense depends on how the class will be used; functionally the approaches are equivalent.

Further Possibilities

Expression evaluation isn't limited to functions taking a single parameter, of course. Example5 shows a program that takes either 1 or 2 parameters, and generates the class accordingly.

These examples have only scratched the surface of what Javassist can do. In addition to creating new classes, it's also possible to modify existing ones, and to remove fields or methods from a class.

The CtClass class also has methods for writing the bytecode of a class to disk or obtaining it in a byte[], in case it's necessary to preserve it beyond its one-time use.

Sometimes a class depends on other classes; in those cases there are ways to tell the ClassPool about what to use as classpath.

There's also a low-level API for dealing with bytecode directly.

Conclusion

This article showed how to create Java classes dynamically, based on information available at runtime. It then used those classes to evaluate mathematical expressions that were not known beforehand. Both these are problems one doesn't encounter frequently, but they do occur, and neither is trivial to solve. But knowing that it's not all that hard, additional ways to make use of them probably suggest themselves.

Discuss this article in The Big Moose Saloon!

WIRE
Return to Top
Using OpenSymphony Quartz Scheduler in Spring

Using OpenSymphony Quartz Scheduler in Spring

by Christophe Verré

Spring offers a few helper classes to do some scheduling in your application. In Spring 2.0, both the JDK's Timer objects and the OpenSymphony Quartz Scheduler are supported. Quartz is an open source job scheduling system that can be easily used with Spring.

Let's get started

As you may expect, both Spring and Quartz must be installed. Spring can be downloaded with all its dependencies. If you don't mind the size, it is recommended to download the bundle including dependencies. Quartz 1.5.x or above is needed in Spring 2.0. It is assumed that you already know how to include jar files in your classpath. If you don't, there's no better place than JavaRanch to ask. It is also assumed that you already know Spring basics.

About Quartz

Quartz offers five main structures to realize scheduling:
  • The Job interface
  • The JobDetail class
  • The Trigger abstract class
  • The Scheduler interface
  • The SchedulerFactory interface
The Job interface represents a job. A job does something, only one thing. Its API is very straightforward. Only one execute() method, which will be called by Quartz when a Job has to be executed. Some useful information can be retrieved from the JobExecutionContext that is passed to the execute() method.
public interface Job {
	void execute (JobExecutionContext ctx);
}

Some data can be passed to jobs via the JobDataMap class. If a JobDataMap is registered in a JobDetail, it can be accessed from the Job, via the JobExecutionContext which is passed to the execute() method of the Job interface. The JobDetail class is used to give some information about a particular Job. Jobs are started (or "fired") by triggers, which are represented by the Trigger class. Quartz has some convenient implementation class of Trigger, such as SimpleTrigger and CronTrigger. A SimpleTrigger acts like a basic timer, where you can define a starting time, an ending time, a repeat count and a repeat interval. A CronTrigger uses more advanced settings, using the "cron" Unix utility notation. The settings for a CronTrigger can be very specific, like "fire the job at 10:15am on every last Friday of every month during the years 2008, 2009, 2010". One notion is that jobs and triggers are given names, and may be assigned to a group. A name must be unique within the same group. So you can create a trigger for one group, and all jobs within that group will be executed.

Finally, the SchedulerFactory is used to get a Scheduler instance, which can be used to register jobs and triggers.
Let's illustrate this with a basic example : a simple job printing a welcome message, and a trigger firing the job every ten seconds.
First, the Job, only printing a welcome message:

public class RanchJob implements Job {
	public void execute (JobExecutionContext ctx) throws JobExecutionException {
		System.out.println("[JOB] Welcome at JavaRanch");
	}
}

Then the scheduler, registering a trigger and a job :
public class RanchSchedule {
	public static void main (String[] args) {		
		try {
			SchedulerFactory factory = new org.quartz.impl.StdSchedulerFactory();
	
			Scheduler scheduler = factory.getScheduler();
			scheduler.start();
			
			JobDetail jobDetail = new JobDetail("ranchJob", null, RanchJob.class);
			// Fires every 10 seconds
			Trigger ranchTrigger = TriggerUtils.makeSecondlyTrigger(10); 
			ranchTrigger.setName("ranchTrigger");
			
			scheduler.scheduleJob(jobDetail, ranchTrigger);
		} catch (SchedulerException ex) {
			ex.printStackTrace();
		}
	}
}
After executing RanchSchedule, [JOB] Welcome at JavaRanch is being printed out every 10 seconds.

There are some others interesting things like Priority, TriggerUtils, listeners, but they won't be discussed here.
If you want to know more about Quartz, there's a complete tutorial at Quartz's homepage.

Spring and Quartz

Spring's Quartz API resides in the org.springframework.scheduling.quartz package. There's quite a few classes there, but we'll only see those needed to fire up jobs.
  • The QuartzJobBean abstract class
  • The JobDetailBean class
  • The SimpleTriggerBean class
  • The CronTriggerBean class
  • The SchedulerFactoryBean class
  • The MethodInvokingJobDetailFactoryBean class
The wrapping of Quartz API is obvious. QuartzJobBean implements Job, JobDetailBean extends JobDetail. No need to say which class SimpleTriggerBean and CronTriggerBean extend. MethodInvokingJobDetailFactoryBean is a nifty class to call methods in any objects, instead of Quartz jobs. We'll see that last, but first let's make our previous RanchJob running. (Note that we won't use groups for our jobs and triggers)

Declaring Jobs

The JobDetailBean is used to declare jobs. We set the name of the job class, and if needed, some data the job may use. The job class extends QuartzJobBean. Here is the declaration :
<bean name="ranchJob" class="org.springframework.scheduling.quartz.JobDetailBean">
  <property name="jobClass" value="com.javaranch.journal.spring.quartz.RanchJob" />
  <property name="jobDataAsMap">
    <map>
      <entry key="message" value="Welcome at JavaRanch" />
    </map>
  </property>
</bean>

And the job class :
public class RanchJob extends QuartzJobBean {
	@Override
	protected void executeInternal (JobExecutionContext ctx) throws JobExecutionException {
		String message = (String) ctx.getJobDetail().getJobDataMap().get("message");
		System.out.println("[JOB] " + message);
	}
}

Note how we retrieve the message from the context. This message was set in the bean declaration, using the jobDataAsMap property. Spring actually calls setter methods for each object set in this map. Here is the Spring way to use the message in the job class :
public class RanchJob extends QuartzJobBean {
	private String message;
	
	public void setMessage (String message) {
		this.message = message;	
	}
	
	@Override
	protected void executeInternal (JobExecutionContext ctx) throws JobExecutionException {
		System.out.println("[JOB] " + message);
	}
}

Declaring Triggers

Declaring triggers is as simple as declaring a job. We'll only use a SimpleTriggerBean, which will start immediately, and repeat every ten seconds. You can refer to the CronTriggerBean API to check how to set a cronExpression for your trigger.
<bean id="ranchTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
    <property name="jobDetail" ref="ranchJob" />
    <property name="startDelay" value="0" />
    <property name="repeatInterval" value="10000" />
</bean>

Declaring the Scheduler

Now that we have a job associated to a trigger, we need to register the trigger. We declare Spring's SchedulerFactoryBean the following way :
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
        <list>
            <ref bean="ranchTrigger" />
        </list>
    </property>
</bean>	

Everything has been set up, all we need now is to load the context. The scheduler will be started automatically on initialization. I declared all the above beans in a file called "schedule.xml". I use ClassPathXmlApplicationContext here, so "schedule.xml" must be somewhere in the classpath.
public class RanchQuartz {
	public static void main (String[] args) throws SchedulerException {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("schedule.xml");
	}
}

Executing RanchQuartz will start the scheduler automatically. As expected, The RanchJob will be fired immediately, and repeated every 10 seconds.

Using the MethodInvokingJobDetailFactoryBean

We've seen so far how to fire Quartz jobs, but what if you want to call your own method of your own bean? With Spring, you are not tied to Quartz job instances, you can also use your own pojos to act as jobs. For example, you may wish to use the CronTrigger's advanced settings to fire up your own task.

Declaring the good old bean

Nothing special here. Just a good old bean, declared the good old way.
<bean name="welcomeBean" class="com.javaranch.journal.spring.quartz.RanchBean">
	<property name="message" value="Welcome at JavaRanch" />
</bean>

And the implementation:
public class RanchBean {
	private String message; 
	
	public void setMessage (String message) {
		this.message = message;
	}
	
	public void welcome() {
		System.out.println("[JOBBEAN] " + message);
	}
}

Declaring the MethodInvokingJobDetailFactoryBean

When declaring the MethodInvokingJobDetailFactoryBean, we need to tell Spring which method of which bean to call. Let's also modify our trigger to use this new bean:
<bean id="methodInvokingJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
  <property name="targetObject" ref="welcomeBean" />
  <property name="targetMethod" value="welcome" />
</bean>

<bean id="ranchTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
    <property name="jobDetail" ref="methodInvokingJob" />
    <property name="startDelay" value="0" />
    <property name="repeatInterval" value="10000" />
</bean>

Voilà! Executing the RanchQuartz application again will produce the same result, with "[JOBBEAN]" being printed out instead of "[JOB]".

A word of caution

A trigger can fire only one job, but a job may be fired by many triggers. This can bring a concurrency issue. In Quartz, if you don't want the same job to be executed simultaneously, you can make it implement StatefulJob instead of Job. In Spring, if you are using the MethodInvokingJobDetailFactoryBean, you can set its "concurrent" property to false.

Finally

Using Quartz with Spring instead as a standalone application offers the following benefits :
  • Keeping all scheduling settings in one place. It makes scheduling easier to maintain. It looks a bit like having one "cron" file for scheduling tasks.
  • Coding only jobs. The scheduler, triggers and job details can be configured in the context file.
  • Using plain old java objects for jobs, instead of Quartz jobs.
As stated at the beginning of this article, Spring also supports JDK's Timer objects. If you want to use a simple timer for a simple task as above, you may consider using a TimerTask and Spring's ScheduledTimerTask and TimerFactoryBean instead. If you decide to use Quartz in Spring, there are many more properties that can be set for the scheduler, jobs and triggers. Refer to Spring's API to discover them all.
Discuss this article in The Big Moose Saloon!

WIRE
Return to Top
Interview with Lasse Koskela

Interview with Lasse Koskela

by Mapraputa Is

"I got into the whole IT business through a backdoor..."

JavaRanch: First things first. How do you pronounce your name?

Lasse Koskela: "Lasse Koskela" -- how else can you pronounce it?

JR: Let's start with your first name. Which syllable do you usually stress, the first or the second?

LK: I usually stress the first syllable. Except when in France.

JR: And your last name?

LK: First. I like being first. Although I seldom are.

JR: How old are you?

LK: I'm as old as Brandon Lee when he filmed "The Crow".

JR: What about your parents?

LK: Yes, they are old. And I don't think they've seen "The Crow".

JR: [Aside: Um, OK. Let's see what you'll get for your "Yes, they are old."] You were born in Finland, right?

LK: Right.

JR: What city?

LK: Helsinki. I was actually the first in my family to born in Helsinki. My mother moved there in her twenties and liked it enough to hang around.

JR: When you were six year old, you wanted to be ...?

LK: My mother used to tell me I wanted to be an architect. A building architect, that is. But I think she just wanted me to become one ;)

JR: You seem quite attached to your mother. [Aside: there!] And you went to the college to study ...?

LK: Yes. I went to the Helsinki University of Technology for a few years but dropped out as soon as I had studied all the useful-sounding courses. Working in the bubbling IT business was too exciting to pass out on and eventually ran over the studies.

JR: Tell us about your working in the IT bubble.

LK: First of all, I got into the whole IT business through a backdoor. I had been working for a couple of media companies writing news articles about the IT industry when I was offered the opportunity to maintain and develop one of the group's many websites. I took the chance. The site was implemented with PHP and the code was utter crap, although I didn't really understand the magnitude of that crappiness back then. I lasted there for some months before I decided to move on. I ended up joining one of the cool new media companies and started working on their two web-based products. That was the best move I could've made.

One of the products was a rather complicated implementation of an online collaboration desktop targeted at advertising companies and the other was an online printing service. Together these two products gave me quite good a maze to run through and I learned loads about a variety of Java-related technologies, common design patterns for web applications, JavaScript (back then we called it DHTML, not Ajax ;), and even C++ because part of the system was implemented in C++. Oh, that C++ code base was also horrible, horrible code but, in hindsight, it was fun to try and figure out what's wrong with that in-house PDF generation software when everyone else is on vacation and I'm looking at the code for the first time.

Around those times I worked practically around the clock on a computer--either at work or at home. I sometimes jokingly say that I got two days of working experience every day... I just couldn't resist the thrill of learning new stuff. I went back and forth between programming stuff in Java to figuring out more artsy types of technologies like Flash. This lunacy resulted in me implementing my own PNG, PDF and XLS generating libraries--that was the "file format era"--and a personal website with more animation than should be allowed by the law. Good times.

JR: Can you explain what is "Test-driven development" in one sentence?

LK: TDD is a development technique that helps you create and evolve a design in a highly disciplined, safe manner in small steps of writing a test, making it pass, and cleaning it up. How's that?

JR: Yes, that's one sentence... Next question: you wrote "Test Driven ..." because you wanted to write it? Your publisher wanted you to write it? Somebody else wanted you to write it? Whose idea was it anyway?

LK: I didn't really want to write it but the voices told me I should. I was afraid they'd tell me to do something bad if I didn't obey. Oh, and the publisher might've had something to do with it, too. Seriously, it all started thanks to Mike Curwen who acted as a matchmaker between myself and the folks at Manning. "Test Driven" wasn't actually the first book idea that was discussed. For example, we also briefly considered a book on continuous integration. I turned that down, eventually, as it looked like I was putting together a software manual. TDD, on the other hand, was a perfect match considering how influential it had been for my own development.

JR: Could you give us a brief tutorial on "How to write a programming book"?

LK: The most important thing to keep in mind is to type fast. If you have any technology-specific material, you'll end up rewriting significant parts of those sections every 6 months so you want to finish before the next wave of open source project releases wets your manuscript.

JR: What was your publisher's role in the whole process? What helped you most?

LK: One part of Manning's role in the whole process was to make sure I write a book and not a series of random articles. That is, the wonderful editors they assigned to my project kept reading my drafts and pointed out structural issues with the table of contents and so forth. They made sure that I'll close the wide gaps between sections that would confuse the reader and generally ensured that there's a clear path through sections, chapters, and parts. It's hard to say what helped me most because taking away any piece of the puzzle would have such a drastic effect on the quality of the book. If I'd really have to pick just one thing as the most helpful, though, I'd probably say it was the development editors' advice on writing well on the small scale--writing sentences and paragraphs that flow well and are easy to read.

JR: In your interview with JavaLobby you said: "Manning's editors did an amazing job in schooling me about the various techniques and nuances that make for a good text." Can you share one tip?

LK: When I had signed the contract, Manning shared with me their secret authoring toolbox that contained all kinds of guides, documents, that described what kind of text they are looking for, what kind of techniques an author can and should use, and so forth. For example, one of these techniques is called a "crutch".

JR: A "crutch"?

LK: Yes. A "crutch" is essentially an introduction based on a concrete example that highlights a problem that is difficult to solve without the to-be-presented concept. It's a technique for helping the reader reach the right frame of reference, understand why she should continue reading the section.

This is the kind of stuff that I hadn't really thought about before. It's like I "knew" the technique and sometimes used it without thinking, but I wasn't aware of what I was doing. This kind of small techniques really help stitch together a seamless whole and understanding them makes it that much easier to become a good writer. Some people have it in them and some have to learn it. I belonged to the latter group.

JR: This photo...

LK: That's me. My first "exit", as they say. I've only done that four times. I was supposed to continue this summer but tennis came into the picture and skydiving lost the duel.

JR: How did it occur to you to jump off the plane?

LK: It all started with a friend of mine starting to skydive some three years back. He kept pestering me about giving it a shot, too, until last year I said "maybe I should try it some day". A week later, I get an email from the skydiving club saying, "thank you for registering for the course." Obviously I had done nothing and my friend knew I hadn't so he went and registered me on my behalf. And once I was up there, do you have any idea how embarrassing it would've been to not jump? It was fun, though.

JR: What did you feel during your first "exit"?

LK: Standing in the doorway, staring at the plane's engine, my only thought was, "why doesn't he give me the sign already?" That is, the jump instructor was supposed to slap me in the ass when I can jump. It felt like I stood there for 10 seconds before the slap. Half an hour later, looking at a video of my first exit, I realized it didn't take longer than one second... When I jumped, the only thing I was thinking of was getting that delta shape and arching my back as I was supposed to. Three seconds after the exit, I was already just hanging there with an open canopy. It was a wonderful feeling just flying back and forth high up in the air.

JR: Now the penultimate set of questions... Let's talk about your book.

LK: Why does the penultimate set have to be about my book? Aren't I much more exciting? I mean, at least I have a pulse and opinions.

JR: Of course you are! So we are not going to talk about your book?

LK: Isn't that exactly what we've been doing all the time? I just think the ratio between book-related and other stuff can be more balanced and less penultimate.

JR: OK. Let's not talk about your book. The first words in your book are:

To my colleagues,
for bugging me to finish this project.
And to my love Lotta,
who gave me the energy to do it.

JR: Lotta.

LK: Lotta is my girlfriend. She's a rollercoaster who makes my day with her smile. And roll my eyes with her unfathomable logic. She literally says the opposite of what she means, except when she doesn't.

JR: Can you think about any other question you want to answer?

LK: I'm already quite happy with the volume of stuff we have but maybe you could ask me something about how TDD relates to my work or to agile methods.

JR: How does TDD relate to agile methods?

LK: Well, the strongest link between TDD and agile methods is XP or Extreme Programming. This agile method, created by Kent Beck at Chrysler, had a set of 12 practices, of which TDD was one. People have worked test-first already decades ago but it's really XP that brought sexy back for TDD. Nowadays, however, I find TDD being more of a standalone practice in that I see all kinds of agile methods be applied in combination with XP engineering practices such as TDD. While TDD isn't an agile method, it's almost always applied by people using an agile method--although that doesn't have to be the case.

JR: What about your next book? Do you have any plans?

LK: I have plans. Several of them. Right now, however, I'm just enjoying the luxury of not having a manuscript in my lap crying for the much needed attention it's not getting.

JR: We are almost done. Lasse, thank you for your time. The only thing we need to do now is to add some human touches to all this dry and boring stuff. Could you tell us some jokes, please?

LK: Jokes? Are you kidding? I'm a Finn, remember?

Discuss this article in The Big Moose Saloon!

WIRE
Return to Top
Interesting stuff elsewhere on the Ranch

Interesting stuff elsewhere on the Ranch

by Ulf Dittmer

Not all the good stuff is in these Journal articles. The Saloon sees lots of insight and wisdom all the time, and the various bloggers on the JavaRanch Radio are also busy turning out quality content. Plus, we've got book authors hanging out with us all the time. So here are a few nuggets you may have missed that should prove interesting to many folks.

Big Moose Saloon

In Pair Programming Sucks?, ranchers discuss the attractions and drawbacks of pair programming, as well as ways to maximize the former while minimizing the latter.

Last week's book promotion of The Art of Agile Development saw several illuminating discussions on various aspects of Agile methodologies: Practical difficulties of Agile, Team size and Scrum, Agile Breakdown and Time sheets in an Agile world

Everybody seems always on the lookout for the next web framework that has even more features than the last one. A small antidote to this trend is the FrontMan framework, which takes a minimalistic approach to functionality, and has recently seen increased attention and discussion.

JavaRanch Radio

Balaji has examined a range of products for Rendering XML, and presents the pros and cons of various approaches.

David has been looking for extra brains and muscle for his development team, and found an off-shore solution in an unlikely location: Off-shoring to the USA

Upcoming Promotions

On November 6, we've got Dmitry Jemerov answering questions about IntelliJ IDEA 7

On November 13, Johanna Rothman introduces Manage It!

Also starting November 13, Ryan Dewsbury covers Google Web Toolkit Applications

On November 27, David Heffelfinger dispenses server knowledge with Java EE 5 Development using GlassFish Application Server

On December 4, Andrew Stellman & Jennifer Greene present the latest Head First book: Head First PMP

On December 11, Herb Schildt serves up the Java Programming Cookbook

And on December 18, Cedric Beust & Hani Suleiman talk about Next Generation Java Testing

WIRE
Return to Top