Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

2007-03-04

Hudson

Hudson

Back in days of yore (circa 2002, I think), Mr. Gettle and I created a Development Portal. It was our home-grown continuous integration server. We wrote it because we needed a common place to create binary distribution of our software.

We just started using Hudson at Versatile. I'm really impressed. It's a snap to install and I had it building our project in no time.

Here are the features I like:

Painless Install
- Just drop the hudson.war file in a servlet container, go to the Admin Page and start configuring your projects.

Great UI - Intuitive design, inline help, pretty graphs, AJAX stuff. Sold!

Email Notifications - Hudson notifies the developers of broken builds and when a build is fixed. It also sends special emails to the suspected build-breakers. The suspects are simply the developers who have committed code since the last successful build.

Multiple Projects - Hudson manages as many projects as you want. You can even set up project dependencies. With this, projects that depend on a core project are automatically rebuilt if the core project is successfully built.

Multi-Threaded Builds - You can specify how many build processes can be run concurrently, allowing you to throttle how hard the build server is pushed.

Distributed Builds
- What an amazing feature. If you have a weak or overworked build server, you can specify slaves boxes to handle some or all of the load.

SCM Integration
- Hudson can watch the source code repository and kick off a build when changes have been made. You can also create a CVS branch/tag right from Hudson. Sometimes creating a branch can take some time, in that case, Hudson will email when it's finished. And finally, you can view all of the source via the Hudson interface just like ViewCVS.

All that said, the Hudson website has this gem listed in the Benefits section:
No more "full rebuild" before a commit:

With Hudson, I stopped doing a rebuild before I commit. Nowadays I just commit, and let Hudson check if a build fails or not for me. Meanwhile, I move on to work on other things. If a build fails, Hudson can tell me so within a few minutes, so breaking a build for that short period of time is not really a problem. Thanks to this, I can spend my time more productively.

-- said the developer nobody wants on their team.

2007-02-14

Unit Testing: still rewarding

I'm not going into all of the obvious virtues of unit testing. If you're a developer and you don't know them, you should probably find a new career.

I didn't like unit testing. I didn't like spending my time writing a test when there was plenty of useful code to be written. Working at Capital Blue Cross for a year changed all of that. My partner, Andy H., insisted that I write a unit test for every part of the system. My work wasn't considered done until the corresponding unit test was written. What a taskmaster. Consequently, I didn't feel productive at all.

Near the end of the project, it was time for us to start running the application through its end-to-end testing. After a few runtime setup environment problems and false starts, the application ran without a problem. It was one of those "Did it just run without a problem?" moments of disbelief. Not only did it run without crashing, it produced the output we were expecting. Hopefully Andy will back me up with a comment so my readers know that I'm not making this up.

OK, so unit testing produces applications with less bugs. Duh. If you didn't know that, or worse, you don't believe it, please stop reading now.

Now for the benefits that I wasn't expecting.

Writing testable code means writing readable and organized code. For example, I wrote an object responsible for building an email using contextual data and a template and sending it. I blew through the implementation pretty quickly. In no time, I had a 150 line method that did it all. OK, time to test. Congratulations jackass, you just wrote a lump of untestable code. I was forced to break the huge-ass method into smaller, more testable, methods. When I was done, I had a class that was easier to read. Even better, I had a class that was tested.

No more Winnebago classes. We've all done it. "Oooh, I know, I'll add this neat feature. No one needs it right now, but someone might need it in the future." When writing code with unit testing in mind, you tend to skip those neat-o features when you also have to write a test for them. The result is lean code that does only what it has to do.

Writing unit tests forces you to think about the design from a different perspective. You may write a nicely organized class that is easy to test, only to realize a design flaw while writing the unit test. After writing a unit test with 70 test methods, you may think the class would make more sense if it were broken into two classes.

Even though I've had mostly positive experiences incorporating unit testing into my development cycle, I still feel unproductive while I'm writing a unit test. Hopefully this feeling will change. I guess I feel unproductive because the benefits are delayed. I take great pleasure in watching 16 unit tests fail because a developer (probably me) made a "simple change" to a core class.

2006-09-25

Hibernate's New Clothes

Ever since it's inception, Hibernate has been touted as the savior of the database centric application. Its Object-Relational mapping defined externally to the application code was going to eliminate thousands of lines of code for doing Create, Read, Update, and Delete (CRUD) database activities. Every press article I've ever read has nothing but good things to say about Hibernate. If you as a developer are not using Hibernate, there must be something wrong with you.

There's a fairy tale written by Hans Christian Anderson entitled The Emperor's New Clothes. In a nutshell, the story is about two smooth talking tailors who convince the Emperor that the invisible clothes they have made for him are the most exquisite in all of the kingdom. The tailors added that anyone who couldn't see how remarkable the clothes were was obviously a fool. Not wanting to be thought a fool the Emperor "dons" the clothing, and strolls through town completely naked. All of the townsfolk, not wanting to be thought fools either, praise the craftsmanship of the clothing. Only a single boy in the kingdom has the courage to say that the Emperor is not wearing any clothes.

Well, I just have this to say, "Hibernate, put some clothes on!"

I had another run-in with Hibernate the other day. I was working with a very simply database model.

ERD Diagram

I was using Hibernate to do the normal CRUD operations. Until I tried to do something fancy.

I wanted to insert a new Item and a new ItemType at the same time. I know what you're thinking, "That's Crazy!". Hibernate thought I was crazy too. It complained of a foreign key constraint violation. I spent two days trying to solve this problem, thinking the whole time how much easier it would be to use JDBC.

I solicited SweetTea’s help. He suggested that I set the cascade attribute on the many-to-one relationship to "none". That didn’t fix the problem. He also suggested that I re-fetch the new ItemType after I inserted it. That didn’t fix the problem either. Sorry, SweetTea. Your two years of Hibernate experience aren’t enough for this problem.

So, I checked online, and I found lots of tutorials/reviews written by enamored Hibernate fan-boys. Saying things like:
"Hibernate is simply the greatest object-relational mapping tool available for Java. I wrote an order application in just a few lines of code. I can’t imagine how hard it would have been to use straight JDBC."


Really? I can. It’s not that hard. I’m sure I can do a crazy two table insert in less than two days.

Thankfully, DeviousBard saved the day. Whoosh! After he was finished laughing at me for having to work with Hibernate, he dug in and started tweaking the Hibernate configuration files. Between us, DeviousBard and I have about 20 years of Java experience, but we must be complete idiots. We were pretty much changing settings randomly, and getting unexpected results.

  • Lazy initialization Errors

  • Batch Update Exceptions

  • Class Cast Exceptions

  • OMG Hibernate Sucks Exceptions



A few hours later, DeviousBard noticed something that appeared to be completely unrelated. A few lines above my troubled code, I was fetching an object by ID from one of the tables that I was attempting to insert into. The object was not found, and Hibernate simply returned null. Not a problem. Right? Wrong! This was the problem. Our best guess is that because the fetch was done within the same transactional context as the insert, Hibernate attempted to perform some sort of CRUD activity on the null object. By simply removing the seemingly unrelated code, my code suddenly started working. Shoot me.

I’m usually interested in knowing why and how things work. Usually when I start using a new API, I dig into the source, and have a look around. I have no interest in Hibernate internals. It’s like trying to figure out why a turd stinks.

I think I’m gonna write an Eclipse plugin called "WakeUp". Its sole purpose is to convert a Hibernate configuration file and the associated Java code back into POJO's that use JDBC. Then maybe, when everyone else in the Java world is willing to admit that Hibernate has no clothes, I can become a millionaire by selling the product that brings them back to reality.

2006-05-22

Wake Up Hibernate

Editor's Note: This post is not about bears and their sleeping habits. Tommy and millhousethecat, you can stop reading now. Really, stop reading.

I finally had the chance to use Hibernate on a recent project. Hibernate is a full-featured and popular API, but it has some problems. Here are my grievances.

Step away from the thesaurus


I feel like it was designed by pompous thesaurus-loving assholes. If you want to query a table and bring back just one column, what do you do? Oh, well that's simple. Add a Projection. Huh? I never would have guessed that. By coming up with crazy names for simple operations, the creators of Hibernate have taken away something very important. Developers new to Hibernate can't discover and learn it by doing (coding). The API is not in touch with reality. Let's go to the javadoc for the Projection interface:
"An object-oriented representation of a query result set projection in a Criteria query. Built-in projection types are provided by the Projections factory class. This interface might be implemented by application classes that define custom projections."

Good job Gavin King. Use the word you are defining in the definition. If I didn't have someone helping me with Hibernate, it would have taken me hours to discover this feature.

Reflection is cool...sometimes


A major selling point for Hibernate is that you don't have to change your object hierarchy in order to get persistable objects. What the hell does that mean? Usually ORM's require the user to subclass some PersistableObject in order for the object to be persistable. This is usually too restrictive for mature code-bases. With Hibernate, any POJO can be persistable. How do they that? -- Reflection my friend.

Reflection is cool until you need to do some debugging. Let's say a private instance variable is being set, and you want to know who/what is setting it. OK, put a breakpoint on the setter for the instance variable in question and see what happens. When Hibernate changes the value, you'll see nothing. Hibernate stealthily sets the value using reflection and the debugger is clueless. OK, put a watch on the instance variable. That will do the trick, right? Wrong. The same thing happens, Hibernate changes the variable and the debugger has no idea the value changed.

Lazy initialization error


This is infuriating for the first-time user. Hibernate only fetches things when it absolutely needs to. By default it's...well...lazy.

For example (pseudo code):
get session
fetch someObject from the session
close session

someObject.getAValue() --->  Boom!
Lazy Initialization Exception

There are three fixes to this problem:

  1. Leave the session open while you are accessing the object values.

  2. Configure Hibernate to not use lazy initialization.

  3. Stop using Hibernate. :)

There are more things that bug me about Hibernate, but I'm tired of typing and I'm sure you're tired of reading. Is anyone still reading?

2005-10-08

apidoc.org

apidoc.org is a great site that aggregates API documentation. It has a register/login feature that doesn't work. Luckily, you don't need to register to use it. There is also an IntelliJ plugin.

Yes, you read that correctly. I'm using IntelliJ...pushed down by the man again. IntelliJ is pretty good. I've only been using it for about 2 months, so my opinions are probably immature.

pros:

  • The code coloring and formatting are really customizable. It has a lot of font effects available.

  • It has great Ant script integration. You can jump around in an Ant script as if it were Java code.

  • It has nice JUnit integration. IntelliJ runs your JUnit TestCases and then summarizes the results. You can run all of the TestCases in a package, run just one TestCase, or run just one method in a TestCase.


cons:

  • SLOW! I hate an IDE, well any application, that can't keep up with the user.

  • Lots of plugins are available, but there are no plugins for additional file type support. ksh, perl, bash, and batch script are just text files to IntelliJ.

  • The code navigation is OK. It's easy to jump forward in the source code, but there is no way to jump back. There has got to be a way to jump back. I just haven't found it yet.
    update 10.10.2005: I found it. "Go To" -> "Back".


  • Five hundred dollars...and it only transports matter... SlickEdit still kicks IntelliJ's ass for $200 less.

2005-07-20

New Job: day 3

I was getting into some serious coding this morning. Here is how it went.
StringIndexOutOfBounds exception in Huh.java line 5. OK, lets have a look at this file. Where is it? Open a command window.

cd /projects.

Error. Right. Windows.

cd projects
find . -name "Huh.java"

Oops, Windows. Close command window. Open File Explorer. Click on My Computer. Click on Local Disk (C:). Ctrl-F. Type Huh.java and click the "Search Now" button. Searching. Hummm...this may take a while. I know, I'll check my mail! I'll just switch over to Firefox. Hummm...still waiting for Windows to respond...looks like the search is consuming alot of resources. Ah, Firefox is ready. I'll just click the "Check Mail" link. And Firefox has crashed. Oh, but my search is finished. Excellent the file was found. I'll just double click on it. Nothing. Hummm. I'll just double click on it. Nothing. There appears to be an excessive amount of disk activity. Ctrl-Alt-Del and click "Task Manager" button, and click on the CPU field to sort by that. Oh it appears that I'm trying to launch two instances of Oracle JDeveloper. I'll just right click -> End Process. And waiting..."Process is not responding. End now?"...yes. Oh look at that. It's lunch time.

Puppies and kittens.
Puppies and kittens.
Puppies and kittens.