Rainy days and Java always get me down


I've Moved My Blog

It's currently located at http://www.urlinone.com/blog

I should say "I'm moving my blog." It's a pretty painful process.

Pebble has blown up on me, and it's been many months since I've been able to blog reliably. I've lost posts. And now I've got to figure out how to migrate my past blog posts from Pebble to my new destination without all the URLs changing, lest external links become 404 Not Founds.

Why does everything in the 21st century have to be a three-day project???

I'm not sure if local search is really the new killer app, but I've got no shortage of options at the moment. I needed to find all the emails I've received from WasteIndustries. I ran all three searches at the same time, pitting the various search tools against one another.

I started Outlook first, because I knew it was slow. Next, I started Lookout, because it's convenient, right there in the Outlook toolbar. Finally, I double-clicked on the Google Desktop icon in the taskbar and waited while a browser opened up.

Google Desktop came back almost immediately with six hits. The downside of Google Desktop (aside from the fact that it's a long name to type every time I mention it), is that it doesn't provide native access to these items. If I want to open, delete, or move these emails, I have to click once on the item in the search results and then on "View in Outlook," not to mention having to go back to the search results for subsequent items. It's fast and powerful searching, but it has the disadvantage of being browser-based.

Lookout finished a close second (although it wouldn't have been as close if I had already had a browser open to Google Desktop). Lookout's main problem is that I can't delete items from its search results list. Very often, I'm trying to whittle away at the *mumble mumble* thousand emails in my inbox (okay, so I'm an email packrat -- according to Lookout and Google, that's okay, so leave me alone), and Lookout's search is nearly worthless for that, because I can't delete what I find without opening each item and deleting it manually. If they would fix that, Lookout would be the top choice for email searches.

Outlook search was just sad. I let it chug along for about a minute, beating the crap out of my hard drive, and then I just stopped it. When it finally finds what it's looking for, it's the best, because its search results list items are just like the items in the inbox itself. You can delete, flag, mark as read/unread, etc. They are native Outlook email objects.

Too bad there's no way to pipe Google Desktop's or Lookout's search results to Outlook, so you could combine the best search with the best native item handling. More and more, I think we'll see that kind of integration become possible, as software becomes more service-oriented and pluggable. Google Desktop could be a search service that feeds to an Outlook item list service. All we have to do is re-engineer every piece of software that's ever been written, and we're good to go.

Anyone who's ever looked at URLinOne knows that I'm always looking for ways to expedite my access to online information. In the past, one of the things I started doing was using Start > Run to quickly get to a browser when one wasn't open. I would just type the URL in there (or just enter about:blank) to get a browser open. (One other little tip that few people know is that the Windows key on most keyboards has some nice shortcuts. Windows-R opens the Start > Run dialog box without having to click anything.)

Anyway, if you have the Google Deskbar installed, you can paste or type a URL in there, and it will open a browser to that site. Pretty sweet.

The other thing it's really great for is spell check, dictionary, and thesaurus. Type or paste a word and do Ctrl-D to get a definition. Ctrl-T for thesaurus. And just search with the word to see if it's spelled right. If it's wrong, you'll see "Did you mean..." at the top of the search results.

Good stuff, Google.

Groovy is one of the hot new things in the Java world. It's a powerful scripting language that integrates both ways, i.e. you can call Groovy scripts from within your Java code, and you can access your Java objects from within your Groovy scripts. In fact, Groovy classes become plain old Java bytecode, so there is ultimately no real distinction between the two. In the Groovy language, you have many powerful constructs including closures.

Here are the steps I took to add a little groovability to my AppFuse 1.5 app. I realize that AppFuse 1.6 is out, but I'm in the midst of a 1.5 development, and I suspect that these steps won't change much, if at all, between 1.5 and 1.6.

  1. Download Groovy from here. Treat yourself to the freshest version available.
  2. Unzip it. FWIW, I unzip all downloaded software to c:\sw.
  3. Create a directory in your AppFuse app for the Groovy distribution. I created c:\projects\optioninsight\lib\groovy-1.0-beta-7.
  4. Copy groovy-1.0-beta-7.jar to your new directory.
  5. Create a lib directory below the new groovy directory.
  6. Copy asm-1.4.3.jar and asm-util-1.4.3.jar from C:\sw\groovy-1.0-beta-7\lib to your lib\groovy-1.0-beta-7\lib directory.
  7. In the top-level lib directory off the root of your appfuse application (in my case, that's c:\projects\optioninsight\lib), edit lib.properties.
  8. At the bottom of lib.properties (or anywhere else you like within the file) add the following
    #
    # Groovy - http://groovy.codehaus.org/
    #
    groovy.version       = 1.0-beta-7
    groovy.dir=${lib.dir}/groovy-${groovy.version}
    groovy.jar=${groovy.dir}/groovy.jar
    
  9. Edit build.xml in the root of your AppFuse application (c:\projects\optioninsight, in my case).
  10. Locate the line </war> in build.xml. Just before that line add the following:
                <lib dir="${groovy.dir}" includes="*.jar"/>
                <lib dir="${groovy.dir}/lib">
                    <include name="asm*.jar"/>
                </lib>
    
    This will add the jars required for Groovy to your war file during deployment.
  11. Now edit properties.xml, in the same directory as build.xml.
  12. Locate web.compile.classpath within that file. Between the <path> and </path> statements add the following:
        <fileset dir="${groovy.dir}" includes="*.jar"/>
    
    This adds the Groovy jar to the classpath for compiling the web module. I haven't done this, but I would imagine you have to add the same line to the other classpaths, if you want to compile Groovy into the dao or service layers. In fact, the way I read properties.xml, anything included into dao.compile.classpath will be included in service.compile.classpath, so you could include this line in dao.compile.classpath and have Groovy available in all three AppFuse layers.
  13. At this point, you should be able to access Groovy within your web layer. As a test, I added a bit of Groovy code to StartupListener.java to make sure it was available. Within the contextInitialized() method, I placed the following:
            // Groovy Shell - call groovy expressions from Java code
            Binding binding = new Binding();
            binding.setVariable("foo", new Integer(3));
            GroovyShell shell = new GroovyShell(binding);
    
            Object value = null;
    		try {
    			value = shell.evaluate("println 'Hello World!'; x = 123; return foo * 10");
    		} catch (CompilationFailedException e1) {
    			// TODO Auto-generated catch block
    			e1.printStackTrace();
    		} catch (IOException e1) {
    			// TODO Auto-generated catch block
    			e1.printStackTrace();
    		}
    		if (log.isDebugEnabled()) {
    			log.debug("Groovy return value: " + value);
    			log.debug("x: " + binding.getVariable("x"));
    		}
            
            // GroovyClassLoader - load an external Groovy script file
            XmlWebApplicationContext ctx =
                (XmlWebApplicationContext) context
                    .getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
            if (ctx == null) {
                // if the context is null, it's likely because the listeners
                // aren't initialized in the same order they're specified in
                // web.xml.  This happens in Tomcat 5.
                ctx = new XmlWebApplicationContext();
                // get the config locations from context parameters
                String configLocations =
                        context.getInitParameter(ContextLoader.CONFIG_LOCATION_PARAM);
                String[] files = configLocations.split(",");
                for (int i=0; i < files.length; i++) {
                    files[i] = files[i].trim();
                }
                ctx.setConfigLocations(files);
                ctx.setServletContext(context);
                ctx.refresh();
            }
            
            LookupManager mgr =
                (LookupManager) ctx.getBean("lookupManager");
            ClassLoader parent = mgr.getClass().getClassLoader();
            
            GroovyClassLoader loader = new GroovyClassLoader(parent);
            Class groovyClass = null;
    		try {
    			log.debug("Loader: " + loader);
    			groovyClass = loader.parseClass(new File("/sw/tomcat-5.0.19/webapps/optioninsight/scripts/HelloWorld.groovy"));
    		} catch (CompilationFailedException e2) {
    			// TODO Auto-generated catch block
    			e2.printStackTrace();
    		} catch (IOException e2) {
    			// TODO Auto-generated catch block
    			e2.printStackTrace();
    		}
    		//         lets call some method on an instance
            GroovyObject groovyObject = null;
    		try {
    			groovyObject = (GroovyObject) groovyClass.newInstance();
    		} catch (InstantiationException e3) {
    			// TODO Auto-generated catch block
    			e3.printStackTrace();
    		} catch (IllegalAccessException e3) {
    			// TODO Auto-generated catch block
    			e3.printStackTrace();
    		}
    		Object[] args = {};
            groovyObject.invokeMethod("run", args);
    
    Now, there's quite a bit of ugliness there. Almost of this is related to the fact that I had to find a class to get a ClassLoader from. I ended up copying a bunch of code from setupContext() at the bottom of StartupListener.java. In retrospect, I probably could have found a better place to run my Groovy test, but availability at startup was what I was after.

    One of the trickiest parts of this whole process was figuring out where the classloader was looking for the script file. As far as I can tell, the path is relative to the root of the hard drive, which is not what I expected. I would have thought that it would be based on the root of the web app or Tomcat, but neither seemed to be the case. Keep in mind that it all depends on what classloader you get, and that is dependent upon what class you get it from. I'm still working on understanding this bit of arcane magic.

  14. The contents of HelloWorld.groovy can be whatever you want, of course, but this is what I had to get you started:
    println "Nice cheese, Gromit!"
    println "----------------------- scripts directory ---------------------------"
    
    I found it helpful, when I was hunting for my script file, to put it in numerous locations with some identifying text, so I knew which one was running.

This entry doesn't actually do anything useful, but it should make Groovy available within your AppFuse environment, so you can start to take advantage of it. Groovy seems like a very powerful tool that can greatly enhance the power of AppFuse. If nothing else, it's a way to make changes without having to repeatedly recompile, redeploy, and restart Tomcat. Once you have the logic down, you can pull the Groovy code into Java, although I'm not sure that's even necessary. It would be nice to hear some Groovy best practices from someone with real world experience.

Yeah baby, yeah!

I'm surprised Bill Maher allowed them to air this week's installment of HBO's Real Time with Bill Maher. Former CIA Director James Woolsey made Bill and his two anti-Bush guests look like the emotional, uninformed, knee-jerk liberals they are.

Mr. Woolsey was quite frank in his criticism of President Bush's administration where fitting, but he also, with his Bob Newhart-esque demeanor, shoved all their rhetoric, propaganda, and hype back down their throats. He made it clear that it was not a mistake, a lie, or inappropriate to link Saddam Hussein with Al Qaeda.

It was a pleasure to watch them squirm as he shot down the mantra they've been chanting for months. Too bad none of it sunk into their thick skulls. They'll continue to believe what they want to, because they aren't interested in the truth. Never let facts get in the way of a good smear campaign, right, Bill?

And just to really drive home the point that Bill Maher is the most irrational, hyperactive whiner on cable television, Dr. Bernadine Healy of the National Red Cross [apologies for not getting her title] made Bill look silly and childish with his nonsensical arguments and inaccurate views on vaccinations and medicine. It was like watching a teacher gently correct the rantings of a tantruming student.

Bill can be tough to take for any period of time. He is so righteous, so judgemental, so intolerant, and so wrong that it's hard to watch. This episode was much better, though.

Great show, Bill! You keep this up, and I'll be a regular viewer.

Maybe you should consider renaming the show to "'Yeah, But...' with Bill Maher."

It never ceases to amaze me how much gets blamed on Presidents, versus what's really in their power.

Kerry, who himself would be President, and who surely knows what a President is and is not capable of, loves to blame Bush for healthcare and jobs, neither of which is under any President's control.

Aside from the fact that inputs into these complex systems take months and often years to propagate through, Presidents are not the ones who write laws. Kerry has been in the Senate for twenty years; he's had more opportunity to affect healthcare and jobs than Bush has. Why doesn't he blame himself for these problems? Because it's not politically expedient.

Does anyone remember Clinton's first term, when he and Hillary were going to fix the American healthcare system? That went on for at least a couple of years. Great job, guys. I'm so glad you solved that problem, so that it wouldn't be a campaign issue twelve years later. This is an example of a horribly complex, nth-order system that it is simply stupid to blame on Bush, as if he's the reason that millions of people do not have coverage. And anyone who votes for Kerry because they think he's going to get them healthcare is a sucker.

Kerry also loves his nonsense about "this President being the only President since the Depression to lose jobs." First of all, jobs don't come from the President; they come from nasty, evil corporations. Second of all, Bush took office in the midst of a major economic downturn and then 9/11 only added to the severe situation. It's very convenient for Kerry to blame Bush, but that's completely unfair. No President, not even the great John Kerry, could have done a thing to prevent those companies from laying off workers. On top of that, we had all the corporate scandals (Enron, Worldcom, etc.), which did even more damage to the economy.

I might also add that these problems, the dot-com bomb, the 9/11 attacks, and the corporate corruption, all grew and festered on Bill Clinton's watch; Bush was just foolish enough to take the reins. If you want to blame a President, blame Clinton. Bush's first term was really the hangover from eight years of Clinton irresponsibility. To be fair, though, I don't think you can even blame Clinton for the dot-com bubble or the corporate corruption. His failure to recognize the growing threat of Al Qaeda for what it was, I do think he bears responsibility for. And that same lack regarding terrorism is exactly what I expect from John Kerry.

The reality, though, is that economies are bigger than any President, and they outlast any President's administration. Presidents don't hire people. Presidents don't write laws. Presidents are basically people who point in a direction and say "I'm taking the country that way." It's usually years before we can see the progress of his journey.

It really bugs me that politics and politicians can't talk honestly about this. They use the public's ignorance to sling mud at the emotional level and place blame that educated people understand is unfounded. Why can't we raise politics to a level where we can talk about real issues and solve real problems? Why is it all about posturing and cheap accusations? It's probably because that's what the American public responds to, unfortunately.

This is why less government is better. Corporations, for the most part, are honest, because the bottom line is what matters. It's not about tricking people into believing your rhetoric. Business is about offering a product that people want at a fair price. Politics is about fooling people into putting you into a job where they can no longer really see what you're up to. Corporations really try to innovate and solve problems, while politicians, for the most part, simply try to get elected.

To me, Kerry is exactly that kind of a politician. He is interested in getting elected, because it's the next thing he'd like on his resume. He's already envisioning the decor of his Presidential library. I think George W. Bush actually sees himself as part of an epic struggle for Good to triumph over Evil. Whether that makes him a megalomaniac or not is another story. But at least he's got a vision and a mission bigger than himself and his own glorification.

...crafting a two-hour commercial for the Kerry campaign that goes down like a documentary. It was so effective that I actually feel like Kerry being elected isn't the end of the world. I can only imagine how swing voters will feel after watching it.

After the first hour, I thought, "well, Kerry and Bush were very different in their youth; Bush will make up ground in the second half." However, Frontline had plenty more "materiel" for the second hour. And it's so subtle that you barely notice it's happening.

Depending on how many people actually watch it, I honestly believe this program may have changed the outcome of the election. Very impressive, public television.


We haven't suffered a terrorist attack on American soil since 9/11/01. All the gosh, we're sorry's and I guess we were wrong's aren't going to mean much when we get hit again. Kerry's failure to recognize and reluctance to act on the absolute realities of terrorism scares the hell out of me.

Bush tried to get allies lined up, but they weren't interested. If Kerry can't get the world to buy in, he's not going to act. That puts us in grave danger. Kerry's overanalyzing and inaction are terribly dangerous when we face suicide bombers, beheaders, and other madmen. Most of the rest of the world is not going to back us. They'd rather sit back and stay "safe" while we become the primary target.

One thing that documentary did show me is that Kerry's Vietnam experience makes him unfit to command. We don't have the luxury to be anti-war in the world of Muslim terrorism. Kerry's mindset after Vietnam makes him a liability. The fact that Vietnam is what he points to in describing himself indicates just how entrenched his thinking is in post-Vietnam waffling and misgivings. We simply can't afford that. The very future of America is at stake. Remember 9/11.

On a mailing list from a former employer, someone just posted the following (edited to protect their identity):

My son is over in Iraq. A few weeks ago, he said to me "I've got my job to do here. Your job is to go out and help get Kerry elected!" You might say I have a vested interest in ousting the man who put my baby in "the wrong war, at the wrong time", to quote Senator Kerry. I'd feel much better about his deployment if he were in Afghanistan or Sudan - someplace that makes sense!

I daresay that this same person, and the rest of the Kerry supporters (along with most Bush supporters), had they been asked on September 10, 2001 about going into Afghanistan or Sudan, would have said "wrong war, wrong time." Had we inspected Afghanistan on 9/10/01, we would have found no weapons of mass destruction. By the standards we suddenly find ourselves so attached to, it would have been difficult to justify such an invasion. Yet, that invasion is now justified in most peoples' minds, including Kerry supporters.

Over the course of his eight years in office, Clinton got away with several military maneuvers including Bosnia, Somalia, and even bombing Iraq with 200 cruise missiles over a four-day period! Where were the standards then? What made each of those "the right war at the right time"? Was it just his lack of commitment to actually winning that made it palatable? Or was it just the fact that he was a Democrat?

Had we invaded Afghanistan and captured Osama bin Laden prior to 9/11/01, many people would have objected. However, if we had prevented the attack on the World Trade Center and Washington, D.C., there would have been no way of knowing what disaster had just been averted. Yet, it still would have been the right move. How, then, can people be so damned sure that eradicating the Saddam Hussein regime was the wrong move? Is it possible they are just using that strategic move as an opportunity to bash a political foe?

Hindsight is 20/20. It is so easy to second guess the choices made by someone else after the fact. Candidate Kerry would have us believe his foresight is as keen as his hindsight. But even hindsight does not give you the benefit of seeing what might have been. Hussein had years to develop all kinds of weapons and then conceal or export them. Look how long it took to find Hussein, himself, living in a hole. For all we know, Bush's invasion of Iraq prevented a 9/11-style attack with nerve gas. Or maybe he was too late, and it's still sitting underground in Iraq or hidden in Syria, yet to be deployed.

But it's awfully cheap and easy to just say "wrong war, wrong time" when you have no idea what could have been. There's a reason Saddam Hussein refused to comply for so many years. I'd rather accept Saddam Hussein's evil intentions at face value, consider his unwillingness to comply with the weapons inspectors as the crime it was, and be safe rather than sorry. If you choose to opportunistically use this perfectly valid interpretation against the President who had the nerve to act, even though it was unpopular, I hope you're right, because the cost of being wrong is another 9/11 or worse.

And I don't think Kerry has the nerve or the conviction to do anything unpopular, based purely on principles. So, be an ostrich, if you like. Just hope you're a very lucky ostrich, because these Muslim terrorists are not kidding around. How many more horrific acts must they commit before you are convinced?

It's amazing how the sound bites and headlines claim to tell the whole story, when they are really intended to mislead and convince you not to look any deeper.

From Power Line Blog:

I've barely had time to dip into the Iraq Survey Group's report, but it's apparent that the report is a treasure trove of information. No one could read even a small portion of the report and conclude that "Iraq had no WMDs" is a fair summary of its contents. [My bold.]

I used to scoff at the "liberal media," but the headline that "Iraq had no WMDs" as the sum total of the Iraq Survey Group's report is offensive, unfair, and an abuse of the power of the press.

Liberals don't play fair. They play to win. At all costs.

This content has been aggregated from another source. Read more...

For over four years, I've been not selling an options trading program I wrote in the wee hours of the morning over the course of late 1998 and 1999 called Option Insight. All this time, I've been snagging free quotes from the CBOE web site.

This weekend, the CBOE very unkindly changed their protocol without telling anyone. Option Insight died, no longer able to retrieve quotes. When diplomacy failed, I had no choice but to hack.

The page to download quotes still worked, but it wasn't working from Option Insight, so I had to get to the bottom of what was different. I first tried simulating the javascript in the page, but that failed. I knew I had no choice but to sniff the packets and see what a browser looked like, so Option Insight could look the same.

The beauty of this process is that in a matter of fifteen minutes, I went to SourceForge, located a free HTTP packet sniffer (Packetyzer), downloaded it, installed it, and had it capture the first trace. This is magic! I'm not talking about the product, although it is enormously amazing. I'm talking about the treasure trove that is the web!!!

Admittedly, the web is most useful for solving problems caused by the web... but it's still cool! :-)

It can be confusing to automate processing of PayPal transactions in a web app, because you have a couple of seemingly overlapping choices.

PDT (Payment Data Transfer) is a way to get information about a transaction that a user in a current session just completed within your web app. The basic flow is that the user selects something to purchase at your site, is directed to PayPal's own pages to complete the transaction, and then returns to your site where you can display information about the completed transaction.

IPN (Instant Payment Notification) is actually more of a behind-the-scenes, server-to-server transaction, in which PayPal notifies you of a transaction, asynchronously. That is, no one has to be logged on to your web site for an IPN to be completed.

This means that a user purchasing something from your site actually kicks off both a PDT and an IPN. How do you deal with that, then? A good rule of thumb is to update your database on IPNs only. The PDT is a good way to give the user confirmation in the presentation layer, but rely on IPN and only IPN to log the transaction or credit an account in your persistence layer.

There is some good information here:
How PDT and IPN work together

Sometimes the littlest changes make the biggest difference. I'm using this one all the time now.

I created a new code completion template in Eclipse. (Go to Window > Preferences, then Java > Editor > Templates.)

I added a new template called dbg in the java context. It is defined as

if( log.isDebugEnabled() ) {
    log.debug("${cursor}");
}

Now, any time I want to log something, I just type dbg<Ctrl-space>, and I'm in position to type my logging message. (I just saved myself three minutes a day! Let's see, what am I going to do with that time? I think I'll learn a new language!)

Naming the template dbg is preferable to debug because there are no naming conflicts with dbg. If you name it debug, you have to confirm that you want the template named debug, as opposed to one of the many classes whose name starts with "Debug".