Nothing Is Permanent Except Change - How Software Architects Can Embrace Change
Michael Stal discusses system architecture quality, how to avoid architectural erosion, how to deal with refactoring, and design principles for architecture evolution.
The content has been bookmarked!
There was an error bookmarking this content! Please retry.

Posted by Oliver Gierke on Dec 20, 2010
Almost every application out there in the world has to access data to do its work. Using a domain driven design approach you will need to define and build repositories for the entities that make up your domain. Java developers nowadays often use JPA to implement these repositories. JPA has made this task easier, but still requires a lot of boilerplate code. Hades is an open source library that's built on top of JPA and Spring to significantly improve the implementation of data access layers by reducing the effort to the amount that's actually needed. This article will take you on a guided tour and give you an overview on what Hades can actually do for you regarding data access layer development and takes a look at the new features of the very recent version 2.0.
The very core part of Hades consists of a generic repository implementation that provides you not only with basic CRUD (create, read, update and delete) methods but adds some functionality on top that removes the need to implement common scenarios around that (e.g. pagination) yourself. This includes the ability to query the repository for pages of entities, dynamically adding sort definitions and so on.
As most of the data access operations you typically have to implement are querying operations one of Hades' core features is to ease defining and executing queries with the least effort possible. The process of doing so actually consists of three steps:
In the first step you declare an interface that extends GenericDao<Entity, Id> which will cause the CRUD operations defined in the Hades interface being available on your interface as well:
public interface UserRepository extends GenericDao<User, Long> { … }
The next step is adding methods for your queries to the interface that serve your business requirements:
List findByUsername(String username);
This should raise the question of how the query will be derived from the method. If you don't add any additional metadata, Hades will try to lookup a JPA named query of the form {entity}.{method-name} and use that if available. In case it does not find any it will try to parse the method name and create a query from it. So the prior example would result in a query select u from User u where u.username = ?. The query parser of course supports a lot more keywords, so feel free to check them out in the reference documentation.
If you prefer defining the query manually you can leverage Hades' @Query annotation to define the query to be executed directly at the method:
@Query("select from User u where u.lastname = ?");
List someReallyStrangeName(String lastname);
This gives you freedom in naming methods the way you like while preserving the full control over the query definition without bothering you with the boilerplate query execution code. There's lots of other stuff around executing queries like using pagination with queries, executing modifying queries and so on.
So now that you have seen how to create repository interfaces with query methods it's probably interesting how you get that stuff started and ready to be used. You can create instances for the repository interface by creating a GenericDaoFactory instance and ask it to create repositories for you:
EntityManager em = … // Get access to EntityManager GenericDaoFactory factory = GenericDaoFactory.create(em); UserRepository userRepository = factory.getDao(UserRepository.class);
As repositories are usually handed to its clients by dependency injection there is sophisticated integration for Hades' usage inside a Spring application. So to bootstrap Hades in a Spring app you simply use the Hades namespace and declare a base package that shall be scanned for repositories.
<hades:dao-config base-package="com.acme.*.repository" />
This would pick up all repository interfaces extending GenericDao and create Spring beans for each of them. Of course the namespace allows much more fine grained control over what's to be detected. The Hades Eclipse plugin provides seamless integration into Spring IDE and SpringSource Tool Suite (STS) so that you will be able to reference Hades repositories from other beans, have them marked as Spring beans in your workspace and so on. For details check out the reference documentation.
It's a very common requirement to track creator, modifier and the according dates for entities. Hades provides an EntityListener that will transparently do the job for you. To activate Hades auditing you need to define the AuditingEntityListener in your orm.xml
<persistence-unit-metadata>
<persistence-unit-defaults>
<entity-listeners>
<entity-listener class="org.synyx.hades.domain.auditing.support.AuditingEntityListener" />
</entity-listeners>
</persistence-unit-defaults>
</persistence-unit-metadata>
and then activate auditing in your Spring config as follows:
<hades:auditing auditor-aware-ref="auditorAware" />
The referenced Spring bean auditorAware has to implement the AuditorAware interface that you'd typically implement querying your security module for the current user. If you only want to track creation and modification date, just omit the attribute. For more on the auditing feature, consult the documentation.
As of version 2.0 Hades is based on JPA 2.0 as well as the according versions of Hibernate, EclipseLink and OpenJPA. Starting with that version the CRUD operations are transactional out of the box so that in very simple cases there's no need for a transactional wrapping layer anymore. Furthermore concrete repository interfaces can be made transactional easily as well.
public interface UserRepository extends GenericDao<User, Long> {
@Transactional(readOnly = true);
List<User> findByUsername();
@Override
@Transactional(readOnly = true, timeout = 60);
List<User> readAll();
}
As you can see you can simply annotate the query methods with @Transactional to let them participate in transactions. You don't have to use annotations if you don't like to, XML based transaction configuration simply works as well. The CRUD operations implemented in GenericDao are transactional by default (with readOnly set to true for read-only operations). Reconfiguring transaction settings for those methods is done by simply redeclaring the method and applying a custom @Transactional on it. For more details check out the reference documentation on transactions.
A quite cool feature of the latest release is the extension ofGenericDao to be able to execute specifications. A specification is a Domain Driven Design concept coined by Eric Evans and Martin Fowler that boils down to capturing business rules for an entity into a predicate. Hades provides an abstraction to easily build such predicates based on the JPA 2.0 criteria API. Supposed you have books written by authors. Hades let's you define specifications like that:
class BookSpecifications {
public Specification<Book> hasAuthorWithFirstnameLike(final String firstname) {
return new Specification<Book>() {
public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
return cb.like(root.join("author").get("firstname"), firstname);
}
}
}
public Specification<Book> hasGenre(final Genre genre) {
return new Specification<Book>() {
public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
return cb.equal(root.get( "genre"), genre);
}
}
}
}
Admittedly this is not the most beautiful piece of code to be written (it will hopefully become a lot better with Java 8's Single Abstract Method (SAM) feature). On the positive side we gain the possibility to execute specifications right on the repository:
bookRepository.readAll(hasAuthorWithFirstnameLike("Oliv*"));
Okay, that's pretty much what we could have achieved with a declared query, right? The power of specifications really shines when combining them into new specifications. Hades provides a Specifications helper class that allows on-the-fly composition:
bookRepository.readAll(where(hasAuthorWithFirstnameLike( "Oliv*").or(hasGenre(Genres.IT)));
This way, extending your repository becomes just a matter of adding new specifications. With a hand full of specs you get a quite flexible DSL-like API to query your repository without polluting the repository with query methods for every exotic use case. A more detailed introduction can be found at in the documentation.
Another part of the 2.0 release is an extensions module that seamlessly integrates Hades with upper layer technologies of your application like Spring MVC. It provides a PropertyEditor and Spring 3.0 Converter that allows to transparently bind entities to Spring MVC controller methods by their id as well as an MVC extension that dynamically extracts pagination information from an HTTP request. So a controller displaying a page of users could look something like this:
@Controller
class UserController {
@Autowired
UserRepository userRepository;
@RequestMapping("/users")
public void showUsers(Pageable pageable, Model model) {
model.addAttribute("users", userRepository.readAll(pageable));
}
@RequestMapping("/users/{id}")
public String showUser(@PathVariable("id") User user, Model model) {
model.addAttribute("user", user);
return"user";
}
}
As you can see for the showUsers(…) method there's no need to parse the HttpServletRequest for pagination information yourself. Note, that in showUser(…) the method parameter bound to the id path variable is already the entity. As the configuration of Spring MVC infrastructure goes beyond the scope of this article feel free to checkout the reference documentation chapter on the extensions module provides configuration examples to ease the setup.
Looking forward, beyond the 2.1.x line, Hades will become part of the Spring Data project where it's core will serve as a base for repository implementations for other datastores as well. Spring Data is a SpringSource project that aims to provide idiomatic Spring support for the varieties of emerging, specialized datastores, including NoSQL database.
Hades hugely eases implementing data access layers with JPA. You get sophisticated CRUD operations, execution of queries as well as specifications for free. It can be used standalone but integrates nicely with Spring as well. Beyond that, there's a Spring IDE/STS Eclipse plugin as well as a Spring Roo add-on to easily create repositories with Roo. For more information see the project website.
Oliver Gierke is Senior Consultant at SpringSource, a division of VMware and the project lead of the Hades open source project. He started the project at his former company Synyx about two years ago.
While you say it is "done right", perhaps fix your manual which has @Entity
@NamedQuery(name = "User.findByEmailAddress",
query = "FROM User u WHERE u.emailAddress = ?1")
where the query is invalid JPQL. According to the JPA2 spec BNFselect_statement :: = select_clause from_clause
[where_clause] [groupby_clause]
[having_clause] [orderby_clause]
so having a select clause is not "optional" (maybe in HQL, but that is not what you are presenting).
Presumably this would also work in other JPA providers such as DataNucleus ? i.e the JPA persistence solution being used in VMforce (being worked by the same company IIRC).
Regards
--Andy (DataNucleus)
Hi Andy,
thanks for the detailled look you took. I'll fix the documentation glitch ASAP.
As Hades is build on top of JPA I expect DataNucleus to work out of the box. It should just be a matter of setting up the EntityManagerFactory correctly. The move to Spring Data has just been started, which means that there hasn't been a deep involvement of SpringSource until now. This is the reason why the vmforce team is not involved that much yet. We will have a MongoDB specific release of the Hades concepts in the near future followed by the JPA port right after that.
Cheers,
Ollie
Really interesting.
Khosro.
Hades caught my eye before, but ultimate typesafe querying tool is still Querydsl
source.mysema.com/static/querydsl/2.0.6/referen...
Hades has an interesting approach, but I believe that the syntactic overhead for specifications is too high. The Querydsl equivalents would be
//has author with firstName like
List<Book> books = query.from(book).where(book.author.firstName.like(firstName));
// has genre
List<Book> books = query.from(book).where(book.genre.eq(genre));
Integrating Hades with Querydsl might be a win-win. Contact us if you are interested.
Br,
Timo Westkämper.</book></book>
Querydsl looks really cool. A lot cleaner than the JPA criteria API. While it's probably a bit late for Hades we should definitely hook up to do something for the Spring Data JPA project. I've added you on Skype, so feel free to ping me ;).
Cheers,
Ollie
When VMware get around to providing Spring Data for JDO too then it will, automatically, gain access to JDO Typesafe queries, something directly related to QueryDSL ;-)
Michael Stal discusses system architecture quality, how to avoid architectural erosion, how to deal with refactoring, and design principles for architecture evolution.
Every developer has had to integrate with another system, API or component. Tis article provides strategies to handle the change and for he separating system boundaries.
Alex Russell talks about the shortcomings of the web platform and how it is evolving in order to adress them. He also explains about how browsers are improving and shares his vision on things to come.
Jeff Lindsay discusses creating distributed and concurrent systems using ZeroMQ – a lightweight message queue-, and gevent – a coroutine-based networking library.
Brian Ketelsen introduces Skynet, a platform for polyglot, distributed and composable services that communicate with each other over RPC/JSON.
Carin Meier tells the story of Alice discovering Monads, meeting three types of monads – Identity, Maybe, State-, and learning how to implement them in Clojure.
The need for agile, queryable, reliable, scalable storage without the pain of SQL schema migration is real. This article uses MongoDB to introduce NoSQL concepts to Java, PHP, and Python developers.
Jérôme Giraud introduces Wink Toolkit, an open source mobile JavaScript framework for HTML5 web or hybrid apps, showing widgets and interactions.
7 comments
Watch Thread Reply