It sounds like you're describing the onion architecture, a form of n-tier architecture -- which is just a fancy way of saying it has components broken out into layers.
The layer you're focusing on is the Infrastructure layer. Data is the most common component of infrastructure. But other functions can be contained in separate libraries in the same layer.
Architecture is a subjective thing. The best I can do is offer you how I would set up the project.
If you want to be really explicit about your layers, you can use solution folders to separate things out.
Notice I didn't include the solution folder in the namespace -- it's Whatever.Web
, not Whatever.Client.Web
. That's another subjective call, but I've found it cleaner this way. Solution folders aren't mandated to be part of the namespace like project folders are.
And in the end, once I had an intuition for what concerns belong in which layer, I found I didn't even really need the solution folders:
Just by glancing at that, it's clear to me that the shared models are in the Core, the client is the Web, and everything else is there to support as infrastructure. But if I started getting many more projects in each layer, then I could switch back to organizing with solution folders.
For extra credit, I might mention that personally my Core/Domain layer would have interfaces for the Infrastructure services:
And the infrastructure library would then implement that interface, so you can always 'swap out' the dependency, to whatever other library implementation.
The green components represent doubts / confusion. Those with "???", are data types that I do not know. What types of data should I put here? Do I need a translator for this (to exchange the correct type)?
This is a quite a matter of taste, personaly i don't like using DTO, because they mainly duplicate business classes make writing adapter, and mess a lot with features like lazy-loading. Furthermore, every time i need to add a field, i need to add it everywhere and retest the whole thing.
So what i did is having only Business Model and i put every annotation i needed (jpa/jackson) on it.
YES this bind my business model to jpa/jackson, as my application rely heavily on Spring, but well decoupling all of that will add quite a lot of work for something that just won't change. I may add later if i need something else (XML serialization) either others annotation or finaly a DTO layer just for this. This will depends of the complexity of the thing.
Is the other type of written data ("DOMAIN MODEL ENTITY" - this is a JPA entity, @Entity) correct? I believe a DAO layer should only be concerned with these types of objects, making it completely independent to care.
As said before, if you want to use the full power of JPA, don't. Here is question of mine on stackoverflow which i was told the same thing, because abstracting JPA leads to unnecessary complex and inefficient code : https://stackoverflow.com/questions/37811139/good-usage-of-managed-entities-proxies-with-orm
I know a DAO type should only be concerned with a single entity, so the query parameters are always their fields / attributes / properties. However, what happens when I have to search for an entity that I need a parameter present in one of it's relationships? For example, search for all users with purchases made last month that had a value greater than X? In this case, I need the details found in the Purchase entity. Do I put this in DAO? And if I have to put it in a service class, I have to set EntityManager inside service also, giving it one more responsibility, which may leave without purpose the DAO persistence layer?
Your DAO layer is by definition aware of the relationships of your model. So of course he can query on subfields and so on. Following what i've been told i considered my DAO layer to be the Entity Manager, so i only have a service layer this fit as long there is nothing too much specific about your DAO/Service.
Finally, is this architectural model wrong for what I want to do? Is there something that needs to be fixed?
As i said, i did some things differently however your model is good because :
- DAO only handle persistency and no business logic/transaction.
- Service handle business logic and transaction.
- Controller do not handle business logic and transaction.
You have the right bases.
Best Answer
I'd say that Fail-fast approach is also applicable in your situation. That is, you should handle the error as close to its source as you can. If you do this webservice call from the business layer and then want to save results of that call in the database, then you should handle error in the business layer. If it's done as a part of data access layer, handle it there.