Showing posts with label Spring. Show all posts
Showing posts with label Spring. Show all posts

Thursday, April 16, 2009

Follow up to the AbstractHibernateDao

In my writing about the AbstractHibernateDao here I mention that you no longer need to extend HibernateDaoSupport class. You do lose one thing though. Your new AbstractHibernateDao based DAO will now throw HibernateExceptions, not Spring DataAccessExceptions. Now, to me, this isn't the end of the world. In a Hibernate 3.2+ world Hibernate does have a clear exception hierarchy. Not like the old days where there was just "HibernateException". That sucked.

If you do want your DAOs to throw Spring DataAccessExceptions there are two simple things to do.
  1. Add the @Repository annotation to your DAO impl.
  2. Add a PersistenceExceptionTranslationPostProcessor bean to your Spring setup.

What this does is tell Spring to wrap an interceptor around your DAO bean that handles the exception translation.

Looking at the UserDaoImpl from the past article...

@Repository
public class UserDaoImpl extends AbstractHibernateDao<User> implements UserDao {

public UserDaoImpl(SessionFactory sessionFactory) {
super(User.class, sessionFactory);
}
...
}

Then in your Spring application context.xml you simply add one line...




Now, this pattern I present is somewhat old school. There is all this fancy component scanning stuff you can do with the Spring 2.5 XML namespaces. Honestly the amount of voodoo that goes on there freaks me out a bit. You can study that on your own if you'd like. A good place to start is here.

Sunday, May 04, 2008

SpringSource Application Platform Details

Last week SpringSource announced their Application Platform project. It is an interesting attempt at slimming down the J2EE environment by tying things like Spring and OSGI together. On the SpringSource Team Blog, Rob Harrop begins an in-depth explanation of SpringSource Application Platform and it's features. Very interesting stuff...

Wednesday, April 30, 2008

SpringSource Application Platform

The guys over at SpringSource have created an "Application Platform" based on Tomcat, Spring, and OSGI. Interesting stuff, read more at InfoQ.

I'm gonna get my hands on the beta. Though if they intend to release it as Open Source anyway, why is there a beta sign up? Odd...

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 :)

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

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

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.

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...

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...


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);

List findByEmail(String email);

List findAll();

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 List findByEmail(String email) {
return query("from User u where u.email = :email")
.setParameter("email", email)
.list();
}

public List findAll() {
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"

Monday, July 02, 2007

Groovy Views in Spring MVC

I thought it might be fun to try and implement Groovy as a View technology in Spring MVC. Most people that use Spring MVC are familiar with the JstlView for Jsps, or the VelocityView for Velocity templates, and the far superior FreemarkerView for FreeMarker templates.

So, let's think about what we'd have to do to use Groovy to render views...
We'd need to be able to load a resource as a groovy script, bind some stuff to it (the request, response.getWriter as out), and evaluate it.

Well, it turns out it wasn't fun at all. In all of about 10 minutes I got it working and it was really boring...
Keep in mind that the code here is totally rudimentary, there's no caching or anything like that. Anyway, check it out...

public class GroovyView extends AbstractTemplateView {

private static final Logger log = Logger.getLogger(GroovyView.class);

protected void renderMergedTemplateModel(Map model, HttpServletRequest request, HttpServletResponse response)
throws Exception {

Binding binding = createBinding(model, request, response);

GroovyShell shell = createGroovyShell(binding, request, response);

Resource resource = loadViewResource(request, response);

if (log.isDebugEnabled()) {
log.debug("resource: [" + resource + "]");
}

evaluateViewResource(shell, resource);
}

protected Binding createBinding(Map model, HttpServletRequest request, HttpServletResponse response)
throws IOException {
Binding binding = new Binding(model);
binding.setVariable("request", request);
binding.setVariable("out", response.getWriter());

return binding;
}

protected GroovyShell createGroovyShell(Binding binding, HttpServletRequest request, HttpServletResponse response) {
return new GroovyShell(binding);
}

protected void evaluateViewResource(GroovyShell shell, Resource resource)
throws IOException {
shell.evaluate(resource.getInputStream());
}

protected Resource loadViewResource(HttpServletRequest request, HttpServletResponse response) {
return getApplicationContext().getResource(getUrl());
}
}

OK, there's the implementation, how would you use it in Spring? Well you can combine it with a UrlBasedViewResolver.

<bean id="groovyViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="prefix" value="WEB-INF/views/">
<property name="suffix" value=".groovy"/>
<property name="viewClass" value="raykrueger.GroovyView"/>
</bean>

Really just follow any Spring MVC 101 example you can find on the internet and use the GroovyView here. Then you can create groovy scripts to use as views that look like...

builder = new groovy.xml.MarkupBuilder(out)

builder.html {
head {
title "Hi there"
}
body {
p "Hello from the GroovyView"
p "Neat Huh?"
a(href:'http://raykrueger.blogspot.com', "Ray Krueger's Blog")
}
}

Then you have all the power of Groovy at your fingertips to build views for your models. Accessing fields and looping iterators is a boatload easier in Groovy than in jstl. Though, honestly, you can do a lot of this stuff with Freemarker...

Now, I'm sure you can clean this up a bit and optimize the crap out of it (view caching and such). Really I just slapped this together as a thought.

Here's the source

Wednesday, May 16, 2007

Update: Acegi and OpenID

I was going full-tilt into refactoring the OpenID support in Acegi. Unfortunately I got held up with home and work (gotta have your priorities in order). There are few central points that I'm focusing on right now...
  1. Replace the JanRain support with OpenId4Java.
  2. Replace the Servlet that is in there with an AuthenticationProcessingFilter based approach.
  3. Try and get some form of integration into the contacts sample.
The JanRain library is all but deceased, and it doesn't seem to support redirects anway. The OpenId4Java library seems to be the most active, and properly supports redirects and discovery. The Servlet that is in there now is well intended but doesn't mesh with the overall architecture in Acegi.

I'm going to try and get this stuff ramped up pretty quickly. Since Ben Alex is starting rumors he's going to be talking about it at Spring One.

Friday, April 20, 2007

OpenID support in Acegi Security

SourceForge.net: acegisecurity-developer

Acegi security now has a first-draft of OpenID support as provided by Robin Bramley of Opsera Limited. We'll definitely need to get some documentation and samples going. It's a great start though.

More info on OpenId...

Thursday, December 07, 2006

On my way to Spring Experience '06

I'm stuck in O'Hare...
My flight was supposed to be at like 7:30 CST. It's been delayed twice. I'm not scheduled to fly until 9:18.

So I try and pick up a wireless network. I see a solid connection to the 'concourse' network. It is the in-house wireless network available. Well, of course, it's not free. Luckily I know how to use my blackberry as a modem and can get a connection through that. Thanks Vinay! It's not a bad connection 100k according to the excellent speed test at InternetFrog.
So, now, I'm scheduled to depart at 9:18 and arrive in Miami at 1:18. The plane is pulling into the concourse as I type this. So, as my new favorite video blogger - Zefrank - says, "It's fire eagle danger day"...

Sunday, November 26, 2006

Spring 2.0 property shorthand

It turns out that with Spring 2.0 XSD support there is a fancy little shorthand for setting properties on a bean.
Read More

XML Example from Rod's post...

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean class="com.interface21.spring2.ioc.Person"
p:name="Tony"
p:age="53"
p:house-ref="number10"
/>

<bean class="com.interface21.spring2.ioc.House"
id="number10"
p:name="10 Downing Street"
/>

Now that's cool