Wednesday, November 14, 2007

Candid 10,000 feet thoughts about Android

Android is the new mobile platform developed by Google. They released the SDK yesterday. Basically a Linux kernel, a mobile optimized virtual machine running Java, and a set of API to play with the phone.

First of all, the usual disclaimer. I am not a mobile developer, I am not much of a UI developer, but I am a Java developer and mobile consumer. Anyway, I'll give you some of my thoughts.

Android is yet another platform. We already had Symbian, Palm OS, Windows Mobile, Java ME, Mac OS X, you name it. So yet another platform to support when writing a mobile app, year!

Sounds pretty bad for Sun and Java ME. I don't know the specific deal that Sun did with Google for embedding the Java technology into Android but I hope it's a good one for Sun because Java ME will suffer from the Android platform:
  • it's "Java" enough for people to think twice before writing a Java ME app
  • it's not Java ME, it's not Java SE, it's a subset of Java SE, so practically a different platform to target
  • it's not a Java VM, so no need to pay any IP-related royalties to Sun
  • it's not the Sun's Java ME virtual machine, so no need to pay Sun some license fee
Last grief. From the live demo you can watch on Youtube (especially minute 3:32), they have a long way to go before having a UI as responsive as the iPhone at least in the screen touch area. Plus they probably don't have multi touch events yet ;p

That being said, it seems to be a smart move from Google in three ways:
  • it's a free platform for any mobile constructor (quite appealing)
  • the notion of intent allows the user to replace one application with another in a very sleek way (sort of the loose coupling dream made true), making Android potentially an open platform even for the user
  • they leverage all the Java developer base
Plus you can define your UI declaratively (XML), that's a smart move too.

So Android is a very open platform, but don't forget one thing: it's so open that your phone carrier can lock it down as much as it wants :)

As an iPhone user, I'm relieved a bit, my investment is worthwhile.

Thursday, October 11, 2007

Welcome to G2One

Yesterday was the official public birth of G2One, a new company dedicated to Groovy and Grails training, consulting and support. I am happy to see Guillaume (Groovy lead) and Graeme (Grails lead) jumping into the Professional OpenSource bandwagon. Good luck to you guys, it is as stressful as exciting :)

Speaking of it, I will be speaking Wednesday 17th to the Grails eXchange.
groovy, grails, java ee, grails exchange
One talk about Hibernate in general and what is cooking up for the next releases and another one about Hibernate Search (hopefully I will get my demo ported on Grails :) )

Tuesday, September 4, 2007

Release Candidate for Hibernate Search 3.0.0

Release Candidate for Hibernate Search 3.0.0

Hibernate Search 3.0.0.CR1 is now out. This release is mainly the last bits of new features and polishing before the final version. The next cycle will be dedicated to bug fixes (of any bug that pops up), as well as test suite and documentation improvements.

Thanks to Hardy for the new getting started section (this should ease the path for newcomers), and to John for hammering the last features we wanted in the GA version.

The next version should be the GA release unless some complex bugs are discovered.

Check the changelogs for a detailed change list.

Tuesday, August 7, 2007

Podcast about Hibernate Shards

Max Ross and Maulik Shah from the Hibernate Shards team at Google got interviewed by the Google Developer Podcast.
It's a nice and easy access 30 mins introduction of Hibernate Shards: how does it work, where does it come from, what are Hibernate Shards do's and don'ts, what's the secret plan to take over the world... Insightful. One of the cool stuffs they added in the latest beta is support for Hibernate Annotations.
If you want to know what shards is all about or if your DB starts to feel the heat, go get your headset.

Wednesday, August 1, 2007

Innovation in the Log space, yawn...

Steve and I had a discussion yesterday about loggers. I know what you're thinking: hasn't log been a solved problem for years now? Plus it's boring ;)
That's why usually, when a discussion starts on the subject, I tend to carefully not listen. But because it's Steve, and because he has some specific requirement for the next Hibernate Core version, I decided to ignore my own rule.

It turned out to be much more interesting than what I expected. Here are some news for people, like me, that stopped listening to the log crowd when the rule was use log4j and when you can't use commons-logging.

I was pleasantly surprised by slf4j. I know, it's yet another facade and the name is awful. But this project has 2 features that really caught my attention.

Parameterized log
Isn't it very annoying to have to do

if ( log.isDebugEnabled() ) {
log.debug("My dummy " + object1 + " and expensive " + object2 + " concatenation");
}

because the object's toString() method are expensive?

slf4j solves that by using parameterized logs

log.debug("My dummy {} and expensive {} concatenation", object1, object2);

Very elegant and just as efficient as the previous form. Now because slf4j supports JDK 1.3, the API cannot use varargs, which means that for 3 or more parameters you will have to write

log.debug("My dummy {} and expensive {} concatenation {}", new Object[] { object1, object2, object 3 });


instead of the much more elegant

log.debug("My dummy {} and expensive {} concatenation {}", object1, object2, object3);


Damn slow movers! I guess most of the time you have 1 or 2 arguments so the pain should be minimal, or you could write you own facade, sigh

Static binding

Once I understood what it meant, I liked it. Basically to switch from one underlying logger to another, you will replace slf4j-mylogger1.jar by slf4j-mylogger2.jar: the slf4j engine is statically bound to an implementation.
OMG! This means I cannot change my logger implementation by hot deploying a config file! Oh, wait a minute, it's useless anyway.
The good side is that classloader hells are behind us.

The Ultimate Uber Cool solution

The ultimate solution is actually what Gavin came up with in Seam. So instead of doing

private static final Log log = LogFactory.getLog(CreateOrderAction.class);

public Order createOrder(User user, Product product, int quantity) {
if ( log.isDebugEnabled() ) {
log.debug("Creating new order for user: " + user.username() +
" product: " + product.name()
+ " quantity: " + quantity);
}
return new Order(user, product, quantity);
}

you end up with

@Logger private Log log;

public Order createOrder(User user, Product product, int quantity) {
log.debug("Creating new order for user: #{user.username} product: #{product.name} quantity: #0", quantity);
return new Order(user, product, quantity);
}


Notice the parameterized logs, the log injection (yes the framework is smart enough to guess the category, doh!), and the contextual parameters injection.

But such solution is not accessible to library developers until someone decides to push that into the JDK.
OK I'm done for logs for another 5 years time :)

Friday, June 22, 2007

Hibernate at Jazoon'07

I will be at Jazoon (Zurich) to talk about Hibernate Search on Tuesday. I'll hang around Monday and Tuesday, so feel free to pass by the JBoss booth for a chat.

Friday, June 15, 2007

Hibernate Search - cool, but is it the right approach? Year baby!

Sanjiv Jivan wrote a blog entry questioning the "point" of Hibernate Search. He missed some critical steps in his argumentation, that I am willing to correct. I started to answer on his blog, but the answer being fairly long, I opted for a blog entry.

I think Sanjiv failed to understand which population Hibernate Search is targeting.
Hibernate Search is about ORM. If you don't use Hibernate, if you don't use JPA, forget about Hibernate Search, it's not for you.

His main point is, why use Hibernate Search instead of a straight Lucene + Database (I'm assuming JDBC) solution? Five years before he could have asked, why use an ORM rather than a straight JDBC access? Because it does for you and optimize 90% of the job and let you focus on the 10% that is hard.
I won't explain why an ORM is usually (but not always) a good approach (everybody got that nowadays), so let's focus on a different question: considering that Hibernate is used in a given application, should we go for plain Lucene and JDBC layer as Sanjiv suggests or should we go for Hibernate Search? Should we go for 2 different set of APIs / programmatic model and model representation, or should we go for one unified model?

Let's see each of Sanjiv's concerns one at a time.

Why Hibernate Search rather than plain Lucene and JDBC?
Out of the box, setting up a plain Lucene and JDBC solution requires to write the bridge. Lucene has it's own world, the DB an other one. Your code has to bind them together (write the optimized JDBC routine + optimized Lucene index routine). It can be long, painful and buggy.
I doubt Sanjiv had to do it before, he would not talk like that :) Hibernate Search does the binding for you in your Hibernate backed application.
People are attracted by Hibernate Search because it lowers the barrier of entry to Lucene in a project by a great deal. This opens the Search capabilities to a lot of applications that would not have considered it with only plain Lucene in their hands.

Hibernate (Search) does not play well with massive indexing
Sanjiv claims that the initial indexing (or reindexing) is slow (he hasn't tried actually) and memory consuming.
Have a second look at the Hibernate Search reference documentation, the massive indexing procedure explicitly helps you to control the amount of memory spent.
In Lucene, one good rule of thumb is use as much memory as possible to minimize IO access. So yes, the more memory you'll spend the more efficient your hibernate Search massive indexing will be. You have to think about the global system, not only a subpart.

Event based indexing should not be used
Next Sanjiv tries to show that the event based indexing is wrong and that one should always use batch indexing. The honest answer is it depends.
Hibernate Search does not constraint to index things per transaction (it's a pluggable strategy), and I never said that indexing at commit time was important. Not indexing before commit time is critical (think about rollbacks).
As a matter of fact, the clustered mode (JMS mode) explicitly does not index at commit time, it delegates the work for later (and to someone else). The overhead of sending a message for later indexing (I'm not speaking of actual Lucene operations here) is minimal.
What do we gain? The usual on the fly vs batch mode benefits: no batch window, more homogeneous CPU consumption on systems, not having to take care of a batch job. I don't know about you, but the less batch jobs I have in my systems, the better I sleep.
By the way, is batch mode supported with Hibernate Search? Absolutely. Who likes to avoid batch jobs when possible, most of the developers and ops guys I have met. When you need to use them, do it ; when you don't stop the masochism.

To justify that batch mode should rules, Sanjiv used the data mining and star / snow schema as an example. These are a very specific kind of applications where ORM are almost never used. They could be, with some adjustments tot he ORM, but that's another story, maybe my next project :) Anyway, this is out of the scope of Hibernate Search, see the very first point.

I agree that JMS is highly over engineered and should be simplified in Java EE6, but come on, setting up a Queue is only a few clicks in a graphical console... it's not too bad. Don't tell me JMS is too hard (Hibernate Search does the JMS calls by the way, not you).

Hibernate Search does not support third party modifications in the database
It's actually a fairly known problem to people who use 2nd level cache in ORMs, has 2nd level cache been banned from our toolbox? clearly no. But once again Hibernate Search works fine in a batch mode. So this should solve Sanjiv's concerns.

Annotation based indexing definition is not flexible
Is that an inflexible approach? How practical would it be to change them on the fly? Changing which elements are indexed, or how would require to reindex the whole set of data. Quite possible, but definitely something that is not so useful on the fly. As for boosting, I do set my field boosting at query time, I find it more flexible than index time boosting, so I never had the issue Sanjiv is describing.

Why using Hibernate Search query API?
Why not using straight Lucene queries an APIs, it's all about text in the end?
The nice thing about the Hibernate Search is that it's really easy to replace a HQL query by a Lucene query: just replace the Query object and you're done, the rest of the code remains unchanged. Because is that simple, people tend to use Hibernate Search and Lucene queries in a more widespread number of usecases, and not simply for a Yahoo-like search screen (we always talk about Google, let's switch for a while ;) ):
- save some DB CPU cycles and distribute it to cheaper machines
- efficient multi word queries
- wildcards
- etc
Here is a use case that is clearly not about plain text:
"increase visibility of all books where 'Paris Hilton' is mentioned and double the increase if 'prison' is also present"

Hibernate Search queries can return either managed objects or projected properties (retrieving only a subset of the data). When to use what?
Sometimes, you use property projections rather than object retrieval in HQL queries either for ease of use or performance reasons, It's more convinient to play with the objects, but you pick up the best tool for the job. I would say the same kind of rules can be applied with Hibernate Search between a regular query and a field projection.

Hibernate Search not suitable for high volume websites
I love this one. I did design high volume websites backed by Lucene. I know what you gain, I know what you lose. Hibernate Search is full of best practices. The Hibernate Search clustering support is a good example of architecture that an architect could mimic to scale with Lucene (up and out). But it's not the only one, it depends on the use case, that's why Hibernate Search does not impose an architecture, that's why I prefer libraries over off-the-shelves products.

I would recommend this off-the-shelves solution?
DBSight or Solr (which I know better) are interesting solutions indeed, but not for the same kind of projects, or at least not for the same integration strategy. We are comparing a library versus a black box. BTW DBSight has a 3-minutes install demo. I could not beat them, it took me 15 mins on stage at JavaOne ( but I walk and talk a lot :) )
I have never been a big fan of black boxes nicely integrated in my IT system, but if I had to choose such a solution I would also give the Google Search Appliance a try, the Google Mini is fairly cheap.


Anyway, Hibernate Search has been developed with practical solutions for practical problems, not theoretical considerations. Giving it a shot is the only way to judge.
Damn long post, sorry about that :(

Tuesday, June 12, 2007

Got a MacBook (Pro), better consider this upgrade

Last night my battery and my MacBook Pro decided not to talk to each other anymore. The battery was full but as soon as I unplugged the AC, the laptop shut down immediately, fairly useless ;-)

Have a look at Apple's support case MacBook Battery Update.

This patch apparently prevent the synchronization failure to happen, saving you a WFT moment and few hours of downtime.

I have been fairly impressed by the Genius bar support. It took me 1h to figure it out the problem in the morning (The Apple support website roughly described my problem), I made an appointment right away, another hour later I had my new battery operational (travel time included).

At least, they don't argue with you and don't ask if you know how to turn the power on. It's a big plus compared to other support organizations.

Wednesday, June 6, 2007

From a Bug blooms a thousand Features

When a severe bug hits a product, you have to fix and release quickly (at least I feel I have to). But, especially in the beta phase, it's fairly humiliating to release with one single ticket resolution.

Call it pride, pair pressure, ego, unwillingness to face reality, teenager knee jerk, I just can't release a beta with one single lonely closed ticket.

This is what happened on Hibernate Search. Beta2 introduced a severe bug in object retrievals. So I ended up coding a few new features, fixing a few additional annoyances to hide the obvious.

That's one of the things I like in the Software as a Service model, transparent bug fixing, but that's another story.

Obviously, such aggressive release cycles can only work as long as a Product Manager don't look over your shoulder.

Who said bugs were a bad thing? ;-)

Hibernate Search freshly baked features

I had to release Hibernate Search Beta3 early after we discovered a fairly severe bug in Beta2. But I had time to inject some new features. After those introduced in Beta2, that a fairly good week :)

batch size limit on object indexing
If you don't pay attention when initially indexing (or reindexing) your data, you may face out of memory exceptions. The old solution was to execute indexing in several smaller transactions, but the code ended up being fairly complex. Here is the new solution:
hibernate.search.worker.batch_size=5000

int batchSize=5000;
//scroll will load objects as needed
ScrollableResults results = fullTextSession.createCriteria( Email.class )
.scroll( ScrollMode.FORWARD_ONLY );
int index = 0;
while( results.next() ) {
index++;
fullTextSession.index( results.get(0) ); //index each element
if (index % batchSize == 0) s.clear(); //clear every batchSize
}
wrap that into one transaction and you are good to go.

Native Lucene
The APIs were never officially published (until beta3), but Hibernate Search lets you fall back to native Lucene when needed. All the needed APIs are held by SearchFactory.

DirectoryProvider provider = searchFactory.getDirectoryProvider(Order.class);
org.apache.lucene.store.Directory directory = provider.getDirectory();
This one is the brute force and gives you access to the Lucene Directory containing Orders. A smarter way, if you intend to execute a search query, is to use the ReaderProvider
DirectoryProvider clientProvider = searchFactory.getDirectoryProvider(Client.class);
IndexReader reader = searchFactory.getReaderProvider().openReader(clientProvider);

try {
//do read-only operations on the reader
}
finally {
readerProvider.closeReader(reader);
}
Smarter because you share the same IndexReaders as Hibernate Search, hence avoid the unnecessary IndexReader opening and warm up.

Finally you can optimize a Lucene Index (roughly a defragmentation)

SearchFactory searchFactory = fullTextSession.getSearchFactory();
searchFactory.optimize(Order.class);
//or searchFactory.optimize();

Tuesday, May 22, 2007

Lucene feedback from Atlassian JIRA and Confluence

Mike Cannon-Brookes from Atlassian has posted (some moons ago) two interesting presentations related to Lucene and Atlassian's feedbacks from Confluence and JIRA.

My favorite is the first one: Lucene: Generic Data Indexing. It's a nice introduction to the benefits of Full Text search engines, as well as the gotchas you will face.
I found their use of FilterQuery as a cross-cutting concern implementation for security fairly interesting.

The first presentation also quickly address some of the indexing strategies (synchronous / asynchronous) depending on the product requirements. Mike goes a bit deeper in the second one by describing some clustering solutions and the one they choose.

JIRA has gone very far in its use of Lucene, I am not sure I would have gone that far, but that's definitively a very interesting extreme use case, and very successful :)

Wednesday, May 16, 2007

Demo of JBoss Seam DVD Store powered by Hibernate Search

Many asked me if the DVD Store demo powered by Hibernate Search that I ran at JavaOne was available online.
The answer is not yet, but it will. My plan is to package it nicely and release it when the beta 2 of Hibernate Search is out.
This will hopefully happen fairly soon. JavaOne being behind us, I can focus back on the code base.

I had some very interesting discussions with some of you about Lucene and the features you need, it's good to see the community growing around the project.

Wednesday, May 9, 2007

Hibernate Search and JSR-303 at JavaOne

I will be presenting Hibernate Search at JavaOne.

I will be demoing a live migration of the JBoss Seam DVD Store application from a classic SQL based search engine onto Hibernate Search with Google-like search capabilities. If your user pressures you for a decent and useful search feature or your DBA asks you not to kill the database perfs, you might want to take a look at it.

It's Friday at 10h50:
TS-4746 - Hibernate Search: Googling Your Java Technology-Based Persistent Domain Model


I will also give an update on JSR-303 Bean Validation (and Hibernate Validator) about the goals, the expectations and where it fits in the Java ecosystem, with a demo too ;-)

Friday again at 14h50 ( 2:50 PM in our local hosts language ;-) )
TS-4112 - Declarative Programming: Tighten Enterprise JavaBeans (EJB) 3.0 and JSR 303 Beans Validation

See you there

Sunday, April 22, 2007

Hibernate Search talk at JAX '07

One feature request for Hibernate Search has been surprisingly pretty popular: support for indexed embedded collections and hence correlated queries involving collections.
This is no longer a request and is available in SVN :-)

Imagine a Movie having a list of Actors, the following query is now possible:
give me the movie talking about Central Intelligence Agency and having one of the Baldwins in the casting
or in Lucene language
description:"Central Intelligence Agency" authors.name:Baldwin
Of course the drawback is to potentially increase drastically the size of your index. So use it when the collection size is under control.

I am going to talk about Hibernate Search at the JAX 07 conference in Wiesbaden on Tuesday. Let's have a beer if you are around.

By the way, I think De Niro did a not so great job on this movie, too much is suggested (probably too many details too fast). I know that was the intend, but he went too far in my opinion.

Monday, March 26, 2007

Licensing and trademark

There has been lots of turmoils last week on two not so related subjects. Let's clarify them a bit.

LGPL rights and duty


Lot's have been said about this license, and lot's of people out there don't understand the rights and duty of this license.

  • Goal
From the GNU LGPL Preambule:
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.
The goal is to guaranty freedom (of speech) to he users of a given software.

  • Can I use a verbatim copy of a LGPL library in my software? What about my code license? What if I distribute my software?
You can use a verbatim (unmodified) copy of an LGPL library in your code and distribute your application. Your application can use any license (commercial or open source), in other words your code does not fall into the LGPL license. The library remains LGPL of course.

  • Can I modify the library? What happens then?
You can modify the LGPL library, any modification has to be LGPL. If you distribute those modifications, you have to comply with the LGPL and distribute the modified source code as well. In other words, a user of yours will be able to see the code changes and do whatever it pleases him with it provided that he follows the LGPL rules.
Your application (aside from those modifications) does not fall into the LGPL license.

It is usually admitted (while not required), as a courtesy, to provide (all) your modifications to everybody (not only the third party you distribute your application to). It usually doesn't matter in the end, because any of your application users will be able to freely redistribute for free the modifications you made on the LGPL library. There is nothing you can do about it.

  • Goal (once again)
The goal is to be sure that any change to an LGPL library will remain LGPL, be contributed back to the community, and never be hidden in a closed source program.

Check the LGPL license for more info.

Trademarks

A trademark includes any word, name, symbol, or device, or any combination, used, or intended to be used, in commerce to identify and distinguish the goods of one manufacturer or seller from goods manufactured or sold by others, and to indicate the source of the goods. In short, a trademark is a brand name.[1]
A trademark does not prevent you from providing a service based on a given product. It restricts and organize, however, the way you can use a given (combination of) word.
(Protection of) Trademarks is actually a fairly common practice, including in the Open Source world, to name a few
All of them, at one time or an other, have made sure their trademark is enforced.

Why?
For all of them, to protect the brand, to protect the message the brand is pushing.

That is the reason why I changed the name Hibernate Lucene to Hibernate Search, it violated the ASF trademark, so I went ahead and fixed it.

To clarify the turmoil with Hibernate, please check the clarification by Mark Webbing. It's in the comments here but I will reproduce it for clarity.

I am writing to clarify the issues raised by the publication of Ms. Robertson's communication on behalf of Red Hat. First, the letter is not placed into the context of the situation it was addressing. That presents the opportunity for misinterpretation. At the same time, I would agree that the letter is less than precise in defining what has been done wrong and the corrective action that is required. Ultimately, that is my fault as the person in charge of trademark enforcement at Red Hat.

Contrary to Gavin's statements above, you cannot offer HIBERNATE Training or JBOSS Training. This is an improper use of Red Hat trademarks in that the marks are being used (a) either as nouns or (b) to promote a good or service that is directly branded with Red Hat owned marks. What is permissable, and I am sure this is what Gavin meant, is that you are permitted to offer HIBERNATE(R) Object Relational Mapping Software Training or, as another example, JBoss(R) Application Server Training. Here the marks are being applied to the goods in a proper manner and it is clear that the training is being provided for that branded technology, not by the brand owner. As a further common courtesy, it would also be appropriate for those properly using the marks in this manner to make clear that they are not in anyway associated with Red Hat or its JBoss Division.

With that clarification I hope I have resolved the confusion and/or discontent around this issue. More extensive information on the permitted uses of Red Hat marks can be found at http://www.redhat.com/about/companyprofile/trademark/

I would also ask, as a courtesy to Ms. Robertson, that the party who posted her letter please indicate that they were the party posting the letter, not Ms. Robertson.

My apologies for any confusion that has been caused.

Mark Webbink
Deputy General Counsel
Red Hat, Inc.

Sidenote

Contrary to some claims, you don't have to have a @jboss.com address to contribute to JBoss projects (I mean commit access). All you have to do is being accepted by the community and the project lead (as any open source project), and sign a contributor agreement (in a similar manner an ASF contributor agreement is signed). To name Hibernate, I can count at least twice as many active contributors not having a @jboss.com address than having one :-)

By the way, I am not a lawyer, so take my words as is etc etc. My dog knows a dog who knows a lawyer, but I am not sure that qualifies me ;-)

Thursday, March 8, 2007

Google Guice: IoC revisited

Google has made public his IoC container. It's all annotations based, no more strings, no more XML.

Some key concepts:
  • Avoid string based injection which are error prone and hard to refactor
  • @Inject actually inject :-)
  • @ImplementedBy(ServiceImpl.class). A service can have a default implementation, use by default when no wiring is explicit. The actual implementation is easily identified, including by your IDE...
  • Injection through custom annotations (even parameterized): useful when you need to bind 2 services implementations and use one or the other. Also useful to bind constants: Guice allows you to bind a constant to an annotation.
  • Scoping: injections are scoped, and you can create you own scope (transaction). Inner scopes can see outer scopes.
  • Because it's Bob Lee: Guice has integration with AOP Alliance is supported
Here are some examples:
Basic injection
public class Client {
private final Service service;

@Inject
public Client(Service service) {
this.service = service;
}

public void go() {
service.go();
}
}


Default for autowiring
@ImplementedBy(ServiceImpl.class)
public interface Service {
void go();
}

Custom annotations
bind(Service.class)
.annotatedWith(Blue.class)

.to(BlueService.class);

...

@Inject
void injectService(@Blue Service service) {
...
}


What I really like:
  • Annotation based, easy to read and concise
  • Injection on methods (not only setters)
  • @ImplementedBy: Most services, they are implemented one and only one time.

I remember the old days of Pico vs Spring vs Avalon. I'm happy to see innovation flowing again in this field. Some took for granted that Spring was the only way, then come annotations. JBoss Seam and its annotation based stateful injection / outjection, and now Google Guice: both share some of the interesting concepts I described earlier. Component injection is revisited and it's good.

Now remember, IoC is not application development, it's at best a part of it :-). To me, the programmation model with the biggest/homogeneous picture is JBoss Seam.

Wednesday, February 28, 2007

Hibernate + Seam team meetup in San Fransisco

This is a pretty rare event, (almost) all the Hibernate + Seam team will be together in San Fransisco end of this week.

We organize a meetup on Friday (March 2nd) at 7 PM

Levende Lounge
1710 Mission St. @ Duboce
San Francisco, CA 94103
Phone: 415.864.5585

http://www.levendesf.com/

Please drop me an email (emmanuel # hibernate.org)
if you intend to come to this event. There is usually a cover charge for this place on a Friday night, so we need to get people's names on the door list.

Tuesday, February 6, 2007

SVN: false promises

I've had to do a massive project refactoring. To be more specific, I had to split Hibernate Annotations in several pieces and make Hibernate Validator and Hibernate Search independent projects (stay tuned). Of course, I wanted to keep track of my changes history.
Supposedly, SVN is greater than CVS in this area, it can keep track of object renaming and copying without loosing tracks.

I've never had such troubles in a long time. A few tricks:
- IntelliJ package renaming is great but don't try to do too much in one commit: nothing is more annoying than a cryptic version control error after a complex refactoring.
- svn move of complex structure does not seems to work properly in local move: prefer using the svn move url1 url2. For the record, SVN ended up moving part of my tree without any complaints :-(
- don't expect to update a directory and move/rename it, SVN will actually prevent you to do so (at least the complex one I had)

So I ended up branching, committing my package renaming, doing server side svn move of my packages around the different projects. I wish I could have done that in an atomic way with no branching.

I'm not a SVN expert, but I usually don't expect my tools to require a PhD in version control, and a driver license to use them. There are huge rooms for improvements here. Think users :-)

For me SVN is not really better than CVS (except the local diff/revert).

Wednesday, January 24, 2007

Groovy Annotations

I have been hammering (nicely) Guillaume for a long time now to get Annotations support in Groovy.
Thanks to Alexandru Popescu, this is now an official work in progress, and one that progress well :-)
I am thrilled by the possibilities to combine JavaEE (or any modern annotation based framework) and Groovy. If you wondered about the dynamic language you wanted to use, don't anymore.

Like the Hibernate team when we worked on the Java Persistence certification, the Groovy team must have been very frustrated to focus on Groovy 1.0 and not being able to innovate as fast as they did. They are now back on track.

Give a try to Groovy SVN trunk and enjoy.

Thursday, January 11, 2007

To copy a file in ...

... Java
private static void copyFile(File srcFile, File destFile) 
throws IOException {
FileInputStream is = null;
FileOutputStream os = null;
try {
is = new FileInputStream(srcFile);
FileChannel iChannel = is.getChannel();
os = new FileOutputStream( destFile, false );
FileChannel oChannel = os.getChannel();
oChannel.transferFrom( iChannel, 0, srcFile.length() );
}
finally {
if (is != null) is.close();
if (os != null) os.close();
}
}

... Groovy
static void copyFile(File source, File destination) {
def reader = source.newReader()
destination.withWriter { writer ->
writer << reader
}
reader.close()
}

... Groovy with a salt of Ant
static void copyFile(File source, File destination) {
new AntBuilder().copy(file:'$source.canonicalPath',
tofile:'$destination.canonicalPath')
}

... in shell
cp source destination

Sunday, January 7, 2007

ActiveRecord pattern, so what?

The Active Record pattern has a lot of publicity recently thanks to the Ruby On Rails and Grails wave. A definition could be: an object that encapsulates both data and behavior (ie a database row and it's data access logic).

A bit of history
I was asked recently my thoughts about this pattern. First of all, if someone still remembers EJB 1.0 and 2.x Entity Beans, this was a perfect example of the Active Record Pattern... and a successful failure. Some of the reasons for this failure was the tight link between the data and it's access logic: Serialization issue, data tight to a persistent technology etc etc.

Statically typed languages
To me the ActiveRecord pattern is not well suited for statically typed languages like Java, hence the raise of another pattern : DAO (aka DAL in the .net world). It prevents the hard link between the persistence technology and the actual data representation.

Dynamic languages
Dynamic languages (and to a certain extend AOP) have the nice ability to decorate an object with additional features on the fly, without linking it "the hard way": you can then easily reuse your domain classes out of the persistence context.
Grails uses such a behavior to add CRUD operations transparently to your domain model (with quite complex Querying capabilities).
One still face a problem, what if the application developer needs to add a more complex persistence operation (esp a query), he will end up "hard-coding" the function to the domain object and we're back to the issue faced by statically typed languages... unless you create a DAO object. But then, your persistence operations will be split between your implicit domain model methods and your DAO: another code smell.

Dynamic DAO
As you can see, I'm not keen on the ActiveRecord pattern (out of simple applications), but I really love the simplicity of GORM (the Grails way). The solution is a dynamic DAO. JBoss Seam already generates very simple yet powerful DAOs benefiting from Java Generics. If you combine that with a dynamic language, you can have the best of both worlds.

class UserProcess {
@In UserDao userDao;

void create(String firstname, String lastname) {
if (userDao.countByFirstnameAndLastname(firstname, lastname) == 0) {
def user = new User( "Emmanuel", "Bernard" )
userDao.save user
}
else {
throw new UserAlreadyExistException()
}
}
}


Note that countByFirstnameAndLastname and save can be dynamic methods à la GORM.

Conclusion
I'm not a big fan of the ActiveRecord. For static languages, I would use the DAO approach. For dynamic languages, I did not make up my mind but a DAO on steroids seems very promising.