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

20090625

Eclipse Galileo Review

It's that time of the year again... here's my short review of Eclipse Galileo, which I've been using since M6.

While reading this review, keep my usage pattern in mind: programming for a large portal written in Java using frameworks such as Spring and Hibernate. Domain objects are mostly annotated, with some Hibernate XML thrown in. Spring configuration is still using XML for now.

Here are the things I like about this release so far:

  • HTML tags now auto-close. Same for XML tags; if you type "/" at the end of an open tag, the close tag is removed. Not a huge feature, but it's the kind of polish you find in IntelliJ that's starting to make its way into Eclipse.
  • Fully qualified class names are hyperlinked in XML files! This is a HUGE help for our team, as navigating those Spring XML files is always tedious.
  • Go to implementation. When you hover on a method call, you get a small pop-up that lets you choose between going to the declaration or the implementation. I'm still catching myself going to the declaration and pressing CTRL-T, but I'll get myself re-trained eventually. It would be nice if this feature had a shortcut key.
  • Switching editors with CTRL-PageUp and CTRL-PageDown. This used to switch tabs within the editor if present, to my great annoyance when I had XML files opened. I never use the "design" view for XML, so having to go CTRL-F6 or mouse around just because of a design view I never use was pretty annoying to me.
  • Rectangular/Column/Block selection mode. This used to be an add-in, but it's nice to have it built-in. This was one of the few things that had me boot up vi for text editing once in a while...
  • The compare editor is now a much more complete Java language editor, with completions and so on. Since I often have to resolve annoying conflicts by hand when merging old branches, this is a welcome addition.
  • Hyperlinks in JavaDoc pop-ups. Man, this is great! How often I've wasted time closing the JavaDoc popup and navigating to the parent class or to "see also" links by hand... Or even given up and gone to the web browser to browse the online HTML doc. In my mind, anything that saves me from switching to a different app just to navigate documentation is a Good Thing; it's one less hurdle to staying in the Zone.
  • The previous version of WTP had an annoying bug in JSPs: malformed tags would eventually lead to a stack overflow on complex pages, on every keystroke, until you closed and reopened the file. I haven't encountered this problem with Galileo.

But the major plus in my mind is the new plugin installation UI, known as p2. It's still not up to par with the Debian package manager front-ends, especially when explaining conflicts or missing dependencies. But it's much less confusing than previous efforts. I may actually use it to upgrade Eclipse next time around, something I never dared to do before.

What's to dislike? Well, nothing much. I still wish they'd implement proper themes for syntax highlighting, since the Export Preferences system exports all preferences. It's possible to edit the resulting file to strip non-highlighting related data, but it's a pain. Don't underestimate the power of syntax highlighting themes! Programmers like to share those, especially when the default theme is dark on light instead of the much less eyestrain-inducing light on dark.

Also, I wish installing Subversion integration wouldn't involve adding third-party connectors that sit in a different update site. I know it's related to licensing, but this is somewhat annoying. SVN support should be built-in, given that CVS is largely deprecated now.

Oh, and this isn't part of the Eclipse Galileo release, but the Maven plugin for Eclipse is really shaping up nicely. We've converted all our active projects to Maven, and it's really convenient to be able to just grab a project out of the repository and start working immediately. Not to mention how nice the new archetype UI is.

20070826

Maven (non)-bashing

Looks like the popular sport of bashing Maven continues. Just thought I'd add my own opinion to the mix.

Background

At work, I've instated Maven use for new projects as well as some active projects (those I could get people to migrate, anyhow) about nine months ago. My reasons were the following:

  1. We had a crufty Ant-based build system (which I built myself, I'm ashamed to say--I think my only excuse is that it replaced another, cruftier Ant-based build system with really wonked dependency management), and some of its persistent bugs (wonked version number handling and unversioned third party libraries) were really starting to get on my nerve and other developers';
  2. I'd tried out Ivy, and I had problems getting it to just work (this was way before the current version, at a time the documentation was rather sparse);
  3. A co-worker started bugging me about "why not Maven," so I got curious;
  4. I finally found out how to adapt the pom.xml file to a non-standard directory structure, from the Wicket project's pom files. This was the clincher, because I really hated the standard Maven layout (especially separated code and resources directories--ugh) and I wanted to be able to retrofit our old projects that had a more widespread layout (source in src/, tests in test/ and webapp in www/).

Initially, I was the only Maven user in the whole place. I introduced my team mate who worked on the same project I was doing, and more recently, I ported a whole bunch of legacy stuff to use Maven instead of the old script, declaring that if that stuff could be ported, anything could. Two other co-workers started using the Maven build at that time, and so far, they feel it's been positive.

Maven bashing

OK, fasten your seat belts, folks, because that's going to hurt.

I had two huge problems with Maven:

  • Bugs
  • Very, very generic documentation for many non-generic tasks, like sofware release (mvn release:prepare and mvn release:perform)

The main bugs I hit were huge bugs with the CVS SCM provider that made the release plugin basically unusable. I tried fixing it myself, but I nearly burned my eyes out navigating the SCM module source code. This is another sub-complaint: the code quality is, frankly, not that amazing. It's a bunch of too-small modules strewn together, and sometimes the modularization is pushed a bit too far for my tastes: you get a package with interfaces only, a package with the implementation, a package with just the model created automatically from modello files, and then a package for each different plug-in. That's two extra packages, in my view, and it means a very high cognitive load.

The main problem with the documentation was that it was highly variable. Sometimes, you get amazing details, lots of examples. Sometimes, you get a glib description and the goal documentation (note to plug-in developers: the goal documentation would be much better if the configuration parameters were actually explained; sometimes, it's not clear exactly what a term means in a given context, and being told "localRepository: local repository path" does not help much). Sometimes, you only get autogenerated stuff with no description whatsoever.

Also, I wish more attention were paid to error messages. This is a common problem in software, however; Maven is not the only (nor necessarily the worse) culprit. Exception: the archetype plugin is one of the stupidest thing I've seen from an error-reporting point of view. When it's missing files, it just throws "unable to copy file" without having the decency to tell you which one... even the stack trace is mum about this.

Maven praises

However, I'm not convinced that this is an excuse to ditch the whole system. The main concepts, if not necessarily the code, are quite solid. I wish there was a way to specify ordering when binding many plug-ins to a single phase, but that's the kind of stuff that's not needed that often.

Maven works mostly as documented, and when it works, it works really, really well. In my experience, it's relatively speedy (at least, compared to my hokey ant script). The release plugin, now that they fixed many, many bugs with CVS interaction (actually, the CVS plugin may have been the culprit, I was never able to ascertain this because the code was really "indirect" about it), works beautifully.

Writing a plug-in is really easy. Even compared with Ant tasks. Yes, it's that easy. It's a shame some Plexus or Maven core stuff is so poorly documented, but you can usually figure it out by looking at a similar plug-in.

Despite what a lot of people say, it is very much possible to have Maven work outside its standards. You'll have to be more verbose in your pom.xml, or use a parent pom. Wicket, as well as our own projects, are testaments to this flexibility. You have to hunt around for information on how to do this, but it is available on the Maven site.

Conclusion

Despite some shortcomings, I truly believe Maven is a very good build system. It was maybe a bit too ambitious at first, but since 2.0.5, it started being able to deliver on those ambitions. It is also much more flexible than people give it credit for.

For those banging their heads with it, I advise that you look at the Wicket and AppFuse pom.xml files. Likely they've solved your problems already, so you can just stealborrow their solution. :-)

20070627

Lesser known IoC containers

The point of this article is to talk about my experience with IoC containers other than the 1000-pound gorilla in the IoC container space.

Through some interesting circumstances (mostly, my hard-headedness about not including 15 megabytes of stuff just to get an IoC container; note that I do know Spring is modular, but it wasn't at the time), I'm one of the few people who hasn't been using Spring. At work, we've mostly used PicoContainer as our middleware "glue" layer. I've also dabbled with Guice, and Plexus (a bit) when messing around with Maven Mojos. This is a summary of my experience with each.

PicoContainer

Let's cover the IoC container I feel I know best first--PicoContainer. PicoContainer is a small (the JAR is 100 KB or so), type 3 (constructor injection) IoC library.

And that's pretty much the only thing it will ever be, if you don't customize the library. It does constructor injection. It supports hierarchical containers to resolve dependency conflicts. And that's it.

However, the real power of PicoContainer is its open architecture. You can implement your own component management strategy by implementing ComponentAdapter and ComponentAdapterFactory. There are a few example adapters. But overall, this lets you futz around with the component instantiation without having to resort to aspect-oriented programming or exotic annotations. Also, since you are in full control of which ComponentAdapter is used for which component, you can completely customize the instantiation on a per-component basis.

As an example of how useful this can be, it was very simple to implement a specialized adapter that can inject some dependencies through construction injection, and then looks for more dependencies to inject using setter injection. When my experiences with Guice left me somewhat lukewarm, I was able to quickly whip up an @Inject annotation for PicoContainer.

Finally, the hierarchical container facility is extremely useful for one-off dependency injections, such as injecting dependencies in objects retrieved from the persistent store by Hibernate.

So, in conclusion:

Pros

  1. Very small
  2. Reasonably fast, to the point that it can be used with throwaway containers
  3. Works even with old JDKs such as 1.4
  4. Component adapters are extremely flexible
  5. Containers are very lightweight, can create and throw away child containers at will

Cons

  1. The authors believe constructor injection is the only viable option. However, although constructor injection enforces integrity, it's also very awkward, especially when you get more than 5 dependencies. OK, you probably shouldn't have that many, but sometimes, especially in Struts actions or some other equally centralized point of logic, you will get that many, and it's still less awkward than having a façade just to cut down the dependencies.
  2. Although the adapters are very flexible, there are very few useful implementations that come with PicoContainer. One that supports Guice-like semantics would be welcome.
  3. The hierarchical system for resolving dependencies works well in some situations, but is extremely awkward in others. Granted, it's possible to write a component adapter that uses an alternative resolution mechanism, but in the IoC realm, PicoContainer is a bit like assembly language, or Forth; even relatively common cases have to be implemented by hand.
  4. There is relatively little integration from 3rd-party frameworks (such as Struts, Wicket, and so on). On the other hand, such integration is always very simple to write with PicoContainer, which is not necessarily the case with every IoC container.
  5. Error stack traces are OK, but sometimes very confusing; specifically, it's not always clear which dependency was missing when trying to instantiate a component.

Summary

If you want a small container and don't need many fancy features, or if you prefer to write such features yourself to gain maximum flexibility, PicoContainer fits the deal. In my mind, it's more of an IoC library than an IoC framework.

Guice

Guice is a relative newcomer in the IoC container arena. Its main claim of fame, despite what its adopters will tell you, is that it comes from Google. Also, unlike PicoContainer, it came out at a time where people started being annoyed at massive XML files, such as those that show up in many industrial Spring-based code bases.

It immediately grabbed the interest of many a-bloggers, showed up on dzone, yadda yadda. The question is, can you believe the hype?

Well, underneath the hype is actually a very nice IoC container that goes the extra mile to provide you with near-perfect error reporting, and that is not afraid to sacrifice purity to the altar of practicality. Guice supports, out of the box, all sorts of dependency injection scenarios, provided that you mark your dependencies with the @Inject annotation. From the theoretical point of view, this is more invasive than a run-of-the-mill IoC container, since classic IoC containers should, in theory, let you use plain objects without any special annotations. This, many argue, makes Guice much less flexible than Spring or PicoContainer.

In practice, I found that adding annotations makes sense in most cases. Externalizing all dependency-related informations sounds great in theory, but in practice, you'll end up with 80% of your services having only one sensible implementation. The services with more implementations have different-enough implementations in many cases that the POJO that receives it works well only with one of them (I estimate that about 10% of application services are like this). Guice's use of annotations to mark injectable resources and to let the target object control what resource gets injected to some degree is very practical.

The IoC container is pretty fast, and does some wicked ASM and cglib-fu to provide precise error reporting and the best possible speed regardless of the situation. Overall, it has an "advanced technology" feel to it. It shows a lot of polish in its package structure and in name selection.

However, Guice is a very "closed" system. Being advanced technology is nice, but it does make certain kinds of things a bit more difficult. Here is an example of such difficult things, and incidentally the reason we went with PicoContainer at work. Guice comes in a "uber jar" format; it bundles two versions of ASM (one for cglib, and a more recent version for itself; ASM is noted for major incompatibilities between minor versions, much to the annoyance of projects using it, and cglib appears to be evolving very slowly these days). Hibernate also uses a version of ASM, albeit an older one, as well as the same version of cglib as Guice. So, in an effort to trim the 550 KB or so JAR file to its bare minimum (remember, PicoContainer takes 110 KB...), I tried to get it to work with the older ASM version. The only part that didn't compile was some code used for error reporting, so I figured I could live without it. Well, I was wrong; the previous version of ASM crashes and burns during unit tests. I'm wary of dismissing obscure crashes to situations that will not happen in production code (even though the failing unit test looked like it was doing something exotic), so I left it at that, figuring I was better sticking with PicoContainer and bloating our applications as little as possible.

Some may dismiss this as a trivial reason to not use Guice, and in some ways it is. But it is something to be aware of. I know Hibernate, for one, has had all kinds of problems with use inside environments that come with a different version of ASM. So I'm a bit wary of such annoying dependencies, especially on ASM and cglib which are known troublemakers. Granted, the problem is a bug in ASM, but it does mean that Guice's use of ASM is exotic enough to trigger that bug.

Another problem with such a closed code base is that it's hard to extend it without releasing your own build of it. I'm not that keen with depending on an annotation that's inside the IoC container's package; I'd prefer depending on, say, the @Resource annotation that's standardized in a JSR (granted, it's not supposed to have exactly the same semantics, but my point is that I dislike putting hard dependencies at the POJO level). I understand the necessity of the annotation, and it's no worse, in my mind, than the transient or volatile keyword. Except in one way: it binds the code specifically to Guice, not just any IoC container. It would be nice if you could ask Guice to use another annotation type (this is noted as issue 70 in their issue database), but right now, you can't.

Pros

  1. Still reasonably small
  2. Very advanced, gives a peek of what libraries can look like if people would start to target Java 5 (see also Stripes)
  3. High-tech, uses all kinds of tricks to maximize performance and give the best error reporting possible
  4. More popular than PicoContainer at this point, is getting all sorts of frameworks integrated with it
  5. The only IoC container I know of that allows post-instantiation injection of dependencies for non-constructor injected services. This is actually a great idea in some cases (such as deserialization)
  6. Used in Struts 2. So it's going to end up being used by somebody visible, unlike PicoContainer :-)

Cons

  1. Sometimes too advanced; that kind of trickery can hurt if you get bit by a bug (admittedly, there doesn't appear to be many of them)
  2. Binding on a specific in-package annotation is annoying, I'm curious as to why there isn't a way to configure it?
  3. Not an open architecture the way PicoContainer is. It's very easy to futz around with PicoContainer internals. Guice is much more selective with respect to what it lets you do or not do.
  4. Java 5 only. Not that I care, but somebody might. Though, they did manage to make it work with Retrotranslator.

Summary

If you want a rich IoC container without the huge XML file tradition (yes, Spring folks, I know about JavaConfig, but it's still not what most people use), with sensible defaults and excellent error reporting, Guice fits the bill. However, if you want something with a hood that you can pop open at will, you may prefer another IoC container.

Plexus

I haven't played with Plexus a lot, so I can't really give too many details. My only experience was inside the Maven 2 codebase.

As far as IoC containers go, it looks OK (although it does suffer from the XML configuration file syndrome, the XML files are lighter than Spring 1.2 configurations [though not Spring 2.0 configurations], and you can use JavaDoc tags to autogenerate the XML file). However, I felt a bit annoyed at it overall. Error reporting, at least within the Maven environment, is not that great, even for simple mistakes like forgetting the appropriate JavaDoc tag or misspelling something. Plus, I can't really figure out where this project fits. It doesn't look like a project that's used by anybody except the Maven guys; why didn't they use PicoContainer to start with instead?

There are a lot of plexus components, but they don't tend to be that reliable, or their use within the Plexus infrastructure is not consistent. A good example is the password input component. Some Maven components use it, some use a plain text input component instead. It's not quite clear, when developing Plexus aware components or Mojos, which you're supposed to use for what.

A pet annoyance of mine: the Plexus guys want you to obtain the logging service through dependency injection. Although that sounds great in theory, I think it's nuts. Logging (at least, programmer logging) is purely a developer service. I'd even prefer not having to create a special object to start logging--if it could figure it out from the current stack with reasonable performance, it would be much better. So, if, to get logging, I need to create a field, a setter, and configure something in an XML file... I'm not going to use logging, or at least, I'll use Jakarta Commons Logging or SLF4J and just forget about Plexus logging.

So, all in all, it looks like an interesting project, but I don't really know why anybody would use it over Spring, or Guice, or even PicoContainer. I guess every developer likes to write an IoC container, because although it's not too hard, there are enough challenges and futzing around with reflection or byte code engineering to make it an interesting task.

Closing thoughts

So, there you have it, a quick round trip of some lesser-known containers. I also know of a few others:

  • HiveMind/Tapestry-ioc, the container behind Tapestry. Well, this one looks powerful, but like Tapestry, it changes wildly between releases, and releases happen relatively frequently. From a pure technology point of view, it looks very powerful, as HLS does not mind looking for good ideas in other projects.
  • Yan, a relatively unknown container that appears to allow injecting almost everything in almost anything. The author is one of the few who documented how to use his container in rich domain model. The Spring guys have allowed this only very recently, and it requires the use of the AOP sledgehammer to get it to work.
  • And, of course, Spring, whose basic container is becoming more powerful with every release thanks to ideas from all those lesser-known projects, but which remains a huge project. Granted, you can use only parts of it, but it's not the standard usage.

I hope this (longish) post will be of some use to somebody.