Business objects (DTO) in Spring Data JPA - spring

By default Spring Data Repositories process database Entities. Please, suggest the standard approach of getting same functionality with Spring Data framework, which allows you operating on your Business Domain Objects (DTO) instead of Entities, and encapsulates all DTO to/from Entity mappings.
My current obvious options are:
Additional "proxy-wrapper" where all methods have same names as in Spring Repository but accept and return DTO types and encapsulate conversions(mappings).
Some clever implementation of previous option using AOP with less boilerplate code.
Both options seem pretty awkward to me for such a standard task. So, I assume I am jut missing something here.

Related

Only simple models in Spring Data JDBC

Im not sure if i can use Spring Data JDBC also for complex models. My doubts arise especially cause in the Spring Data JDBC (3.0) documentation is written:
"There is a simple model of how to map entities to tables. It probably only works for rather simple cases. If you do not like that, you should code your own strategy. Spring Data JDBC offers only very limited support for customizing the strategy with annotations." https://docs.spring.io/spring-data/jdbc/docs/3.0.0/reference/html/#jdbc.why
I was expecting Spring Data JDBC is also working for more complex cases.
The limitations that rise from this simple model affect mostly legacy projects where you have a database that you maybe can't even change.
Spring Data JDBC is not intended to map an arbitrary database model to an arbitrary Java domain model, but to use a Domain Driven Design approach and construct the database accordingly.
But even in the cases where you hit the limitations of Spring Data JDBC you can always fall back on Springs JdbcTemplate without any conflict with the rest of your model which gets persisted by Spring Data JDBC.
The same is not true for JPA. Of course you can use JdbcTemplate with JPA as well, but you now have to very different approaches to persistence in your application which can and will interact in interesting ways due to JPA caching and dirty checking.
I therefore think Spring Data JDBC is an excellent choice for large application and complex models.
It's limitations will push you in the direction of better defined smaller modules and less complex models.

DDD - Maintaining separate Domain Classes and Entity Classes in Spring Data

I'm working on a project Spring Boot project where there are two separate packages named domain and persistence.
The domain package primarily contains the Domain Classes (designed based on the business requirements) whereas the persistence package contains the repository interfaces defined by extending the repositories provided by Spring Data.
I have used Spring Data JPA annotations inside the domain classes and those classes are directly used when defining the repository interfaces as well. Everything works well here.
But the issues I have is that one could argue that domain classes do not need to know about the persistence implementation and domain classes should kept clean without polluting with Spring Data JPA annotation. This makes me this that I should maybe use a different set of classes (let's say Entity classes with more or less attributes) to implement the persistence so that I can keep the domain classes clean. But if I do this;
Spring Data repositories are going to work with these Entity Classes and I will not be able to use the interface based repositories out of the box since I will always have to map the Entity objects returned by repositories to Domain Classes.
I believe that at some point, I will introduce DTOs as well and when I reach this level, there will be too many mappings (Entity Classes to Domain Classes and then Domain Classes to DTOs). I personally think this mapping will be an overhead in the long run.
Summary -
Should I maintain Domain Model Classes and Entity Classes separately or should I just use Domain Model Classes along with Spring Data JPA annotations and KISS?
I think it is a mistake to separate the repository interfaces from the domain classes. Repositories are a part of the domain. Their implementation isn't, but you are not dealing with the implementation since that is provided by Spring Data (and JPA).
If your domain classes and your entity classes should be separate things depends on if they have different needs.
You might encounter scenarios where you need to model entity classes to accommodate the limitations of JPA or whatever persistence technology you use and you don't want to leak that into you domain.
But until you encounter that I don't see the need to separate them.
If you are concerned about annotations on your entities, it might help to realise that annotations are an extremely weak dependency. You can use your entities without the annotations even on the class path. So from a purist point of view they are a smell, but in reality I still have to find a situation where they are problematic.
If you really want to get rid of them you might want to look into jMolecules, which offer technology agnostic annotations for DDD concepts that then get translated into JPA annotations or whatever you want to use.

Two approaches to implementing REST API on Spring

I do REST API on Spring. Took a course in Spring Data Hibernate and found that it made the REST API the most time-consuming way.
When I added a new entity to the domain, I went through the following chain of objects:
Entity - domain object
DTO - for transmitting/receiving an object to/from a client
Mapper - to convert between Entity and DTO
Repository - for interacting with the database
RestController - for processing API requests
Service - service class for the object
The approximate chain of my actions was as follows:
RestController processes requests - receives DTO from the client (in case of creation of a new object)
Mapper in controller converts DTO to Entity
Service is called
Service accesses the Repository
Repository returns the result of execution (created by Entity)
Service returns Entity is created in RestController
RestController returns to the client an object of type ResponseEntity, where I put the body and response code.
As you can see a large chain of actions and a large number of objects.
But then I found out that if you use Spring Data REST, all this doesn't need all the API supplied by Spring from the box. In general, you only need to create an Entity and Repository.
It turns out that for typical CRUD-type operations, I wrote a lot of controllers and their methods in vain.
Questions:
When should I use RestConroller, and when is Spring Data REST?
Is it possible to combine two approaches for one Entity? It turns out that I was wasting my time writing for simple operations like creating, getting, saving, deleting controllers, it can be moved to Spring Data REST.
Will I be able to implement some of the actions that I did in Spring Data Rest in RestConroller? Such as:
Return an entity property value as id instead of object? I mean I have properties for entities that are entities themselves, for these fields I sometimes need to return their ID instead of the whole entity.
Is there any way to control error handling? In RestController I have implemented the ResponseEntityExceptionHandler extension class and all errors wherever they occur in my RestController are handled in the same way in one place and I always know that all errors will return approximately the same response structure.
Data validation will have to be hinged on the fact that it used to be validated on DTOs received from the client. Are there any nuances waiting for me in this regard?
I'm a little stumped on how to move forward. Give me your recommendations and thoughts on this. Push forward on what to use and how.
What Spring Data REST can do for you is scaffolding of the plain repository to rest service. It is much faster, and in theory it should be flexible, but in practice it is hard to achieve something more than REST access to your repositories.
In production I've used Spring Data REST as a wrapper of the database - in a service/microservice architecture model you just wrap-up sometimes the core DB into such layer in order to achieve DB-agnostic Application. Then the services will apply the business logic on top of this wrapper and will provide API for the front-end.
On the other hand Spring Data Rest(SDR) is not suitable if you plan to use only these generated endpoints, because you need to customize the logic for fetching data and data manipulation into Repoitories/Services. You can combine both and use SDR for the "simple" entities, where you need only the basic CRUD over them, and for the complex entities to go with the standard approach, where you decouple the entity from the endopint and apply your custom business logic into the services. The downside of mixing up both strategies is that your app will be not consistent, and some "things" will happen out-of-the-box, which is very confusing for a new developer on this project.
It loooks wasted time and efforts to write these classes yourself, but it only because your app doesn' have a complex database and/or business logic yet.
In short - the "standard" way provides much bigger flexibility at the price of writing repetetive code in the beginning.
You have much more control building the full stack on your own, you are using DTO's instead of returning the entity objects, you can combine repositories in your services and you can put your business logic on the service layer. If you are not doing anything of the above (and you don't expect to in the near future) there is no need for writing all that boilerplate yet over again, and that's when Spring Data REST comes into play.
This is an interesting question.
Spring Data Rest provides abstraction and takes a most of the implementation in its hand. This is helpful for small applications where the business logic resides at the repository layer. I would choose this for applications with simple straight forward business logic.
However if I need fine grained control (eg: transaction, AOP, unit testing, complex business decisions etc. ) at each of the layers as you mentioned which is most often needed for large scale applications I will prefer writing each of these layers.
There is no thumb rule.

Should I create a dependency from presentation tier to Spring Data to use pagination

We are creating a web based application using, JSF (Primefaces as presentation library) and Spring Data JPA for data access tier. And the project is Spring Boot enabled.
The project is divided into multiple modules (according to tiers), and one of them is the presentation tier.
Do you suggest creating a dependency from presentation tier to Spring Data (so have access to PageRequest and Slice and ... classes) or not?
Otherwise we shall re-implement these classes in this tier and convert them to Spring Data classes, which seems some how verbose.
Do you suggest creating a dependency from presentation tier to Spring Data (so have access to PageRequest and Slice and ... classes) or not?
Every decision you make will have it's Pros and Cons and it really depends on your specific situation if this is a problem or not.
I see the following things in favor of a dependency:
reuse of PageRequest and similar classes. They represent concepts that are needed when working with persistence but aren't really persistence specific. Therefore there is really no point in duplicating them.
On the other hand, Spring Data contains many classes that don't have any business in a presentation layer. For example, those dealing with creating repositories.
Your task is to determine if the risk/damage of having those classes around is bigger than the benefit of having PageRequest and co available.
With all teams and projects I worked with so far I'd opt for just having a dependency.
Here is why:
The domain has a dependency on JPA and Spring Data anyway. So by depending on the domain-layer, you get a transient dependency, no matter if you want or not.
The persistence specific classes inside Spring Data are so specific that I never experienced anybody trying to use them directly.
Note that especially the first point assumes that you are not copying over your JPA entities in separate transport objects, which would kind of negate the benefits of JPA.

MVC / Repository Pattern - Architecture

I have a project in which I am using NHibernate and ASP.Net MVC. The application is intended to allow users to track certain data and then produce views of statistics based upon the data entered. The structure of my application thus far looks something like this:
NHibernate Layer: Contains Repository<T> and UnitOfWork classes, as well as entity mapping definitions.
Core/Service Layer: Contains generic EntityService class. At the moment, this simply defines transaction scope via IUnitOfWork and interfaces with IRepository to provide higher-level data access services.
Presentation Layer (MVC Application): Not yet implemented, but contains the usual stuff plus dependency injection.
I have a couple of questions:
Is it poor design to allow my MVC application to handle dependency injection for ALL layers? For example, as well as dependency injection of EntityService instances into controllers, it will handle the dependency injection of IRepository into the EntityService classes. Should the service layer handle this itself, even though this would mean performing dependency injection in two distinct places?
Where should I produce my statistics? This business logic doesn't seem to belong in my service layer, which, at present, only contains entity type definitions and an interface for modifying and accessing entity properties. I have a few thoughts on this, but I'm not sure which I like best:
Keep my service layer as is and create a separate Statistics project - this is completely independent of the entity types for which it will be used, meaning my MVC controllers will have to pass raw numerical information between my business entities and my (presumably static) statistics classes. This is quite a neat separation but potentially means a lot of business logic still remaining in the presentation layer.
Create a Statistics project; however, create a tight coupling between the classes in this project and my business entities. For example, instead of passing a Reading object's values into a method, I will pass the entire object (or define them as extension methods). This will shift business logic out of my MVC app but the tight coupling seems a bit messy.
Keep all of my business logic inside my service layer. Define strongly-typed subclasses of EntityService, so my services contain both entity-specific business methods and data storage methods, while keeping the entity classes themselves as pure data containers. Create a separate Statistics project for any generic statistical processing and call its methods via my derived service classes. My service classes effectively merge business functions with the storage functionality provided created by IRepository<T>.
I am erring toward the third option but does anyone have any thoughts? Alternative suggestions?
Thanks in advance!
Preliminary observation:
I like the way in which you described your project, I just didn't get why your Data Access Layer (DAL) is called NHibernate Layer: it is odd with all the rest in which you didn't use technology name to describe a logical layer (correctly). So I suggest you to rename it DAL, and use it to abstract your app from NHibernate.
My opinions about your questions:
Absolutely no. It is good to apply Dependency Injection to All Layers. A couple or reasons for which it is good:
1.1 Testing: you can mock DAL interfaces and do unit test Service Layer w/o DAL using another DI config file. In the same way you can mock Service for Web Controllers layer and so on.
1.2 Different DAL implementations: suppose you need different DAL implementation (NOSQL, SQL or LINQ instead of NHibernate, etc..) technologies for different deployment of you project or to scale in the future. You can do that easily maintaining different DI config files.
You can have the same layer deployed in different projects. In the same way you can have a project containing different layers. I think their relation is orthogonal: project is describing a physical (development time and run time) implementation. Layers are logical. So initially I would keep it simple with the third option.
I just don't understand why you saying the following regarding this option:
Create a separate Statistics project for any generic statistical
processing and call its methods via my derived service classes. My
service classes effectively merge business functions with the storage
functionality provided created by IRepository.
I see Statistics as one or more services so you can implement it as namespace with classes inside your Service Layer. And, as any other service, you can inject DAL Repository classes. And, as any other Service/DAL, the Model classes can be shared between different Services and DAL classes.
StatsService.AverageReadingFor(Person p, DateTime start, DateTime end) sounds good.
There are several implementation options:
Using underlying repository features (for example: SQL avg function)
Using Observer Pattern which is implementable also using Dependency Injection
Using Aspect Oriented Programming. See that Spring.Net chapter as an example.
If you have more than one Service Layer instance (more than one server) than 2 and 3 must be adapted for out of process communication using a messaging system.
Just an update - Regarding my second question, I have decided to define an IStatsService<T> which expects an IEntityService<T> to be passed into its constructor. I'll use this for generic statistical processing of business entities and create further interfaces that implement IStatsService<T> where I need more type-specific information.
Hopefully this will help someone who has been scratching their head about a similar problem!

Resources