I'm starting with DDD and you can image my brain is boiling.
My question is related to my domain objects (entities, VO, ...) which represents my domain concepts/logic and how to persist/retrieve them.
The blue book says the repository is a way to represent collections on domain objects and is responsible to communicate with the infrastructure layer. I read also at some post the infrastructura layer is where you must use hibernate, JPA or whatever.
Then I see this Spring-data-jpa example http://spring.io/guides/gs/accessing-data-jpa/ and I become crazy.
The slogan say Spring-data-jpa is to create repositories easily and the previous samples seems to merge JPA annotations into a domain object (the customer).
Is the sample right? or Am I right?
If I'm right and the domain and infrastructure must be separated, that means to store a customer I must have:
a Customer class in my domain layer (that represents a customer and has all the logic operations)
a CustomerRepository un my domain layer (that retrieves or stores customers from infrastructure layer)
a Customer class in infrastructure layer, probably annotated with #Entity
Some CustomerReposityJPA that know how to store/retrieve customers from database.
Thanks for any clarification.
In DDD, a repository is an object that participates in the domain but really abstracts away some backing store.
If you annotate your domain objects with JPA annotations, your persistence mechanism has bled into your domain. You have tied your domain structure to your persistence structure which is not ideal.
Your JpaCustomerRepository (implements ICustomerRepository) could map the unannotated domain classes (Customer) into an annotated JPA representation - JPA customer. This keeps the annotations out of your domain classes, so is cleaner. It allows you to vary the JPA persistence structure independently of your domain structure. The cost for this benefit is the complexity of the mapping code.
interface ICustomerRepository {}
class JpaCustomerRepository implements ICustomerRepository {
void save(Customer customer) {
JpaCustomer jpaCustomer = map(customer);
save(jpaCustomer);
}
}
class Customer {}
class JpaCustomer {}
I can't see the link you've posted and I have never apply Domain driven design to the Java world.
Theoretically what you need is Customer aggregate in the domain layer. In your domain layer there's space for the repository (intended as interface), so you'll have ICustomerRepository.
Probably you will have the four prototype for the common persistence issues:
GetById(CustomerId id);
Add(Customer c);
Delete(Customer c);
Update(Customer c);
In the infrastructure layer you will provide the body (for instance CustomerRepository), in the infrastracture layer you can couple yourself with something technological (for example JPA).
Domain layer MUST be completly unaware of technology used in the infrastructure. Doing so you could change completly the implementation details having (almost) no troubles.
Related
I have three tables on a database, and one old and good query that joins the interesting columns for the usecase on a DTO object after use a RowMapper. Classical Java approach.
But I am wondering, how can I convert this into a DDD implementation? How can I use entities for solve the problem without having 3 separated queries to create the models with it's fields, and then create a DTO just for create the object with the desired columns?
What I am missing? Or should be better the already implemented way?
You cannot convert that model to DDD.
DDD is about creating a business model in a separate layer: the domain layer. The purpose of this layer is to verify that any state-changing operations does not violate your business rules. How you model your domain entities must be driven by the use case you are handling, not how the data is stored: the domain layer is said to be persistence agnostic. It doesn't matter whether the data is stored in one or multiple stores, RDBMS, nosql, files, etc ... that's ther purpose of the infrastructure layer.
Domain object are read by a class called a repository. The repository behaves like an in memory collection of domain object, but actually re-hydrates objects from the persistence store(s). It operates as a mediator between your persistence model and your domain model. Since models may differ, the repository can flatten relations, join data from different sources, and ignore some columns if needed.
When querying your state, you don't need to use the domain layer at all. The purpose of that layer is to validate state-changing operation, business-wise, but this is unnecessary when querying the state. In that situation, you can implement classes, called mediators, that will query your database and produce presentation layer DTO. Like the repositories, mediators are adapters between your persistence model and your presentation model. It can join data from multiple persistence stores, flatten relations, and ignore columns as well.
Whether to use an ORM, or not, for accessing the database, is an implementation detail of your infrastructure layer. It has nothing to do with domain modeling, which is about your use cases and business rules validation.
According to Uncle Bob, the entity layer should know nothing about the database.
What about the JPA annotations then? Don't they violate the architecture proposed by the author? If they do, how to use the entities with JPA?
In a non-ORM world, a clean architecture would (or could) involve having DAO interfaces, with DAO implementations knowing how to retrieve the data from a database (or any other source), and convert and return it as a domain object. An upper layer would then use the DAOs (through the interfaces) to retrieve those objects.
This would allow you to for example create different DAO implementations for different databases, and you could change databases without bothering the rest of the software.
In a JPA/ORM world you can bypass a lot of that if you choose. You can use entity classes as domain objects, create the entity classes in a database agnostic way (i.e. not using any database specific NativeQueries for example). Now that your entities are database agnostic, you can just use NamedQueries in your service layer instead of creating DAOs.
In the end you need to have some layer which knows about the database, but in JPA's case it doesn't even hold true. Your entities are Java objects and it's the JPA implementation layer that is responsible for converting them to and from the database.
In conclusion: there are very few universal truths in software development and you can talk to a dozen uncles and hear a dozen versions of essentially the same "story".
I know there are many questions about my problem and I've read a lot, but I'm still feeling little bit stupid, because I still haven't got it. So I'm trying it on my particular problem.
I'm implementing the school work. It should be a part of the information system, which has to be layered. We have to write it in Java or C# (I've chosen Java). We have to use two different data sources and two different views, in my case, oracle db and xml as data source and Java Swing and JSF as views.
According to the book "Patterns of Enterprise Application Architecture by Martin Fowler" there are three principal layers:
Data source layer: I've generated entities using Hibernate ORM, I've created data access objects to implement simplier "interfaces" to getting the data.
Domain layer: ...
Presentation layer: I've created the Swing GUI and some .xhtml pages with MVC logic
If there wouldn't be any "calculations" in the system, but only simple achieving and returning data, I'm done, everything is ok. But I'm, for example, implementing the system, which should manage the competitions of the sport dancing, and during the competition I need to generate sets of couples for every round, after the competition I need to calculate points of every dancer, increment points if necessary and so on.
I know, that it is the responsibility of the Domain layer (business logic), but where in my code with? What names for these objects should I choose and where to put them in my code structure?
My structure:
hibernate.cfg.xml (configuration of hibernate)
hibernate.reveng.xml (reverse engineering file of hibernate)
isets.dao (package)
isets.dao.hibernate (package)
HbmCompetitionDao.java (data access object of Competition entity)
...
isets.dao.xml (package)
... (data access objects of another entities, which are stored as XML)
isets.entities (package)
Competition.hbm.xml (generated entities)
Competition.java
...
isets.util (package)
HibernateUtil.java (file to get session factory object)
Where should I put my business logic and what should be the names of these classes?
Thank you very much for your help. Bye :-)
Usually domain layer means "entities" (models for domain) and domain services.
Entities hold all business logic related to them. Validations (checking that they're in correct state) and calculations are usually put in the property setters/getters, while operations for transforming data are exposed via public methods.
Domain services are classes that operate with multiple entities and do some calculations and/or transformations between entities.
A few things to consider. In order for this design to work properly (so it is testable, decoupled etc), dependency injection (DI) must be used. Domain should never be bothered by getting or saving data etc. It should be clearly decoupled and all its dependencies should be known upfront.
If it is a simple application it may be wise to combine domain layer and data access layer, so objects that are created from ORM are already entities. Just add domain services (if you need them). Use then the same entities on presentation as well (as model for MVC). This will decrease the need for mappers to map between ORM made objects (lets call them dbos), entities and possible models needed for presentation. Of-course if you need different objects for each layer, by all means create them. Just don't over complicate if it is not needed.
One of the possibilities is to structure you application as follows:
1) #Entity annotated POJO represent your data layer representing tables, relationships between them, etc using JPA
2) Stateless session beans implementing Session Facade desing pattern wrap your container managed CRUD operations. There are typically one facade per entity, they usually look like this:
#Stateless
public class FooFacade extends AbstractFacade<Foo>{
#PersistenceContext
EntityManager em;
public EntityManager getEM() {
return em;
}
public void save (Foo entity) {
getEM.persiste(Foo.class, entity);
}
public void reload (Foo entity) {
getEM.refresh(entity);
}
//other similar stuff
}
AbstractFacade is an abstract class that provides genetic find and other operations that look identical in all facade classes (to avoid duplicate code). This e-commerce sample application can be used as a great example of this strategy. The classes are usually named as EntityName + Facade.
3) Stateless session beans that realise your business logic (calculations for competitions in your case or adding goods into basket, implementing checkout, etc. for ecommerce app). Usually they talk to data layer via *Facade EJBs mentioned in part 2 above. This part of the aforementioned tutorial realises these EJBs.
4) Servlets to which your UI layer will refer their request. Servlets will utilize EJBs from part 3 to serve the requests.
5) UI layer - JavaFX, Swing, JSF, JSP, Apache Wicket framework - add anything you like.
Such a structure gives you both flexibility and scalability. Centring your business logic in stateless beans means you can scale well because they are pooled and every instance in the pool can equally be used when you application (e.g. servlet) needs talk to an instance of such a bean.
I strongly recommend you to thoroghly read through the ecommerce tutorial on Netbean's website to see the concrete implementation of this scheme. Here is the download link for the source code of the application, AffableBean ecommerce system, built through the tutorial.
According to many programers, DAO layer can be bypassed when using JPA.
While using DDD approach, domain layer composes of infrastructure region (containing external resources like repositories implementations) and domain region (with entities, needed value objects and repositories interfaces and services etc...).
Thus, if DOA layer is skipped, should the infrastructure region be part of domain layer within a package called 'infrastructure' for instance ?
If infrastructure part should be moved in a separated layer (separated project to get things cleaner), are circular dependencies acceptable between domain layer and infrastrure layer? Indeed, entities and interface repositories must be shared.
Otherwise, should I separate entities and repositories interfaces from Domain layer in order to be considered as an independent thing shared by domain and infrastructure ?
What is the good practice ?
In DDD, the data access objects (DAOs) are Repositories. There's no "DAO layer", persistence is part of the Infrastructure layer.
As you mentioned, the contracts (interfaces) of Repositories are defined in the Domain layer while their concrete implementation resides in the Infrastructure layer.
There's no need for the Domain layer to reference the Infrastructure since entities are supposed to be pure domain objects, unaware of how they are persisted, transferred to other systems, and so on.
"In other words, each of the layers uses an abstract interface that
represents it's infrastructure needs. It does not know what
infrastructure it will be using. It simply states it's needs through
an abstract interface and expects the infrastructure to implement that
interface and supply the required functionality."
http://www.artima.com/weblogs/viewpost.jsp?thread=35139
A DAO layer and a infrastructure region/domain region are not the same things. DAO layers are used when implementing the infrastructure/domain regions.
Your programmers are correct, JPA is the DAO layer. You still need the infrastructure region and domain regions. They'll just be smaller/differnet then if you had to implement a DAO layer within these two regions.
I need some advice on designing an "Integration Tier" of an N-Tiered system in Java. This tier is responsible for persisting and retrieving data for the "Business Tier" (located on a separate server). I'm new to J2EE and I've read a few books and blogs. The alphabet soup of technology acronyms is confusing me so I have a handful of questions.
First, what I have so far: I'm using JPA (via Hibernate) for persisting and retrieving data to a database. I made my data access objects EJBs and plan on deploying to an application server (JBoss) which makes transactions easier (they're at the function level of my DAOs) and I don't have to worry about getting a handle to an EntityManager (dependency injection). Here's an example of what things look like:
#Entity
class A{
#Id
Long id;
#OneToMany
List<B> setOfBs = new ArrayList<B>;
}
#Entity
class B{
#Id
Long id;
}
#Remote
public interface ADAO{
public A getAById(Long id);
}
#Stateless
class ADAOImpl implements ADAO{
#PersistenceContext
EntityManager em;
public A getAById(Long id){ ... }
}
My question: How should the Business Tier exchange data with the Integration Tier. I've read up on RESTful services, and they seem simple enough. My concern is performance when the frequency of gets and sets increases (HTTP communication doesn't seem particularly fast). Another option is RMI. My DAOs are already EJBs. Could I just have the Business Tier access them directly (via JNDI)? If so, what happens if the #OneToMany link in the example above are lazily loaded?
For example if the Business Tier does something like the following:
Context context = new InitialContext(propertiesForIntegrationTierLookup);
ADAOImpl aDao = (ADAOImpl) context.lookup("something");
A myA = aDao.getAById(0);
int numberOfBs = myA.setOfBs.size();
If the setOfBs list is loaded lazily, when the Business Tier (on a separate server) accesses the list, is the size correct? Does the list somehow get loaded correctly through the magic of EJBs? If not (which I expect), what's the solution?
Sorry for the long post. Like I said I'm new to J2EE and I've read enough to get the general idea, but I need help on fitting the pieces together.
When you call size() on lazy collection, it gets initialized, so you'll always get correct size no matter which interface you're using - Remote or Local.
Another situation is when you're trying to use JPA classes as data transfer objects (DTO) and request them via Remote interface. I don't remember any lazy initialization issues here, cause prior to transmission all objects have to be serialized (with lazy collections initialized) on server side. As a result, the whole object graph is passed over network, which might cause serious cpu and network overheads. In addition, for deserialization to be possible, you will have to share JPA classes with remote app. And that's where and how 'EJB magic' ends :)
So, once remote calls are possible, I'd suggest to start thinking of data transfer strategy and non-JPA data transfer objects as additional data layer. In my case, I've annotated DTO classes for XML binding (JAXB) and reused them in web-services.
Short answer: If you are using an "Integration Layer" approach, the things you should be integrating should be loosely coupled services, following SOA principles.
This means you should not be allowing remote calls to methods on entities that could be making calls to the framework under the lid on another server. If you do this, you are really building a tightly coupled distributed application and you will have to worry about the lazy loading problems and the scope of the persistence context. If you want that, you might like to consider extended persistence contexts http://docs.jboss.org/ejb3/docs/tutorial/extended_pc/extended.html.
You have talked about a "business tier", but JPA does not provide a business tier. It provides entities and allows CRUD operations, but these are typically not business operations. a "RegisterUser" operation is not simply a question of persisting a "User" entity. Your DAO layer may offer a higher level of operation, but DAOs are typically used to put a thin layer over the database, but it is still very data centric.
A better approach is to define business service type operations and make those the services that you expose. You might want another layer on top of your DAO or you might want to have one layer (convert your DAO layer).
You business layer should call flush and handle any JPA exceptions and hide all of that from the caller.
The issue of how to transfer your data remains. In many cases the parameters of your business service requests will be similar to your JPA entities, but I think you will notice that often there are sufficient differences that you want to define new DTOs. For example, a "RegisterUser" business operation might update both the "User" and "EmailAddresses" table. The User table might include a "createdDate" property which is not part of the "RegisterUser" operation, but is set to the current date.
For creating DTOs, you might like to look at Project Lombok.
To copy the DTO to the Entity, you can use Apache Commons BeanUtils (e.g., PropertyUtils.copyProperties) to do a lot of the leg work, which works if the property names are the same.
Personally, I don't see the point in XML in this case, unless you want to totally decouple your implementations.