Getting the right start

Starting out right is incredibly important. Someone once said, "choose your parents wisely." In software development I think that we really do have a chance at choosing our proverbial parents. Choose who you learn from wisely.

Depending on what your goals are pick mentors and teachers that exemplify those goals in their careers. The way these people think will alter the way you perceive the shape of what software is and how it should be made. The way you think about this things will yield either success or doom you to failure.

If I could get a "do over" for the last year and a half I would have started with getting to know who were the big thinkers in the land of Java. I would have spent some time reading their books. I would have avoided marketing fluff and I would have looked at real world experiences. I would have talked to real Java developers.

In short I wish I could have started my journey from C & Perl programmer to Java programmer by attending a conference such as No Fluff Just Stuff. Not because it would have eliminated any confusion... but because I would have learned what other real life Java developers think. How do real life Java developers solve these problems?

It would have made all the difference in the world. Too many developers suffer from what I call "old man on the mountain" syndrome. Instead of living the life of a hermit learning only from books, spend some time in the community learning from others.


I was wrong.

I was wrong about workflows. I was wrong about acceptance testing. I was wrong about scripting languages. It's time to fix that. The next few weeks will begin my quest to change the world and right these wrongs.

  1. Workflows are not ever the right answer unless they can be tested and debugged. If you can not test it you can not validate it. If you cannot validate it you will eventually see code rot.
  2. Business needs should be modeled in testing not just whether a unit of code functions but whether it helps to fill a business need.
  3. Scripting languages are a vital tool in the software developer's tool kit. You can create clean maintainable applications in the right scripting language. To dismiss dynamic scripting languages as toys is wrong.
Changing the world for the better...

Step one: Continuous Integration and Executable Documentation.


Symbolic Link Joy

Let's say you have a server. It runs the frobnicate service. The problem is you have to upgrade the frobnicate service every so often. Sometimes you have to "roll back" to an old version.

What to do?

Lately I've been thinking like this:

$ cd /usr/local/
$ mkdir frobnicate-dist
$ cd frobnicate-dist
$ install frobnicate1
$ install frobnicate2
$ ln -s frobnicate2 current
$ cd /usr/local
$ ln -s frobnicate-dist/current frobnicate

The result is that /usr/local/frobnicate is our currently running frobnicate. If you need to change the currently running frobnicate... change the frobnicate-dist/current and all frobnicate versions are in the /usr/local/frobnicate-dist directory.

Perhaps frobnicate-versions?

Just a thought.


Livin' and Lovin' the Groovy Life

I have seen the light and baby it's groovy. Write better, faster, lighter, groovier code. I may never write another shell script again.


Agile Test Driven Design Process Proposal

I am proposing the following software development pattern to our team next Monday. The idea is to create an environment where testing comes first, expresses business rules on a one-to-one and onto manner (borrowing a term from set theory). If a design element does not fulfill an acceptance test it is not developed. And, all development starts at test and ends in code.

  1. Business expresses a need.
  2. Business Analyst determines a use case.
  3. Software Engineer and Tester collaborate to create an acceptance test using business terms that will map down to classes or class structure. They use fitness to do this. Driving down from fitness tests Unit tests should provide 100% coverage. Code that is not covered should either get covered by a new acceptance test or get deleted. All tests of unimplemented code should fail on unimplemented method calls or null classes... in fact some initial tests will fail to compile since the classes simply don't exist. All tests that fail should represent one functional deliverable.
  4. Software Engineer partitions work between development teams. Teams fill out classes so tests pass. Weekly reports show the teams' progress. Each test maps onto each business need... as business needs get filled the number of passed tests increases. The ratio of passed to failed tests indicates the percentage of completeness of the project. Projects can go backwards... this is not good but it is possible.
  5. Once a number of passed acceptance tests reaches 100% the project is done. The version is branched and marked as a release and the software is shipped. Then the process starts over.
The practicalities need to get worked out but these are the basics.


NFJS 2007: RESTful Loosely Typed SOAP services

I just got back from No Fluff, Just Stuff 2007 (NFJS) and I went there with my document centric design ideas and came back after words with an idea that is far more powerful. RESTful Loosely Typed SOAP services.

Okay, I'll admit it... it would be hard to pull off a truly RESTful SOAP service but we nearly have all the components. It is much easier to pull off a Loosely Typed SOAP service and that is where the real power is.

There is quite a bit of support for a Loosely Typed SOAP service. Simply put SOAP services use XML documents and not structured data types defined in their WSDL. The cost is using strategy patterns to tear apart your documents. Since you can get any number of document versions you need any number of strategies to unmarshal them.

The benefit is that the marshaling and unmarshaling of data is done by strategy patterns that can be swapped out. One service end point can service multiple document process versions. Viola instant upgrade path that is also backward compatable.

The RESTful-ness is achieved by providing a set of "fetch" documents that would fetch things in an easy to understand way... the fetches would be polymorphic too. This is not quite RESTful since the restful ideal would be to be able to specify unique URI to get each item... but it is closer to the ideal than strongly typed SOAP.

I need to play with this more and write some examples.


Document Centric Design?

The Idea is that documents represent a single common data format for all processes. All processes produce or consume documents. A process that consumes no documents is called an originating process. A process that only consumes documents is called a terminating process.

Key Concepts:

  1. Business Processes shall produce documents
    • documents can never be changed
    • documents record answers & decisions
    • not necessarily real documents (like *.xml, *.pdf, *.doc) but perhaps table structure
  2. Business Processes consume documents
    • documents from other processes may feed this process
    • processes may develop natural dependencies based on the documents they need
    • processes may raise alerts based on the documents they need
    • some processes may not require any documents, these are originating processes
  3. Originating Processes begin a new workflow
    • they originate a new workflow
    • they have no prerequisite documents
  4. Business Processes are versioned and concurrent
    • clients default to starting the newest defined process under a given name
    • documents in process will finish in the version they started in (this is not to say you couldn't terminate processes to force people to use a new version )
  5. Interviews are Processes concerned with asking questions
    • Interviewees are the people taking an interview
    • An Interviewer is a person filling in an interview form for a person
    • A Self-Directed Interview is an online interview with no human interviewer (the computer is conducting the interview)
    • answers are unique to an interviewee
    • answers relate to facts that we can assert about an interviewee.

In addition consider that all updates should themselves be a new process and document.


Love for edgewall trac

I think I am in love with trac. The wiki makes for a convenient place to drop documentation. The wiki can link back to source. The source can reference wiki entries. Tickets can be referenced from source and from the wiki. Plus its all SVN and works nicely with eclipse or the command line. Nice job guys.


On my book shelf now:

In no particular order...
  • JBoss: A developer's Note book
  • Linux in a Windows World
  • JavaServer Faces
  • Applied Cryptography
  • Linux Administration Handbook
  • Ajax In Action
  • Javascript: The definitive guide
  • Cascading Style Sheets: The definitive guide
  • Service-Oriented Architecture: A field Guide to Integrating XML and Web Services
  • Java & XML (O'Reilly two lions book)
  • Organizational Patterns of Agile Software Development
  • Hibernate in Action
  • the zen of css design
  • applied Java Patterns
  • UML Distilled
  • EJB3 In Action
  • Agile Software Development
  • Ship it!
  • Communications of the ACM
  • The Linux Journal
  • API for SEVIS Batch Interface: Homeland Security


JBoss Portal 2.6.0 woe and the fix

I recently posted a problem in JBoss Forum and got an answer.

The problem was:

16:38:07,433 ERROR [StartupServletContextListener] Error initializing ServletContext
java.lang.IllegalArgumentException: Class org.jboss.portal.faces.portlet.JSFMetaBridgeViewHandlerImp
l is no javax.faces.application.ViewHandler

Which is consistent with deployment isolation issues. It turns out that you can't isolate the right classes between a 2.6.0 install of JBoss Portal and certain legacy JSF servlets. The class cast problem will follow you around.

The fix is to head on over to:


checking that out and running build/build.sh deploy on that... (make sure your JBOSS_HOME is set and no old versions of jboss-portal.sar are lying around). From the trunk directory...

$ export JBOSS_HOME=/usr/local/jboss
$ ./build/build.sh

After that life in JSF land is good. Very vexing problem if you are doing anything in JSF not specific to JBoss Portal


Suse Java5 install notes

I wrote this tutorial a while ago for our services group to help them setup Java on our production servers.

If you are on OpenSuSE

Open yast2 (CLI or GUI), and choose Software -> Software Management, next you'll search for java. Find a version of java that is 1.5.0_06 or better and install it. If java version 1.5 is not in your list then you'll have to add on more software sources (see: AddingSoftwareSources) then try again.

If you are on SLES10:

Download the Java EE 5 SDK from java.sun.com and follow the install instructions. Install path should be /usr/lib/jvm/ you could have the installer drop the jvm in a temporary location and then move it to /usr/lib/jvm/ later.

Note: Just because Java 5 is installed does not mean it is active.

A Standard Java Directory

If you are manually working with distributions of Java without an installer, all versions of java should end up in the /usr/java directory. Then you create two symbolic links... the "default" and the "latest" link. When linking the java binaries make sure to use the link passing through the /usr/java/default symbolic path. That way you can change which java the system is using by default simply by changing the default link in /usr/java without following the rest of the instructions for /etc/alternatives

$ ls -l
total 1
lrwxrwxrwx 1 root root 11 2007-06-13 14:33 default -> jdk1.5.0_09
drwxr-xr-x 9 root root 376 2006-10-12 16:01 jdk1.5.0_09
drwxr-xr-x 10 root root 472 2007-04-23 15:29 jdk1.6.0_01
lrwxrwxrwx 1 root root 21 2007-04-23 15:29 latest -> /usr/java/jdk1.6.0_01
This advice only applies if you don't already have a /usr/lib/jvm directory or you aren't relying on RPMs to manage your java versions. I believe later versions of OpenSuse have started to ship with RPMs that set up this /usr/java directory structure. Either way I'll point you at either /usr/lib/jvm or /usr/java as standard directories to use.

Manipulating the Distro

Fortunately, the SuSE distribution maintainers at Novell have done a good job of separating out the symbolic links for various programs, java being one of them. To activate one version or another of java in the SuSE distributions we can take advantage of the /etc/alternatives directory. By changing the sym links in this directory you change the active version of these programs.

Try the following:

$ whereis java
java: /usr/bin/java /etc/java /usr/lib/java /usr/share/java /usr/share/man/man1/java.1.gz
$ ls -hal /usr/bin/java
lrwxrwxrwx 1 root root 22 2006-06-29 16:06 /usr/bin/java -> /etc/alternatives/java
$ cd /etc/alternatives/
$ ls -hal java*
lrwxrwxrwx 1 root root 35 2006-07-05 10:04 java -> /usr/lib/jvm/java-1_4_2-sun-
lrwxrwxrwx 1 root root 37 2006-08-25 09:53 javac -> /usr/lib/jvm/java-1_4_2-sun-
lrwxrwxrwx 1 root root 39 2006-08-25 09:53 javadoc -> /usr/lib/jvm/java-1_4_2-sun-
lrwxrwxrwx 1 root root 37 2006-08-25 09:53 javah -> /usr/lib/jvm/java-1_4_2-sun-
lrwxrwxrwx 1 root root 37 2006-08-25 09:53 javap -> /usr/lib/jvm/java-1_4_2-sun-
lrwxrwxrwx 1 root root 37 2006-07-05 10:04 javaws -> /usr/lib/jvm/java-1_4_2-sun-

Uh oh. We have the wrong version of java active. Is Java 5 even installed?

$ cd /usr/lib/jvm/
$ ls
java java-1.4.2-sun java-1.5.0-sun jre jre-1.4.2-sun jre-gcj
java-1.4.2 java-1_4_2-sun- java-1.5.0-sun-1.5.0_06 jre-1.4.2 jre-1.5.0 jre-sun
java-1.4.2-gcj- java-1.5.0 java-sun jre-1.4.2-gcj jre-1.5.0-sun

Yes it is. I see java-1.5.0-sun-1.5.0_06 and that's just the java we need. Let's see what binaries we have...

$ cd java-1.5.0-sun-1.5.0_06/bin
$ ls
appletviewer HtmlConverter java javap jdb jsadebugd keytool native2ascii rmic servertool
apt idlj javac java-rmi.cgi jinfo jstack kinit orbd rmid tnameserv
ControlPanel jar javadoc javaws jmap jstat klist pack200 rmiregistry unpack200
extcheck jarsigner javah jconsole jps jstatd ktab policytool serialver

... these are the binaries we're going to symbolically link in /etc/alternatives. But, there are already symbolic links in the way we'll need to remove them and then set come back here to recreate the links.

$ pushd .
/usr/lib/jvm/java-1.5.0-sun-1.5.0_06/bin /usr/lib/jvm/java-1.5.0-sun-1.5.0_06/bin
$ cd /etc/alternatives
$ sudo rm `ls /usr/lib/jvm/java-1.5.0-sun-1.5.0_06/bin`
$ popd
$ pwd
$ sudo ln -s * /etc/alternatives/
$ cd /etc/alternatives
$ ls -hal java*
lrwxrwxrwx 1 root root 35 2006-07-05 10:04 java -> /usr/lib/jvm/jre-1.5.0-sun/bin/java
lrwxrwxrwx 1 root root 37 2006-08-25 09:53 javac -> /usr/lib/jvm/java-1.5.0-sun/bin/javac
lrwxrwxrwx 1 root root 39 2006-08-25 09:53 javadoc -> /usr/lib/jvm/java-1.5.0-sun/bin/javadoc
lrwxrwxrwx 1 root root 37 2006-08-25 09:53 javah -> /usr/lib/jvm/java-1.5.0-sun/bin/javah
lrwxrwxrwx 1 root root 37 2006-08-25 09:53 javap -> /usr/lib/jvm/java-1.5.0-sun/bin/javap

And now we have the right symbolic links in place. Test the default version of java:

$ java -version
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Server VM (build 1.5.0_06-b05, mixed mode)

good. Now we have the right version active.

NOTE: The Novell software that depends on Java 1.4 should be smart enough to pick out the right JVM for itself given the /usr/lib/jvm directory structure. We've just set the default java to 1.5.0_06 which works fine with our JBoss tools. If there is a problem in the future, knowing where the other JVM are located will be valuable. The word on the street is that Novell's QA couldn't finish their last round of testing in time for release.

NOTE: the environment variable $JAVA_HOME must point to the home directory of the Java install


The joy of symbolic links

I'm working with different versions of JBoss. My company has standardized on /usr/local/jboss as the home directory for JBoss. All JBoss servers will find their homes under /usr/local/jboss but we upgrade JBoss servers about once a year. As a developer often I'm swapping between production and test environments switching between JBoss versions.

For example today we are going to production with JBoss 4.0.5 but we are moving forward on JBoss 4.2.0 and I need to swap between the different versions for different projects. Now we already use symbolic links in production. Let me show you how those work.

The directory /usr/local/jboss is actually a symbolic link made like this:

$ sudo ln -s /usr/local/jboss-4.0.5 /usr/local/jboss

If we upgrade to jboss-4.2.0 I can simply remove the symbolic link and point it at the new directory like this:

$ sudo rm /usr/local/jboss && sudo /usr/local/jboss-4.2.0 /usr/local/jboss

And now my server is upgraded and there is an easy way to "fall back" should I need to.

But what if I'm a developer?

For my developer set up I'll head off to my home directory and then I'll make a JBoss directory where I'll keep all the various versions of JBoss that I'm using. I'll have a ~/jboss/jboss-4.0.5 and a ~/jboss/jboss-4.2.0 for example.

Next I'll make a symbolic link...

$ ln -s ~/jboss/jboss-4.2.0 ~/jboss/current

... and then I'll make one more symbolic link ...

$ sudo ln -s ~/jboss/current /usr/local/jboss

Now when I need to change my current working version of jboss...

$ rm ~/jboss/current && ln -s ~/jboss/jboss-4.0.5 ~/jboss/current


The Rules of Data Normalization

When Codd came down from the moutain top he held in his hands two stone tablets that had these rules graven upon them. One tablet contained the first three rules, the second tablet contained the other two. The rules are:

1. Eliminate Repeating Groups: Thou shalt not repeat the names of columns in a table. The key shall designate a unique row without repeats.
2. Eliminate Redundant Data: Thou shalt not repeat data in a table. The data in a table shall be unique for the whole of the key.
3. Eliminate Columns not dependent on the key: Thou shalt not put data in a table that relates to a column not in the key.
4. Isolate Independent Multiple Relationships: Thou shalt not put multiple relationships in one table unless they are related to each other
5. Isolate Semantically Related Multiple Relationships: Thou shalt not mingle semantically unrelated data in the same table.

The first three rules can be committed to memory using this saying: "The key, the whole key, and nothing but the key... so help me Codd."

Good database design will not number column names. Good database design will focus on what uniquely identifies data and not repeat the same data over and over again in the same table. Good database design will only relate columns to the key creating new tables for newly identified keys. Good database design will avoid master "relationship tables" that force all relationships to traverse them. Good database design will not mix un-related data just because they share the same key.

Thus saith Codd.

Woe unto those who do not heed the words of Codd for doom and swarms of Bugs will follow all those who fail to heed the wisdom of Codd.

Joy and prosperity will follow all who hear and obey the words of Codd for they will know the ever lasting peace of DataIntegrity.


Why A WorkFlow Engine?

Different problems lend themselves to expression in different languages. There are points at which a new tool is beneficial. Too many tools means that there are too many things to learn and that complicate work unnecessarily.

Consider the simplicity of chopsticks versus the complexity and elegance of formal cutlery as demanded by a formal table setting. Different utensils for salad, soup, main-course, dessert, and to stir your coffee or tea versus one pair of utensils for absolutely everything. Which is better?

Don't fall into the "hammer" problem, that's where you see every thing as a nail needing to be hammered. Yet, keep away from the Victorian table setting if at all possible. We have chosen to simplify Business Process Design at the expense of adding a new tool to learn. The tools are simple enough but will take time to learn how to use well.

And, if you missed it: Java is the chopsticks and jBPM is one utensil in a very big cutlery set.


Deep Structure

Deep Structure is a term from linguistics. Specifically Chomsky and his work with Universal Grammar. The term when used in computer science usually refers to meta-design-patterns or deeper computational constructs than those typically generalized by a pattern.

Programming language frameworks supposedly give us implementations of design patterns which are themselves expressions of deep structure computational models. Some people argue that the programming language should obviate design patterns... I don't agree.

A programming language should allow for the creation of design patterns organized into frame works that can be plumbed by specific implementations. The better job your design pattern implementations do of sticking near deeper structures the better you do to create an useful framework. The framework might even be better programmed in a different language.


The Woe of MySQL and java.sql.Date

The class java.sql.Date cannot hold a date of "0000-00-00" (ISO date format YYYY-MM-DD) because that is simply NOT a valid date. Our legacy Perl application uses the string "0000-00-00" as a date for any uninitialized date in the system. That is because the original system designer forbade the use of NULL for dates. This becomes a problem when working with Perl legacy dates in Java. Specifically the JDBC drivers will throw exceptions when attempting to work with a date that has the value "0000-00-00" and exception handlers for these exceptions are not prompted for by the Eclipse IDE.

I have developed a few strategies for dealing with this date woe problem.
On the issue of selecting "0000-00-00":

Using the NULLIF mysql function inside select statements means that you must map out every single select column returned and catch every single date so that it gets set to NULL for the JDBC drivers...

NULLIF(Candidate.CertificationDate, '0000-00-00') AS certificationDate

On the issue of saving "0000-00-00":

Since you can't create a date of "0000-00-00" you'll need to leave the date null but you'll have a problem setting the column NULL in MySQL since the column will be restricted to prevent your insert of a NULL value. Here's what I have done:

try {
ps.setDate(107, new java.sql.Date(a.getCertificationDate1().getTime()));
} catch (NullPointerException npe) {
ps.setString(107, "0000-00-00");

Note: The IDE doesn't "know" about the NullPointerException? since it can be thrown from every single line of code in every single java program ever written and handling it on every single line of code would get a little silly.

The Date stored in object a may be null. If it is we use the feature of MySQL that will take the string "0000-00-00" and map it into a date.

1. Q: Why not change the database? A: Perl programs look for the string "0000-00-00" to be returned indicating a NULL date (an uninitialized date). You will have to rewrite all these Perl programs.
2. Q: Why not work with dates in Java as strings? A: Java's date parsers are deprecated and you would have to perform custom parse and casts on these date strings since they do not match the Java date formats... if you wanted to work with the dates as dates. In other words: you would have to write your own date handling.
3. Q: Why not toString all dates for the database? A: Java and MySQL use different native date string formats... and we still would have to make special cases for "0000-00-00" any way.
4. Q: Why not write a custom Perl2Java Date class? A: Your company would have to dedicate a small portion of staff time to monitoring for changes in ISO date formats, time zones, DST, and watch for potential date bugs.

Other possible solutions

1. Write a helper utility class that would manage the casts taking all dates to MySQL strings. (only helps saves, can't help loads)
2. "fix" all the Perl programs and write helpers in Perl to handle the cases where the Perl programs need "0000-00-00" then set all null dates to null.
3. don't fix this and wait for the legacy Perl to age out.

NOTE: I found the answer to this problem here.

What is a workflow engine?

Workflow engines are a new way for representing knowledge in a computer. They are simmilar to RDBMS systems (DataBase Engines) in that they allow for the storage and organisation of facts in a specialized way. Workflows differ from Databases in that they represent different types of information and in radically different ways.

Traditional computer programs represent data in scalars which are single atomic bits of data. Scalars can be organized in arrays which are grids of data that may have 1, 2, 3, or more dimensions. You could think of a scalar as a single variable like "x" or "y" and an array as a spreadsheet.

Relational databases allow us to organize data in something simmilar to a spreadsheet with named columns called a table. However, databases do not stop there. There are rules called The Rules Of Data Normalization that help us master these additional aspects of the Relationships between data elements.

Workflow engines are not concerned with data specifically as are Databases, they are concerned with the concept of a Process Definition. These are often drawn by computer scientists as bubbles with arrows between them. In the past these were pain-stakingly coded by programmers using if-then-else statements and session management systems to distinguish different actors (people or programs) as they progress through a process.

When developing a Workflow driven program, programmer's focus is on how something happens, and a Process Designer's focus is on what happens next. A Process Designer may be a Programmer, a Business Analyst, or other semi-technical role. Just as Database systems require specialists eventually Workflow engine specialists will emerge. Workflows should not be confused with Rules Engines. Workflows are not completely non-technical and still require programming expertise.

As with any computer related discipline the development of a workflow system requires a linguistic and mathematic aptitude. The developer of a workflow must be able to follow the abstract rules of a formal logic system and also be capable of articulating complex logical proceedures to both humans and computers. These are a unique combination of skills that are not commonly found together in equal measure.

The concepts behind workflow engines are nearly as old as the ones behind the RDBMS but Workflows are still early in their "hype cycle." This may be in part because only companies such as SAP have been producing these engines pricing them out of reach for many companies. Many lessons are yet to be learned by the bulk of IT departments. The trick is to be enlightened about what the technology can actually do for us and not to get caught up in hype about the technology.


JAAS + Liferay + Woe

The problem:

I've written several EJB3 soap services that need to be secured by the PortalRealm security domain. When someone is logged into the portlet they can use the soap services... not logged in? no soap for you.

The woe:

No ClassLoaders found for: com.liferay.portal.security.jaas.PortalLoginModule

Which seems innocuous enough until you realize what would be entailed in fixing the class loader problem. I would need to either make my project a direct extension of Liferay or I would need to alter Liferay to extend a custom security module.

Neither solution is good. It would be better if Liferay used a common container managed security system. Perhaps my solution is to somehow combine the realms.


private social networking sites

Jeff Atwood has posted a entry Avoiding Walled Gardens on the Internet that advocates using open internet tools and avoiding products such as LinkedIn or Facebook. The reason we should avoid these tools is to avoid locking up our contributions in other people's safes. Since LinkedIn and Facebook control their sites your contributions to their sites are locked up forever inside their infrastructure.

Jeff's opinion has a ring of truth to it. However, I don't think this means you shouldn't participate in the closed networks, just be certain that if you contribute to a Facebook that you can also use your contribution in the wild and wooly web.