I can't wait to play this!
Friday, February 29, 2008
Tuesday, February 05, 2008
Grails 1.0 Released
Graeme Rocher, from G2One Inc., announced the release of Grails 1.0 this morning. The release notes are available from grails.org.
If you're a Java person and aren't familiar with Grails or Groovy for that matter, you should definitely check out Grails. Grails is a rapid web application development framework based on convention over configuration. It is designed MUCH like Ruby-on-Rails, but built using Groovy as a language. The main benefits of this approach is that Groovy is based on Java; which means it looks and feels like Java. This helps introduce it to a team and lower the learning curve. The other benefit is that it builds down to a WAR file that you can deploy into any old application server. No special hackery required. This is important when deploying it into a very 'enterprisey' environment.
Also, the internals of Grails and how it works are not based on it's own invented voodoo. Grails uses Spring, Hibernate, and Acegi internally. Good stuff...
If you're a Java person and aren't familiar with Grails or Groovy for that matter, you should definitely check out Grails. Grails is a rapid web application development framework based on convention over configuration. It is designed MUCH like Ruby-on-Rails, but built using Groovy as a language. The main benefits of this approach is that Groovy is based on Java; which means it looks and feels like Java. This helps introduce it to a team and lower the learning curve. The other benefit is that it builds down to a WAR file that you can deploy into any old application server. No special hackery required. This is important when deploying it into a very 'enterprisey' environment.
Also, the internals of Grails and how it works are not based on it's own invented voodoo. Grails uses Spring, Hibernate, and Acegi internally. Good stuff...
Sunday, January 27, 2008
Out of the Sandbox: Spring-Security OpenID Support
I just finished moving the OpenID support For Acegi/Spring-Security out of the sandbox and out into it's own module. It is in dire need of documentation, but the code itself is pretty solid.
Here's the post to the mailing list.
Here's the post to the mailing list.
Sunday, January 20, 2008
Save Windows XP
InfoWorld has started a petition aimed at getting Microsoft to keep Windows XP support around past the June 30th end-of-life date.
To summarize, here's why I like XP...
- XP is simply the best OS Microsoft has produced. I realize that doesn't say much, but it's true.
- I am a gamer. I'd gladly run Ubuntu or Fedora Linux, but I am not down with playing Pac-man, Super-pacman, or one of 200 Tetris clones.
- I'd love to get a Macbook, but they're really expensive, and again, I don't like pacman.
- Vista blows
So, sign the SaveXP Petition at SaveXP.com
Wednesday, January 16, 2008
Sun to Buy MySQL
This is huge news! MySQL has to be the single most popular open-source database in the world.
Tuesday, January 15, 2008
Acegi OpenID Support Update
I said I'd work on the OpenID support in Acegi (aka Spring-Security) and I finally did. Really nothing major, I refactored the functionality from the CAS package that we needed in OpenID up into its own existence in the "providers" package. So now there's a now AuthoritiesPopulator and DaoAuthoritiesPopulator impl that uses the UserDetailsService to look up Authorities for a given principal. This functionality was being "borrowed" from the Cas package, now it's been refactored up. For backwards compatibility I've left the original CasAuthoritesPopulator and DaoCasAuthoritiesPopulator items in as subclasses of the new classes. Both of those extensions are empty now though. They should be removed in the future.
Also, I've removed the janrain support as Janrain is dead. Spring-Security will now use openid4java exclusively. It has been updated to version 0.9.3 of that library.
Now the call goes out to Jeff Dwyer to update MyHippoCampus to the latest stuff and put it through its paces. Thanks Jeff!
Next up? Well, I'm going to slap it into one of the samples and do some testing, and then work on promoting it out of the sandbox. Hopefully we can get openId support into the main project soon :)
Also, I've removed the janrain support as Janrain is dead. Spring-Security will now use openid4java exclusively. It has been updated to version 0.9.3 of that library.
Now the call goes out to Jeff Dwyer to update MyHippoCampus to the latest stuff and put it through its paces. Thanks Jeff!
Next up? Well, I'm going to slap it into one of the samples and do some testing, and then work on promoting it out of the sandbox. Hopefully we can get openId support into the main project soon :)
Wednesday, January 09, 2008
OpenID Gains Steam
From Techcrunch
TechCrunch UK’s Mike Butcher is reporting that Google, IBM and Verisign are in late stage discussions with the OpenID Foundation.
Good to see OpenID getting some traction. I really regret not finishing up the OpenID support for Acegi now. The code is still there in the sandbox. It apparently works, the folks over at MyHippoCampus were using it.
Tuesday, January 08, 2008
An Exercise in Flowcharting
Wednesday, January 02, 2008
Is Rails a Ghetto?
Zed Shaw, creator of the extremely popular Mongrel server for Rails applications, thinks so.
Rails Is A Ghetto
Even if you don't know a damn thing about Ruby or Rails this is some pretty funny shit.
Rails Is A Ghetto
Even if you don't know a damn thing about Ruby or Rails this is some pretty funny shit.
Friday, December 21, 2007
Ruby on Rails Stuff
I've found a few interesting resources for Ruby on Rails stuff and I figure I'll link 'em up here.
First up, Railscasts.com; a collection of video screencasts on various small Rails tricks.
Railscasts.com
Next, a presentation from Dave Thomas at QCon about meta-programming in Ruby.
MetaProgramming - Extending Ruby for Fun and Profit
Rails 2.0 just came out, here's a post from DHH about some of the new features.
Rails 2.0: Preview Release
Also, if you don't own a Mac and therefore don't have that sexy Textmate editor, you might consider NetBeans 6.0. Netbeans used to be a joke of an IDE for Java but it's really come along nicely for Java and has really excelled in it's support for Ruby and Ruby on rails.
NetBeans: Ruby Developer's New Best Friend (Part 1)
NetBeans: Ruby Developer's New Best Friend (Part 2)
First up, Railscasts.com; a collection of video screencasts on various small Rails tricks.
Railscasts.com
Next, a presentation from Dave Thomas at QCon about meta-programming in Ruby.
MetaProgramming - Extending Ruby for Fun and Profit
Rails 2.0 just came out, here's a post from DHH about some of the new features.
Rails 2.0: Preview Release
Also, if you don't own a Mac and therefore don't have that sexy Textmate editor, you might consider NetBeans 6.0. Netbeans used to be a joke of an IDE for Java but it's really come along nicely for Java and has really excelled in it's support for Ruby and Ruby on rails.
NetBeans: Ruby Developer's New Best Friend (Part 1)
NetBeans: Ruby Developer's New Best Friend (Part 2)
Saturday, December 15, 2007
A Brief Introduction to REST
InfoQ posted a very good article introducting the concepts of REST. If you've heard the buzz and are looking for a practical explanation, this looks like a good place to start.
A Brief Introduction to REST
A Brief Introduction to REST
Tuesday, November 20, 2007
Spring Framework 2.5 Released
http://www.springframework.org/node/561
The latest version of Spring is released, and it has tons of new features. I can't wait to get them going in some of my projects. I'm especially excited about using the @Resource annotation support.
The good folks at InfoQ have posted the first of a series of articles about Spring 2.5. Have a look...
http://www.infoq.com/articles/spring-2.5-part-1
The latest version of Spring is released, and it has tons of new features. I can't wait to get them going in some of my projects. I'm especially excited about using the @Resource annotation support.
The good folks at InfoQ have posted the first of a series of articles about Spring 2.5. Have a look...
http://www.infoq.com/articles/spring-2.5-part-1
Thursday, November 15, 2007
NBC Pulls their Youtube Channel
I just noticed today that NBC pulled down their YouTube channel. This is a tragedy. I loved watching the stuff they put up. I was generally impressed with NBC and the amount of content they were putting out on YouTube. Hell, I am still impressed that you could watch past episodes of their shows on their site.
Unfortunately, I shouldn't have to be impressed by this. How hard is that? You lace some commercials in for revenue and you put the stuff online to watch. How different is that from TV right now?
Good bye http://www.youtube.com/NBC, thanks for breaking all the links on my SNL Digital Shorts post...
Unfortunately, I shouldn't have to be impressed by this. How hard is that? You lace some commercials in for revenue and you put the stuff online to watch. How different is that from TV right now?
Good bye http://www.youtube.com/NBC, thanks for breaking all the links on my SNL Digital Shorts post...
Tuesday, October 30, 2007
Introduction to the Spring Framework 2.5
Rod Johnson updated his "Introduction to the Spring Framework" article to include the Spring 2.5 updates.
I've always forwarded this article on to folks that are new to Spring to get a footing.
Link
I've always forwarded this article on to folks that are new to Spring to get a footing.
Link
Friday, October 19, 2007
Securing Java Applications with Acegi
Consutlant Bilal Siddiqui wrote a series of articles at IBM developerWorks around Acegi. Definitely worth a read if you're trying to understand Acegi. Our reference guide is good, but it's a bit over the top for most folks.
The first article was released in March 2007. The third part was released on September 25 2007. I've fallen behind on my feed reading a bit :P
The first article was released in March 2007. The third part was released on September 25 2007. I've fallen behind on my feed reading a bit :P
Thursday, October 18, 2007
IntelliJ IDEA 7.0 Released
IntelliJ IDEA 7.0 was released three days ago. I just got it up and running here, so I'll be feeling out the new features.
The folks at IntelliJ were kind enough to provide the developers of the Acegi Security (aka Spring Security) framework an Open Source license for use in the Acegi Security project. In the past I had to contact them when new major releases came out. This time they were on the ball. A new license key was mailed out the next day. So, if you work on an open source project and would like to try out IntelliJ you can apply for an Open Source license.
Now a quick list, for my own reference really, of the features I'm most interested in...
These are just the new or improved features. I already believe that IDEA is simply the best Java IDE out there. Period. Lots of folks complain that it's not free. Well, it is free to Open Source projects, and the individual license is pretty respectable at US$249.
I think I'll try out the new features and build a sample project around my DAO articles and upload it here...
The folks at IntelliJ were kind enough to provide the developers of the Acegi Security (aka Spring Security) framework an Open Source license for use in the Acegi Security project. In the past I had to contact them when new major releases came out. This time they were on the ball. A new license key was mailed out the next day. So, if you work on an open source project and would like to try out IntelliJ you can apply for an Open Source license.
Now a quick list, for my own reference really, of the features I'm most interested in...
- Maven Integration
- XML Refactorings
- Ruby, JRuby and Rails
- Improved Spring Support (this looks awesome)
- Hibernate Support (again, this looks really good too)
- Groovy and Grails (I'm a big fan of Groovy, maybe not so much Grails)
These are just the new or improved features. I already believe that IDEA is simply the best Java IDE out there. Period. Lots of folks complain that it's not free. Well, it is free to Open Source projects, and the individual license is pretty respectable at US$249.
I think I'll try out the new features and build a sample project around my DAO articles and upload it here...
Friday, October 12, 2007
Video: Rolling out Web Services the Right Way with Spring-WS
http://www.springframework.org/node/544
Posted two days ago at Springframework.org, a video about the Spring Web Services project. The video is a recording of Arjen Poutsma of Interface21 at the Spring Experience conference in December 2006.
We have chosen Spring-WS for a project my team is starting at work. We will definitely sit down and watch this. I have no idea if the video is good or not, I haven't watched it yet. Arjen is a really smart dude, so I'd imagine there's some good information here.
Posted two days ago at Springframework.org, a video about the Spring Web Services project. The video is a recording of Arjen Poutsma of Interface21 at the Spring Experience conference in December 2006.
We have chosen Spring-WS for a project my team is starting at work. We will definitely sit down and watch this. I have no idea if the video is good or not, I haven't watched it yet. Arjen is a really smart dude, so I'd imagine there's some good information here.
Friday, October 05, 2007
Saturday Night Live: Digital Shorts
At lunch today someone mentioned that they don't watch SNL any more. They asked if it was still funny. Honestly, they can't all be gems, but yeah it's definitely still funny from time to time. When people think about SNL, they only remember what they want to remember. Most folks tend to remember the "Land Shark", the "Samurai Tailor", and most stuff Dana Carvey did. You know what was in between all those memorable skits? Stuff that wasn't funny.
So, like I said, they can't all be gems. SNL has been on a roll with creating these "Digital Shorts" the last view years. Most of them are hysterical. I've already embedded a few of them here in the past. Today, in response to the lunch conversation, I've compiled a list...
“Lazy Sunday”
“Special Christmas Box”
“United Way” (Peyton Manning isn’t the nice guy you think he is)
“Maraka” (If your kids watch Dora)
“Apacalypto Recut” (A shot at Mel Gibson, who was um in the news at the time)
“I Ran”
“Natalie Portman” (Her Gangsta Lifestyle...)
You'll notice most of these are actually published by NBC, which is very cool. You'll also see that they almost all contain a shaggy haired kid named Andy Samberg. I think Andy is one of their big up-and-coming stars right now.
Andy is also a member of "The Lonely Island" writing group. It turns out that they wrote most of the really good digital shorts. Have a look :)
http://www.thelonelyisland.com/digitalshorts.html
So, like I said, they can't all be gems. SNL has been on a roll with creating these "Digital Shorts" the last view years. Most of them are hysterical. I've already embedded a few of them here in the past. Today, in response to the lunch conversation, I've compiled a list...
“Lazy Sunday”
“Special Christmas Box”
“United Way” (Peyton Manning isn’t the nice guy you think he is)
“Maraka” (If your kids watch Dora)
“Apacalypto Recut” (A shot at Mel Gibson, who was um in the news at the time)
“I Ran”
“Natalie Portman” (Her Gangsta Lifestyle...)
You'll notice most of these are actually published by NBC, which is very cool. You'll also see that they almost all contain a shaggy haired kid named Andy Samberg. I think Andy is one of their big up-and-coming stars right now.
Andy is also a member of "The Lonely Island" writing group. It turns out that they wrote most of the really good digital shorts. Have a look :)
http://www.thelonelyisland.com/digitalshorts.html
Wednesday, September 26, 2007
Adding Generics to the AbstractHibernateDao
In my previous post, "The Best AbstractHibernateDao Ever", I made a passing reference to the generics being a problem.
So now, in slight contradiction to my "The Best Generic Dao Interface Ever" article, I am going to add Generics to the "AbstractHibernateDao".
If you don't know what Generics are, and you're a Java developer, you obviously aren't keeping up-to-date with your chosen trade. In fact, you should stop reading my blather and go study. Start here "New Features and Enhancements J2SE 5.0". Be sure to read the "Generics Tutorial"
Alrighty then. Why do we want generics on our DAO? Let's look back at our UserDao example, and have a look specifically at our "findAll" method...
The problem with this method is in it's definition on the AbstractHibernateDao. The "all()" method comes from the AbstractHibernateDao and is defined like...
Why are generics a problem here? Well the Hibernate critria returns a "List". It is a list of "Object"s, nothing more. Our AbstractHibernateDao respects that and returns a "List". This "List" is a "List<Object>" (a "List of objects"). Our UserDao on the other hand returns a "List<User>" (a "List of Users").
Well now we have a mismatch, a "List of Objects" is not a "List of Users", we are implying specifics that aren't enforced. Unfortunately there isn't much we can do about it. Hibernate doesn't have generics, so we have to have some faith that when we ask Hibernate for Users, it's going to give Users, not Toast. The easy fix for that is to mark our "UserDaoImpl.findAll()" method with the SuppressWarnings Annotation...
That fixed it right? Wrong. This sucks. This sucks because I'll need to put this @SuppressWarnings annotation all over the place. I need it on each on all of the methods that return lists. I'll need it on most of the methods in every Dao I create. So like I said, this sucks.
OH! And don't forget about all the downcasting we're doing...
Here, we are downcasting the "Object" returned from "uniqueResult()" to the "User" instance we asked for. Generics can help with all this.
My goal is for the DaoImpls to be "downcast" and "SuppressWarnings" free. In order to accomplish this I need to push the "dirty" stuff up into the AbstractHibernateDao. So I'll add a few wrapper methods that handle the downcasting and untyped collections...
So, now, I've added generics to the AbstractHibernateDao. I've changed the class declaration to...
Let's just jump right into the changes this makes to our UserDaoImpl...
By employing Generics on the AbstractHibernateDao and isolating all downcasting and warning suppression to AbstractHibernateDao we can have a much cleaner DaoImpl. What I did was add wrapper methods to the AbstractHibernateDao for list(Criteria), list(Query), uniqueResult(Criteria), and uniqueResult(Query).
Using these new wrapper methods you see that the UserDaoImpl no longer calls query.list() it calls list(query) to get back a typed list. Also, the UserDaoImpl no longer calls criteria.uniqueResult(), it calls uniqueResult(criteria).
The isolation gives us one place to hide our dirty laundry (the AbstractHibernateDao). Maybe, some day, Hibernate will support Generics. That day is probably very, very far away. I would have thought the new JPA EntityManager API would support generics. Apparently it does not either, how unfortunate.
So now, in slight contradiction to my "The Best Generic Dao Interface Ever" article, I am going to add Generics to the "AbstractHibernateDao".
If you don't know what Generics are, and you're a Java developer, you obviously aren't keeping up-to-date with your chosen trade. In fact, you should stop reading my blather and go study. Start here "New Features and Enhancements J2SE 5.0". Be sure to read the "Generics Tutorial"
Alrighty then. Why do we want generics on our DAO? Let's look back at our UserDao example, and have a look specifically at our "findAll" method...
public List<User> findAll() {
return all();
}
The problem with this method is in it's definition on the AbstractHibernateDao. The "all()" method comes from the AbstractHibernateDao and is defined like...
protected List all() {
return criteria().list();
}
Why are generics a problem here? Well the Hibernate critria returns a "List". It is a list of "Object"s, nothing more. Our AbstractHibernateDao respects that and returns a "List". This "List" is a "List<Object>" (a "List of objects"). Our UserDao on the other hand returns a "List<User>" (a "List of Users").
Well now we have a mismatch, a "List of Objects" is not a "List of Users", we are implying specifics that aren't enforced. Unfortunately there isn't much we can do about it. Hibernate doesn't have generics, so we have to have some faith that when we ask Hibernate for Users, it's going to give Users, not Toast. The easy fix for that is to mark our "UserDaoImpl.findAll()" method with the SuppressWarnings Annotation...
//fixin it the lazy way
@SuppressWarnings("unchecked")
public List findAll() {
return all();
}
That fixed it right? Wrong. This sucks. This sucks because I'll need to put this @SuppressWarnings annotation all over the place. I need it on each on all of the methods that return lists. I'll need it on most of the methods in every Dao I create. So like I said, this sucks.
OH! And don't forget about all the downcasting we're doing...
public User findByUsername(String username) {
return (User) criteria().add(
Restrictions.eq("username", username)
).uniqueResult();
}
Here, we are downcasting the "Object" returned from "uniqueResult()" to the "User" instance we asked for. Generics can help with all this.
My goal is for the DaoImpls to be "downcast" and "SuppressWarnings" free. In order to accomplish this I need to push the "dirty" stuff up into the AbstractHibernateDao. So I'll add a few wrapper methods that handle the downcasting and untyped collections...
public abstract class AbstractHibernateDao<E> {
private final Class<E> entityClass;
private final SessionFactory sessionFactory;
public AbstractHibernateDao(
Class<E> entityClass,
SessionFactory sessionFactory) {
Assert.notNull(entityClass,
"entityClass must not be null");
Assert.notNull(sessionFactory,
"sessionFactory must not be null");
this.entityClass = entityClass;
this.sessionFactory = sessionFactory;
}
protected Criteria criteria() {
return currentSession().createCriteria(entityClass);
}
protected Query query(String hql) {
return currentSession().createQuery(hql);
}
protected Session currentSession() {
return sessionFactory.getCurrentSession();
}
protected List<E> all() {
return list(criteria());
}
public Class<E> getEntityClass() {
return entityClass;
}
/*=== BEGIN GENERICS SUPPRESSION WRAPPERS ===*/
@SuppressWarnings("unchecked")
protected List<E> list(Criteria criteria) {
return criteria.list();
}
@SuppressWarnings("unchecked")
protected List<E> list(Query query) {
return query.list();
}
@SuppressWarnings("unchecked")
protected E uniqueResult(Criteria criteria) {
return (E) criteria.uniqueResult();
}
@SuppressWarnings("unchecked")
protected E uniqueResult(Query query) {
return (E) query.uniqueResult();
}
@SuppressWarnings("unchecked")
protected E get(Serializable id) {
return (E) currentSession().get(entityClass, id);
}
}
So, now, I've added generics to the AbstractHibernateDao. I've changed the class declaration to...
public abstract class AbstractHibernateDao<E>
Let's just jump right into the changes this makes to our UserDaoImpl...
public class UserDaoImpl extends AbstractHibernateDao<User> implements UserDao {
public UserDaoImpl(SessionFactory sessionFactory) {
super(User.class, sessionFactory);
}
public User findById(Long id) {
return get(id);
}
public User findByUsername(String username) {
return uniqueResult(criteria().add(
Restrictions.eq("username", username)
));
}
public List<User> findByEmail(String email) {
return list(query("from User u where u.email = :email")
.setParameter("email", email)
);
}
public List<User> findAll() {
return all();
}
public void save(User user) {
currentSession().saveOrUpdate(user);
}
public void delete(User user) {
currentSession().delete(user);
}
}
By employing Generics on the AbstractHibernateDao and isolating all downcasting and warning suppression to AbstractHibernateDao we can have a much cleaner DaoImpl. What I did was add wrapper methods to the AbstractHibernateDao for list(Criteria), list(Query), uniqueResult(Criteria), and uniqueResult(Query).
Using these new wrapper methods you see that the UserDaoImpl no longer calls query.list() it calls list(query) to get back a typed list. Also, the UserDaoImpl no longer calls criteria.uniqueResult(), it calls uniqueResult(criteria).
The isolation gives us one place to hide our dirty laundry (the AbstractHibernateDao). Maybe, some day, Hibernate will support Generics. That day is probably very, very far away. I would have thought the new JPA EntityManager API would support generics. Apparently it does not either, how unfortunate.
Monday, September 24, 2007
The Best AbstractHibernateDao Ever
(Follow up to "The Best Generic DAO Interface Ever")
I love the 3rd grade title theme I got going on here. Anyway...
I've seen so many incarnations of an AbstractHibernateDao out there; some are good, some are bad. Myself, I've always gone the AbstractHibernateDao extends HibernateDaoSupport route myself. I'm a huge fan of Spring for the amount of helpful stuff it provides in all areas of "Enterprisey Software Development".
I've done some re-thinking of the Spring Dao concept lately. See, according to Alef Arendsen of Interface21, "start using the Session and/or EntityManager API directly". In other words, stop using the HibernateTemplate, it isn't really useful.
As it turns out in Spring 2.x in combination with Hibernate 3.x (I'd go with no less than 3.2.1), you don't need the HibernateTemplate. If you are using the Spring LocalSessionFactoryBean to configure your Hibernate SessionFactory, the HibernateTemplate just isn't needed. The reason is that the LocalSessionFactoryBean creates a proxy SessionFactory that implements the SessionFactory.getCurrentSession() method appropriately for Spring intercepted classes.
So if you're using Spring Transaction management (via annotations, declarative xml, or what-have-you), you don't need the HibernateTemplate. Now, the one area that the HibernateTemplate does help with is the Exception translation. Hibernate 2.x just threw HibernateException for everything, you were left guessing really what the true problem was. The Spring HibernateTemplate would translate these 'bad' HiberatenExceptions into Spring's DataAccessException hierarchy. This meant that you could easily handle DataIntegrityViolationException vs. IncorrectResultSizeDataAccessException. Well, Hibernate 3.x has it's own exception hierarchy. So you can handle ConstraintViolationException vs. NonUniqueObjectException.
If you want that exception translation, there's some voodoo you can do with an annotation called "@Repository" (There's that repository word I mentioned in my last post). This annotation wraps your Dao (or Repository) with a proxy that will convert the HibernateExceptions to DataAccessExceptions. I don't think it's really that useful to do, so I don't do it...
So, now, if we combine Spring's Handling of the Session for us, with the Hibernate SessionFactory.getCurrentSession() we get a very simple, very clean AbstractHibernateDao to base our Dao's from...
The purpose of the AbstractHibernateDao above is to take away any work the sub-class Dao might have to do regarding the "Persistent Class" it's responsible for. Meaning that subclasses don't have to pass the Class all the time.
What does it look like in use? Well, let's pretend we have a User entity and a UserDao.
First, our "User" entity...
And now the User Dao or Repository...
Now let's implement that UserDao using our AbstractHibernateDao...
If you're curious about what the "Dao" interface here looks like, see my previous post "The Best Generic Dao Interface Ever". Or you can skip it and just know that the Dao interface is simply a Marker, there isn't a single method on it.
Understanding this Dao infrastructure has a very low barrier to entry. You don't need to know how the Spring HibernateTemplate interacts with the Hibernate Session to use this. You only need to know how to use the Hibernate Session. There is very little noise in this Dao, it is all directly related to querying Hibernate, as it should be.
This implementation relies on the Hibernate SessionFactory.getCurrentSession() method. When you combine Spring with Hibernate here you get a very elegant solution with no stuff about transactions or any weird abstraction layer in the way. There are whole books around using the Hibernate Session. The Spring HibernateTemplate only gets a few pages dedicated to it in any Spring book. That right there means you spend less time explaining it to people, tell them to "Read the freakin' manual".
Disclaimer: You might notice that there are some generics used in here that will cause "unchecked" warnings. I didn't bother with a lot of generics and the @SuppressWarnings("unchecked") stuff in this example because they can be distracting. To see the generics cleaned up, read "Adding Generics to the AbstractHibernateDao"
I love the 3rd grade title theme I got going on here. Anyway...
I've seen so many incarnations of an AbstractHibernateDao out there; some are good, some are bad. Myself, I've always gone the AbstractHibernateDao extends HibernateDaoSupport route myself. I'm a huge fan of Spring for the amount of helpful stuff it provides in all areas of "Enterprisey Software Development".
I've done some re-thinking of the Spring Dao concept lately. See, according to Alef Arendsen of Interface21, "start using the Session and/or EntityManager API directly". In other words, stop using the HibernateTemplate, it isn't really useful.
As it turns out in Spring 2.x in combination with Hibernate 3.x (I'd go with no less than 3.2.1), you don't need the HibernateTemplate. If you are using the Spring LocalSessionFactoryBean to configure your Hibernate SessionFactory, the HibernateTemplate just isn't needed. The reason is that the LocalSessionFactoryBean creates a proxy SessionFactory that implements the SessionFactory.getCurrentSession() method appropriately for Spring intercepted classes.
So if you're using Spring Transaction management (via annotations, declarative xml, or what-have-you), you don't need the HibernateTemplate. Now, the one area that the HibernateTemplate does help with is the Exception translation. Hibernate 2.x just threw HibernateException for everything, you were left guessing really what the true problem was. The Spring HibernateTemplate would translate these 'bad' HiberatenExceptions into Spring's DataAccessException hierarchy. This meant that you could easily handle DataIntegrityViolationException vs. IncorrectResultSizeDataAccessException. Well, Hibernate 3.x has it's own exception hierarchy. So you can handle ConstraintViolationException vs. NonUniqueObjectException.
If you want that exception translation, there's some voodoo you can do with an annotation called "@Repository" (There's that repository word I mentioned in my last post). This annotation wraps your Dao (or Repository) with a proxy that will convert the HibernateExceptions to DataAccessExceptions. I don't think it's really that useful to do, so I don't do it...
So, now, if we combine Spring's Handling of the Session for us, with the Hibernate SessionFactory.getCurrentSession() we get a very simple, very clean AbstractHibernateDao to base our Dao's from...
public abstract class AbstractHibernateDao {
private final Class entityClass;
private final SessionFactory sessionFactory;
public AbstractHibernateDao(
Class entityClass,
SessionFactory sessionFactory) {
Assert.notNull(entityClass,
"entityClass must not be null");
Assert.notNull(sessionFactory,
"sessionFactory must not be null");
this.entityClass = entityClass;
this.sessionFactory = sessionFactory;
}
protected Criteria criteria() {
return currentSession().createCriteria(entityClass);
}
protected Query query(String hql) {
return currentSession().createQuery(hql);
}
protected Session currentSession() {
return sessionFactory.getCurrentSession();
}
protected List all() {
return criteria().list();
}
protected Object get(Serializable id) {
return currentSession().get(entityClass, id);
}
public Class getEntityClass() {
return entityClass;
}
}
The purpose of the AbstractHibernateDao above is to take away any work the sub-class Dao might have to do regarding the "Persistent Class" it's responsible for. Meaning that subclasses don't have to pass the Class all the time.
What does it look like in use? Well, let's pretend we have a User entity and a UserDao.
First, our "User" entity...
public class User {
private Long id;
private String username;
private String email;
//getters and setters omitted
}
And now the User Dao or Repository...
public interface UserDao extends Dao {
User findById(Long id);
User findByUsername(String username);
ListfindByEmail(String email);
ListfindAll();
void save(User user);
void delete(User user);
}
Now let's implement that UserDao using our AbstractHibernateDao...
public class UserDaoImpl extends AbstractHibernateDao implements UserDao {
public UserDaoImpl(SessionFactory sessionFactory) {
super(User.class, sessionFactory);
}
public User findById(Long id) {
return (User) get(id);
}
public User findByUsername(String username) {
return (User) criteria().add(
Restrictions.eq("username", username)
).uniqueResult();
}
public ListfindByEmail(String email) {
return query("from User u where u.email = :email")
.setParameter("email", email)
.list();
}
public ListfindAll() {
return all();
}
public void save(User user) {
currentSession().saveOrUpdate(user);
}
public void delete(User user) {
currentSession().delete(user);
}
}
If you're curious about what the "Dao" interface here looks like, see my previous post "The Best Generic Dao Interface Ever". Or you can skip it and just know that the Dao interface is simply a Marker, there isn't a single method on it.
Understanding this Dao infrastructure has a very low barrier to entry. You don't need to know how the Spring HibernateTemplate interacts with the Hibernate Session to use this. You only need to know how to use the Hibernate Session. There is very little noise in this Dao, it is all directly related to querying Hibernate, as it should be.
This implementation relies on the Hibernate SessionFactory.getCurrentSession() method. When you combine Spring with Hibernate here you get a very elegant solution with no stuff about transactions or any weird abstraction layer in the way. There are whole books around using the Hibernate Session. The Spring HibernateTemplate only gets a few pages dedicated to it in any Spring book. That right there means you spend less time explaining it to people, tell them to "Read the freakin' manual".
Disclaimer: You might notice that there are some generics used in here that will cause "unchecked" warnings. I didn't bother with a lot of generics and the @SuppressWarnings("unchecked") stuff in this example because they can be distracting. To see the generics cleaned up, read "Adding Generics to the AbstractHibernateDao"
Subscribe to:
Posts (Atom)