I'm trying to find a nice and elegant way to query database content based on DDD "specifications".
In domain driven design, a specification is used to check if some object, also known as the candidate, is compliant to a (domain specific) requirement. For example, the specification 'IsTaskDone' goes like:
class IsTaskDone extends Specification<Task> {
boolean isSatisfiedBy(Task candidate) {
return candidate.isDone();
}
}
The above specification can be used for many purposes, e.g. it can be used to validate if a task has been completed, or to filter all completed tasks from a collection. However, I want to re-use this, nice, domain related specification to query on the database.
Of course, the easiest solution would be to retrieve all entities of our desired type from the database, and filter that list in-memory by looping and removing non-matching entities. But clearly that would not be optimal for performance, especially when the entity count in our db increases.
Proposal
So my idea is to create a 'ConversionManager' that translates my specification into a persistence technique specific criteria, think of the JPA predicate class. The services looks as follows:
public interface JpaSpecificationConversionManager {
<T> Predicate getPredicateFor(Specification<T> specification, Root<T> root, CriteriaQuery<?> cq, CriteriaBuilder cb);
JpaSpecificationConversionManager registerConverter(JpaSpecificationConverter<?, ?> converter);
}
By using our manager, the users can register their own conversion logic, isolating the domain related specification from persistence specific logic. To minimize the configuration of our manager, I want to use annotations on my converter classes, allowing the manager to automatically register those converters.
JPA repository implementations could then use my manager, via dependency injection, to offer a find by specification method. Providing a find by specification should drastically reduce the number of methods on our repository interface.
In theory, this all sounds decent, but I feel like I'm missing something critical. What do you guys think of my proposal, does it comply to the DDD way of thinking? Or is there already a framework that does something identical to what I just described?
Hades is a Repository framework as a wrapper for JPA. It is DDD friendly. It supports DDD Specifications out of the box. I also suggest you look at this article from InfoQ.
I actually read that article, but hades specifications require you to include JPA logic in your
specification. Specifications are domain specific and should be kept separate from any type of
persistence logic.
What about JPA annotations man...? Do you think your domain objects should be kept seperate from JPA annotations ?
I think the solution provided by Hades (which is now known as "spring-data-jpa") is a better solution than the one provided in Evans book : Eric Evans shows an example where a "Specification" calls a "Repository" which itself calls the "Specification" ! I really wondered how client code would only go through the specification, and not use the repository directly. The solution provided by Hades/Spring-data-jpa is a good one to me, it's ok to put JPA in domain logic, because JPA is designed to go in the domain layer.
EDIT : I forgot to mention Eric Evans implements a "double dispatch", it's not a silly circular dependecy between specification and repository, but as mentioned above, it doesn't prevent any developper to bypass the specification implementation.
In the .NET world, that is covered by LINQ. I know of no Java equivalent.
Related
I work on a big project using Hibernate, Spring and ZK frameworks, and I want to upgrade to Hibernate 5. There are several ZK tables with DB-layer paging/filtering/sorting in the GUI. For these tables we use the approach described in https://www.zkoss.org/wiki/Small_Talks/2009/May/Paging_Sorting_with_a_filter_object, that is, the model of the table has a SearchObject (wrapper of the query), a SearchResult (wrapper of the resultset) and a reference to the DAO. By paging/sorting/filtering the SearchObject will be changed, and then processed by the DAO automatically.
The problem is that the hibernate-generic-dao project (https://code.google.com/archive/p/hibernate-generic-dao/) is dead and should be upgraded to Hibernate 5. I consider to upgrade it myself (or at least the search and search-hibernate modules), but I am interesting whether there is a similar living project. (Although it would be painful to use a different API in each cases.)
It sounds a bit similar to spring-data repositories which greatly reduce boiler plate code, and provide a common interface for regular CRUD/Paging/Sorting repository methods. The implementation is generated automatically based on naming-conventions and meta-data.
At the same time it is extensible down to native queries in case none of the naming conventions match.
Also the query by example functionality might be a candidate to replace your dynamic SearchObject.
Maybe that's something for you.
After reading some pages from DDD, I read about Repository pattern, then used it in an application successfully (I really liked it); then I noticed that EntityManager is generic-repository-like, but while I was reading about Repository I saw many examples on the web explaining how to impliment Repository pattern, and JPA was a simple Repository implementation between many implementations, like this website: http://www.lestard.eu/2015/generic_repository_part1/
The developer demonstrated in-memory implementations of Repository pattern, and in the second part : http://www.lestard.eu/2015/generic_repository_part2/, showed JPA implementation of repository pattern.
So here my question: while JPA is already like a generic repository, can we extend JPA to use in-memory, web services (e.g: REST CRUD) and entity persisting -- as JPA stands for Java PERSISITENCE API, (I wrote it in capital letters to show that it means a general persistence mechanism) -- as it seems that current JPA is tightly coupled with databases, but its name refer to a general use.
Technically it's possible but I would prefer not to do this and don't have any links to specific implementation standard (like Java JPA). I prefer to hide all of implementation details inside my Repository impl.
Moreover, I definitely don't like idea to put any persisting (like #Entity) or conversion (like #XmlRootElement from JAXB or #JsonProperty) annotations inside my domain objects.
The reason is the simple: if in the future you will change Java JPA to smth new like Java New JPA you'll have to change you domain objects for this too. But it contradicts whole DDD idea.
Is it discouraged to have "extra" functionality inside a hibernate javabean? For example, a "save", "publish", or even static "get by id" method? And other potential variables such as locks, bells and whistles?
If so, where are we supposed to put these extra features that are supposed to be in each object we are dealing with? If for example we created a wrapper class ArticleWrapper that includes the POJO Article as its own private member variable, which doesn't have a mapping to Hibernate, then it wouldn't work because Hibernate can only get a list of Articles, not a list of ArticleWrappers.
I guess the reasons for this are because they follow a specific well tested pattern for this, but that is not the only pattern to deal with database manipulation.
The one you describe sounds more like the Active Record Pattern Pattern.
Some frameworks implement Active Record and then their object models mix data and functionality together, pretty much like you describe. I have seen this pattern in Ruby on Rails Active Records and in Python's framework named Django.
In this pattern every domain object represents a row in the database and carries both data and behavior.
Martin Fowler in his book on Enterprise Application Architecture Patterns (and corresponding catalog page) mentions a few other well known ways to deal with your data source layer:
Table Data Gateways
Row Data Gateway
Data Mapper
Active Record
The book and the catalog delves into many other patterns for object-relational mapping.
Layered Design
In the classical way you describe with Hibernate, the entities are just placeholders for data, but contain no logic whatsoever. Under this pattern you would most likely have a data access layer or repository layer around your entities that deals with recovering entities from the underlying data source and updating them back.
This layer is the one that deals with CRUD operations.
interface ArticleRepository {
Article findById(Integer articleId);
List<Article> findByAuthor(Integer authorId);
Article save(Article article);
void delete(Integer articleId);
}
On top of this layer, you have a service layer which is the one that exposes the business logic to the users of your application.
interface ArticleService {
void publishArticle(String author, Date date, String title, String contents);
List<Article> getFeaturedArticles(Date date);
void unpublishArticle(Integer articleId);
}
On top of this layer, most likely you define some form of integration layer to expose this service layer to the application users in many different ways, like through RESTful or SOAP Web services, or RMI, EJBs or whatever other technology you know out there.
By not putting any kind of logic in your entities, they serve well their purpose of data carriers and can be reused in different service layers if necessary.
You may want to take a look at the framework like Spring Data that fosters this type of design. It makes it all more clear where every piece should go.
I guess writing code is not only about making it compiling and running. To make code clean and easy to maintain developers have come up with various design patterns such as DataAccessObject (or dao) for this particular situation. Following OO good practices will make developers' work more efficient, especially if they work on big projects, with time code that doesn't present decent level of cohesion and looks like a bucket of dirty laundry will become impossible to maintain. Remember - just because you can do something doesn't mean you should.
I'm hesitating between two designs of a database project using Hibernate.
Design #1.
(1) Create a general data provider interface, including a set of DAO interfaces and general data container classes. It hides the underneath implementation. A data provider implementation could access data in database, or an XML file, or a service, or something else. The user of a data provider does not to know about it.
(2) Create a database library with Hibernate. This library implements the data provider interface in (1).
The bad thing about Design #1 is that in order to hide the implementation details, I need to create two sets of data container classes. One in the general data provider interface - let's call them DPI-Objects, the other set is used in the database library, exclusively for entity/attribute mapping in Hibernate - let's call them H-Objects. In the DAO implementation, I need to read data from database to create H-Objects (via Hibernate) and then convert H-Objects into DPI-Objects.
Design #2.
Do not create a general data provider interface. Expose H-Objects directly to components that use the database lib. So the user of the database library needs to be aware of Hibernate.
I like design #1 more, but I don't want to create two sets of data container classes. Is that the right way to hide H-Objects and other Hibernate implementation details from the user who uses the database-based data provider?
Are there any drawbacks of Design #2? I will not implement other data provider in the new future, so should I just forget about the data provider interface and use Design #2?
What do you think about this? Thanks for your time!
Hibernate Domain objects are simple POJO so you won't have to create separate DPI-objects, H-Object themselves can be used directly. In DAO you can control whether they come from hibernate or anything else.
I highly recommend reading Chapter 4 "Hitting the database" of Spring in Action, 3rd edition, even if you aren't using Spring in your application. Although my second recommendation would be to use Spring :-)
The DAO pattern is a great way to keep database and ORM logic isolated in the DAO implementation, and you only need one set of entity objects. You can make that happen without Spring, it just takes more work managing your sessions and transactions.
If I understand your post, this is sort of a middle-ground between Design 1 and Design 2. The H-Objects (the entities that Hibernates loads and persists) don't need any Hibernate specific code in them at all. That makes them perfectly acceptable to be used as your DPI-Objects.
I've had arguments with folks in the past who complain that the use of JPA or Hibernate Annotations exposes Hibernate specifics through the DAO interface. I personally take a more pragmatic view, since annotations are just metadata, and don't directly affect the operation of your entity classes.
If you do feel that the annotations expose too much, then you can go old school and use Hibernate Mappings instead. Then your H-Objects are 100% Hibernate free :-)
I recommend design #2. Simply construct domain objects, and let hibernate look after them. Don't write separate classes that are persisted.
Hibernate tries to hide most of the persistence business from you. You may need to add a few small annotations to your entities to help it along. But certainly don't make separate classes.
You may need some very small DAO classes. For example, if you have a Person entity, it would be fairly common practice to have a PersonDAO object that saves a person. Having said that, the code inside the DAO will be very simple, so for a really small project, it may not be worth it. For a large project, it's probably worth keeping your persistence code separate from your business logic, in case you want to use a different persistence technology later.
I used to design my application around anemic domain model, so I had many repository object, which were injected to the big, fat, transaction-aware service layer. This pattern is called Transaction script. It's not considered a good practice since it leads to the procedural code, so I wanted to move forward to the domain driven design.
After reading couple of articles on the web, listening to the Chris Richardson's talk on Parleys and reading DDD chapters of the POJOs in Action, I think I got the big picture.
Problem is, that I don't know, how to organize transactions in my application. Chis Richardson in his book states:
The presentation tier handles HTTP requests from the user’s browser by calling
the domain model either directly or indirectly via a façade, which as I
described in the previous chapter is either a POJO or an EJB.
Good so far, but Srini Penchikala on InfoQ article states:
Some developers prefer managing the transactions in the DAO classes which is a poor design. This results in too fine-grained transaction control which doesn't give the flexibility of managing the use cases where the transactions span multiple domain objects. Service classes should handle transactions; this way even if the transaction spans multiple domain objects, the service class can manage the transaction since in most of the use cases the Service class handles the control flow.
Ok, so if I understand this correctly, repository classes should not be transactional, service layer (which is now much thinner) is transactional (as it used to be in Transaction script pattern). But what if domain objects are called by presentation layer directly? Does it mean, that my domain object should have transactional behavior? And how to implement it in Spring or EJB environment?
This seems kind of weird to me, so I'd be happy if somebody would clarify that. Thank you.
My personal take on applying DDD with Spring and Hibernate, so far, is to have a stateless transactional service layer and access the domain objects through that. So the way I'm doing it the domain model does not know about transactions at all, that is handled entirely by the services.
There is an example application you might find helpful to take a look at. It looks like Eric Evans was involved in creating it.
See this extremely useful blog-post. It explains how to achieve smooth DDD while not loosing Spring's and JPA's capabilities. It is centered around the #Configurable annotation.
My opinion on these matters is a bit non-popular. Anemic data model is actually not wrong. Instead of having one object with data+operations, you have two objects - one with data and one with operations. You can view them as one object - i.e. satisfying DDD, but for the sake of easier use they are physically separated. Logically they are the same.
Yes, this breaks encapsulation, but it doesn't make you use some 'magic' (aop + java agent) in order to achieve your goals.
As for the transactions - there is something called Transaction propagation. Spring supports it with #Transactional(propagation=Propagation.REQUIRED).
See this, point 9.5.7. In case you want your transactions to span multiple methods (of multiple objects) you can change the propagation attribute accordingly.
You can also use #Transactional in your service layer, where appropriate, but this might introduce a lot of boilerplace service-classes in cases when you want to use simple, single-step operations like "save".
I think one easy way to get started with DDD and Spring and have good examples of how to deal with transactions is by looking at one of the sample apps that get shipped with Spring Roo. Roo churns out code that follows the DDD principles. It relies heavily on AspectJ. I suspect it was implemented building on the ideas put forward (back in 2006) by one of SpringSource's heavyweights, Ramnivas Laddad, in this talk.
Unnfortunately I haven't make myself familiar with Spring but I will give feedback about your DDD understanding. Reading your description of transaction it is obvious that you haven't understand DDD especially Aggregate, Aggregate Root, and Repository concept.
In DDD transaction can't span across aggregates so one Aggregate will always have one transaction.