When people working on a multitiered application get asked to draw their architecture, often something like this emerges:
UI -> Domain -> Persistence
This is all nice until you start to wonder what the arrows actually mean.
Is it data flow? Probably not, except when you are working on an application that takes input, stores it somewhere but never retrieves it back.
Is it dependencies? Hopefully not, or everything depends on your persistence layer. You really don’t want that.
It might be calls: The UI gets triggered by the user in some way (say hitting a save button). The UI calls the domain logic tod do its stuff which in tern calls the persistence layer to store the stuff, load some other stuff and this gets returned up the stack until it gets displayed in the UI.
While this is valid information to convey it often isn’t what people think they are conveying. Instead they claim this are dependencies. And maybe they are. But if you want to document your dependencies your diagram should look like this most of the time:
UI -> Domain <- Persistence
The Domain should be the center of your architecture and there for at the center of your dependencies. Everything else, i.e. all the interfaces (in the general sense) should depend on the domain. Not the other way round.
You achieve that by defining interfaces (in the Java sense) inside your domain which then get implemented or used by the UI or the Persistence layer.
If you want you can have those interfaces in seperate layers you can:
UI -> Presentation Interface Persistence Interface <- Persistence Implementation
Just take care that the design of the Presentation Interface and the Persistence Interface is driven by the domain, not by some UI or Persistence technology.
As a side note: If you are using Hibernate / JPA with annotation based mapping you are either violating this design principle, because your persistence technology (JPA) bleeds into the domain logic (annotations on the domain classes) or you have to copy all the data from your entity classes into your domain classes which really is cumbersome and reintroduces the kind of boilerplate code we wanted to get rid of with tools like Hibernate in the first place.
How to resolve that issue is a topic for another day.