Friday, December 21, 2007

Dear Santa, Here's My List

Dear Santa,

I have been good this year. I have written intelligent unit-tests with plenty of code coverage. No empty catch blocks and tried to stay aware of threading issues.

Here is my list for this year. Please see attached.

thank you,
Michael Easter

10. "Oh Crap" Customizations

I want to configure software so that it ignores my "Oh Crap" moves. e.g. If I click on the A: drive, I want Windows Explorer to ignore me. If I type "google.cmo" into Firefox, I want it to no-op.

9. Snopes Plugins

I want a plugin for Firefox and Outlook that will confirm links and text against Snopes and alert the user that the given email is a hoax.

8. JSnopes

I want a website that lists "urban myths of Java" and sets developers straight on the current best practices. e.g. advice like "use StringBuffers everywhere" from 2001. Still accurate, or myth?

7. A Cap on DZone Down Votes

I want users on DZone (with which I have no affiliation) to have a limit of 10 down votes per week. That way, poseur naysayers can't blithely vote down everything they see. If a person runs out of down votes, they can express themselves with a comment on the site or, better yet, their own blog.

6. Please let "spaces in filenames" be just a bad dream, from which we will awake

5. Fitness as Games

I want treadmills, rowing machines, and other fitness equipment to be networked via games so that my gym becomes as fun and popular as an arcade.

Given the age/weight of Person A and Person B, weight the difficulty so that it's a fair battle. e.g. Can my heart-rate stay lower at 7.5 mph than yours at 5 mph? Then use this data to drive truly creative 3D games.

4. Python

I want to give Python at least half the coverage that Ruby gets. It deserves it. e.g. Why is it one of the very few approved languages at Google? Discuss.

3. Microsoft DeveLista

I want a version of the Microsoft OS that is geared toward developers:

  • No applications or bloatware.
  • Just give me the file system, drivers, registry etc, and the ability to add programs.
  • I might even pay the same amount IF you give me a modern way to edit environment variables!
2. Closures

I want the closures debate to be: rational, civil, and at times light-hearted. So far, so good, but I'm worried that things are going to get hot.

Jokes/spoofs are fine by me. The ideas put forth by the Big Players have been well-thought out, and even the regular joes are making sense. I just hope it stays that way.

1. Taser Task

I want an Ant Taser task that will send a signal to a USB taser and zap anyone who breaks the build. This includes me. I think it will make the workplace more fun.

Bonus points if the task can play a sound file of "Don't Tase Me, Bro" just before delivering the juice.

Thursday, December 13, 2007

Scala at St Louis JUG

Looking for something to do on a Thursday night, for a ray of sunshine in an otherwise bleak and desolate week?

Need a break from the hustle and bustle of holiday shopping?

Want some new icebreakers for a holiday party, so you can impress that person from Marketing?

Well, then come on out to the St Louis Java Users Group. Tonight, Tim Dalton will be presenting on Scala. I'm looking forward to it: a shiny new language!

If you can't make it, or aren't in the area, check out Tim's article over on the OCI Java News Brief.

Wednesday, December 12, 2007

Zero to RMI with Groovy and Spring

In a recent post, I leveraged Spring to write a simple client-server app using 50 lines of Java.

I've moved it to Groovy. I've included the code below, but here are some fast facts:

  • I used groovyc to compile the Groovy to class files, then used the java command.
  • I could only reduce the code by an import or two. However, I did save 220+ characters (notice how clean the Groovy is). Groovy gurus might be able to improve on this.
  • Note that the Spring config files have more namespaces for Groovy support. Discovering this was the hardest part of the exercise.

Here is the contract between the client and server. This would be in a common package:


interface EasyServer {
Message exchangeMessage(String user)
}

Here is a simple Message class. Of course, for RMI, being Serializable is vital:

import java.io.Serializable

class Message implements Serializable {
private final String message

Message(String message) { this.message = message }

String getMessage() { return message }
}

So far, so good. Now the server implementation:

import org.springframework.context.support.ClassPathXmlApplicationContext

class EasyServerImpl implements EasyServer {

Message exchangeMessage(String user) {
return new Message(user + ", Spring with Groovy rocks!")
}

static void main(String[] args) {
def context =
new ClassPathXmlApplicationContext("server_config.xml")
context.getBean("easyServer")
println("server ready")
}
}

It defines an easy exchangeMessage method and a starting main method. Spring takes care of the rest, as shown in the server_config.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/lang
http://www.springframework.org/schema/lang/spring-lang-2.0.xsd">

<lang:groovy id="easyServer" script-source="classpath:EasyServerImpl.groovy"/>

<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<!-- does not necessarily have to be the same name as the bean to be exported -->
<property name="serviceName" value="easyServerService"/>
<property name="service" ref="easyServer"/>
<property name="serviceInterface" value="EasyServer"/>
<!-- defaults to 1099 -->
<property name="registryPort" value="1199"/>
</bean>

</beans>

For running and compiling the server, simply ensure that these are in the CLASSPATH:
  • SPRING_HOME/dist/spring.jar
  • SPRING_HOME/lib/jakarta-commons/commons-logging.jar

Then it is up and away:

$ java EasyServerImpl

[ Spring magic dust snipped ]

server ready

The client is even simpler:

import org.springframework.context.support.ClassPathXmlApplicationContext

class EasyClient {
private EasyServer easyServer

void setEasyServer(EasyServer easyServer) { this.easyServer = easyServer }

Message exchangeMessage(String user) {
return easyServer.exchangeMessage(user)
}

static void main(String[] args) {
def context =
new ClassPathXmlApplicationContext("client_config.xml")

def easyClient = context.getBean("easyClient")

String output =
easyClient.exchangeMessage("CtJ Reader").getMessage()
println( output )
}
}

The client-side configuration XML:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/lang
http://www.springframework.org/schema/lang/spring-lang-2.0.xsd">

<lang:groovy id="easyClient" script-source="classpath:EasyClient.groovy">
<lang:property name="easyServer" ref="easyServer"/>
</lang:groovy>

<bean id="easyServer" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="rmi://localhost:1199/easyServerService"/>
<property name="serviceInterface" value="EasyServer"/>
</bean>

</beans>

Using the same CLASSPATH, but with a separate window, we establish contact like so:

$ java EasyClient

[ Spring noise snipped ]

CtJ Reader, Spring with Groovy rocks!


Cool stuff...

Tuesday, December 11, 2007

JetBrains Gets It

There was a tidbit couched in the recent announcement about Groovy 1.5: there is a joint compiler that eases the compilation of projects that use both Groovy and Java.

I want to highlight that JetBrains contributed it.

I have no affiliation with the company. I simply think that is very cool and a savvy business move with respect to goodwill.

From the Open Musings Department:

As I write this, I was about to joke that the joint compiler code might have an advertisement in the comments:


///////////////////////////////////////////
// "Brought to you by JetBrains, makers of Idea"

Maybe that's an idea? Hockey rinks, race cars, and baseball parks are plastered with ads: what if open-source projects allowed (regulated) ads in (a) the comments or (b) the startup console. Would that encourage contributions? Would it cause political issues? Hmmm.....

Monday, December 10, 2007

Zero to RMI in Minutes (or I *heart* Spring)

Recently, I paired with a colleague and sought to experiment with detached objects in Hibernate across a remote connection. Armed with some POJOs and Hibernate files from a project source tree, we decided to write a toy client and server from scratch.

(Admittedly, we had experience with Spring IOC: this is not a tutorial.)

We were fully experimenting with the sandbox in 75 minutes. This may not seem fast but it was astonishing: some days, it seems I can't empty my Recycle Bin in 75 minutes.

Partly for my own reference, but also for CtJ readers, here is a recap of the RMI portion. No Hibernate here. And an extremely "toy" project structure (e.g. no Ant, no packages). But the key idea is there, and it will showcase the power of Spring.

We used Spring 2.5. To be honest, I don't know if this is in Version 1.x. It may well be.

Here is the contract between the client and server. This would be in a common package:


interface EasyServer {
Message exchangeMessage(String user);
}

Here is a simple Message class. Of course, for RMI, being Serializable is vital:


import java.io.Serializable;

public class Message implements Serializable {
private final String message;

public Message(String message) { this.message = message; }

public String getMessage() { return message; }
}

So far, so good. Now the server implementation:


import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class EasyServerImpl implements EasyServer {

public Message exchangeMessage(String user) {
return new Message(user + ", Spring rocks!");
}

public static void main(String[] args) {

ApplicationContext context = new
ClassPathXmlApplicationContext("server_config.xml");

context.getBean("easyServer");
System.out.println("server ready");
}
}

It defines an easy exchangeMessage method and a starting main method. Spring takes care of the rest, as shown in the server_config.xml file:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<!-- EasyServerImpl is the implementation -->

<bean id="easyServer" class="EasyServerImpl">
</bean>

<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<!-- register the impl as the 'easyServerService' -->
<property name="serviceName" value="easyServerService"/>
<property name="service" ref="easyServer"/>
<property name="serviceInterface" value="EasyServer"/>
<!-- defaults to 1099 -->
<property name="registryPort" value="1199"/>
</bean>

</beans>

For running and compiling the server, simply ensure that these are in the CLASSPATH:
  • SPRING_HOME/dist/spring.jar
  • SPRING_HOME/lib/jakarta-commons/commons-logging.jar

Then it is up and away:


$ java EasyServerImpl

[ Spring magic dust snipped ]

server ready

The client is even simpler:


import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class EasyClient {
private EasyServer easyServer;

public void setEasyServer(EasyServer easyServer) {
this.easyServer = easyServer;
}

public Message exchangeMessage(String user) {
return easyServer.exchangeMessage(user);
}

public static void main(String[] args) {
ApplicationContext context = new
ClassPathXmlApplicationContext("client_config.xml");

EasyClient easyClient =
(EasyClient) context.getBean("easyClient");

String output =
easyClient.exchangeMessage("CtJ Reader").getMessage();

System.out.println( output );
}
}

The client-side configuration XML:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<bean id="easyClient" class="EasyClient">
<property name="easyServer" ref="easyServer"/>
</bean>

<bean id="easyServer"
class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl"
value="rmi://localhost:1199/easyServerService"/>
<property name="serviceInterface" value="EasyServer"/>
</bean>

</beans>

Using the same CLASSPATH, but with a separate window, we establish contact like so:


$ java EasyClient

[ Spring noise snipped ]

CtJ Reader, Spring rocks!

This trivial example uses approximately 50 lines of Java, with no knowledge of RMI. Amazing. It an easy exercise for the reader to package it up into a more formal project, using Ant etc. It is more challenging to add Hibernate, but still tractable: the basic wiring for a client-server playground is right here.

I'm curious as to how many lines of code this would take in Groovy. I think 40 would be easy to attain.

That's cool. I *heart* Spring!

ps. I lifted "*heart*" from Eric.

Tuesday, December 4, 2007

Zen and Groovy's Expando

In the past, I had trouble remembering the concept behind Groovy's Expando class. I knew it wasn't difficult but it was elusive. Perhaps I was distracted by the groovy-ness of the name.

In a recent training class with Jeff Brown, I was struck by a metaphor.

Readers of CtJ know the old refrain of dynamic-typing:

If it walks like a duck and quacks like a duck, I would call it a duck.

In other words, if "it" can provide the desired behaviour (e.g. quacking), then it can pass for a duck, in so far as a dynamic language cares. Cool beans.

Well, in Groovy, the Expando class is an empty "it"! It is a container for various behaviours, to which we can add stuff. Check out this code sample:


// tests the incoming, purported "duck" to see
// if "it" really quacks
def duckTester = { duck ->
duck.quack()
}

////////////////////////// Main

// create "it"... it cannot quack -- yet
def it = new Expando()

// add quacking
it.quack = { println "quack!" }

// call test: "if it quacks like a duck"
duckTester.call(it)
See? We create "it", then add quacking behaviour, and then test it. Easy. This prints
quack!
to the console.

Question: does anyone know the origin of the Expando name?

I've searched but not found it.

ps. A less glamorous way of thinking about it is that Expando is a map of methods and attributes. I'm sticking with ducks and it.

pps. Expando's are especially useful for mocking objects in unit-tests.