Use database #Entity classes for REST exposure? - java

#Entity
class MyEntity {
//some properties to be explosed to REST, some not
}
I have some database classes that I want to explose via REST using spring.
Is it advisable to create a DTO for each database class, copying over all properties needed to be exposed.
Because certainly some fields like the id should never be available via rest. But these fields can maybe be annotated accordingly so they are ignored during REST offer?
Is writing DTOs still advisable today if they just serve as plain data containers that get the fields copied over from DB?

Some points I can think while deciding:
Arguments against common model for persistence & web service
In many applications the rest services are written to provide you a fully constructed object & not really a normalized view of the data. For example your rest service may return an Employee object with a Department object, wheras your db model just has a deparment id
Modifications in 1 model do not affect the other. For example you decide to change a String in the persistence model to an integer, you may still be ok with keeping it as a string in your rest service
You may have attributes in the rest model which make no sense to be on the persistence model or vice versa
If you are distributing your model jar (like a client API) then it may end up with a dependency on your persistence framework which your clients may not want/support.
Arguments supporting common model for persistence & web service
Avoid copying/cloning data for every interaction
Avoid duplicate maintenance or possible issues when an attribute is added in 1 model and forgotten in another
In my experience if you are creating services exclusively to be consumed by your own application (like a UI) and have tight control on those services, you might get away with using a common model
However if the rest API is intended for broader use and for longevity I would go with separate models. You can use spring's beanutils to ease the conversion of models from one format to other. See example here

Related

JPA Spring Data entity to be used outside of transaction

I have a Spring Boot application with a service that returns a Spring Data entity that is exposed to a controller. The problem is that I know it's not a good idea to use entities outside of DB transactions, so what would be the best practices?
Consider the following service:
#Transactional
public MyData getMyData(Long id) {
return myDataRepository.findById(id);
}
where MyData is a database #Entity and myDataRepository is a JpaRepository
This service method is called from a controller class, that sends this object in JSON format to a client that calls this method.
#RequestMapping("/")
public ResponseEntity<?> getMyData(#RequestParam Long id) {
return myService.getMyData(id);
}
If I expose MyData to a controller, then it will be exposed outside of a transaction and might cause all kind of hibernate errors. What are the best practices for these scenarios? Should I convert entity to POJO in side the service and return MyDataPOJO instead of MyData in MyService?
Using entities outside of transactions does not necessarily lead to problems; it may actually have valid use cases. However, there's quite a few variables at play and once you let them out of your sight things may and will go south. Consider the following scenarios:
Your entity doesn't have any relationships to other entities or those relationships are pretty shallow and eagerly fetched. You retrieve that entity from repository, detach it from persistence unit (implicitly or explicitly) and pass to controller. Controller does not attempt to modify the entity; it only serializes it into JSON - totally safe.
Same as above but controller modifies the entity before serializing it into JSON - again, totally safe (just don't expect those changes to be reflected in DB)
Same as above, but you've forgotten to detach the entity from PU - ouch, if controller changes the entity you may either see it reflected in DB or get transaction closed exception; both most likely being unintended consequences.
Same as above, but some of entity's relationships are lazy. Again, you may or may not get any exceptions depending on whether these lazy properties are being accessed or not.
And there are so many more combinations of intentional and unintentional design choices...
As you may see, things can get out of control very quickly. Especially so when your model has to evolve: before long you're going to find yourself fiddling with JSON views, #JsonIgnore, entity projections and so on. Thus the rule of thumb: although it may seem tempting to cut some corners and expose your entities to external layers, it's rarely a good idea. Properly designed solution always has a clear separation of concerns between layers:
Persistence layer never exposes more methods or entities than required by business logic. More over, the same table(s) can and should be mapped into several different entities depending on the use cases they participate in.
Business logic layer (btw this is your API, not the REST services! see below) never leaks any details from persistence layer. Its methods clearly define use cases from the problem domain.
Presentation layer only translates API provided by business logic into one or another form suitable for client and never implements additional use cases. Keep in mind that REST controllers, SOAP services etc logically are all part of presentation layer, not business logic.
So yeah, the short answer is: persistence entities should not be exposed to external layers. One common technique is to use DTOs instead; besides, DTO objects provide additional abstraction layer in case you need to change your entities but leave API intact or vice versa. If at some point your DTOs happen to closely resemble your entities, there are Java bean mapping frameworks like Dozer, Orika, MapStruct, JMapper, ModelMapper etc that help to eliminate the boilerplate code.
Try googling "hexagonal architecture". This is a very interesting concept for designing cleanly separated layers. Here's one of the articles on this subject https://blog.octo.com/en/hexagonal-architecture-three-principles-and-an-implementation-example/; it uses C# examples but they're pretty simple.
You should never leak the internal model to outside resources (in your case - the #RestController). The "POJO" you mentioned is typically called a DTO (Data Transfer Object). The DTO can be defined as an interface on the Service-side and implemented on the Controller-side. The Service would then - as you described - transform the internal model into an instance of the DTO, achieving looser coupling between the Controler and the Service.
By defining the DTO-interface on the service-side, you have the additional benefit that you can optimize your persistence-acces by only fetching the data specified in the corresponding DTO-interface. There is, for example, no need to fetch the friends of a User if the #Controller does not specifically requests them, thus you do not need to perform the additional JOIN in the database (provided you use a database).

Service layer return object types

You know that for an API project there are many patterns to retrieve and serve data to client. Controller <-> Service <-> Dao pattern is one of the these patterns.
Is it good to return any type of object from service layer or service layer return objects must be related entity?
For example, we have User, UserService, UserDao.
Should UserService return types be User or any type of object is suitable?
Having logical operations in service layer force me to use other objects as return type.
What is the best practice for that case?
I've found that I need 3 types of objects to keep things manageable (I'm still in a battle trying to come up with a decent naming strategy). It's sometimes beneficial to have:
Objects returned from your data layer - These objects will be dictated by your data implementation. For example, they could change if you decide to store your data differently. Perhaps you decide to serialise an object and store it as JSON rather than storing it in a separate table, or you move from SQL to NOSQL.
Objects returned from your domain layer - These are application objects and should model your domain. They shouldn't contain anything that is specific to your data implementation.
Objects sent to and from you API - It's useful to have separate serialisation objects to shape your API. It means you can tweak your API without having to touch the business logic. On some projects, I have multiple versions of the API objects for v1, v2 etc.
The widely accepted practise involve the service to have all business logic in it and return the Data Transfer Object(DTO)/ Business Object like User in your case. The Service may call DAO, any other datasources to fetch the entities, and a mapper/converter util can be used to convert the entities to DTO objects.
The DTO objects returned from Service can be embedded in a ResponseEntity(In the case of Spring MVC) and returned from the controller.
This makes your application into 3 separated layers like web, service, dataaccess. This supports design principles like Separation of Concerns, Single Responsibility. This also makes your unit testing and code management easier.

Architectural layers in Java web application [duplicate]

This question already has answers here:
How to use DTO in JSF + Spring + Hibernate
(2 answers)
JSF Service Layer
(2 answers)
Closed 7 years ago.
I am developing a java web application and am trying to follow some patterns like dao/dto. At the moment i am thinking about such base architecture layers:
I ran into some questions regarding the layers. The scheme would go as such: DAO takes in DTO and returns objects(entities) from DataBase, Service layer also takes in DTO, uses DAO and does all the required logic with the returned objects. UI Bean, Service, DAO and DTO classes are Entity specific - each entity has its own layers.
Now would i need the UI bean to use in views or would that be an overkill and UI views can directly use service classes as ui beans? If no, why would i need UI bean?
Another question is regarding DTO. I have created entities with all the required properties and as i understand DTO classes are like reflections of Entity classes. So why would i need these DTO classes and if i use them i recon it would require some converting from entity to dto and vice versa. Do i do the converting in Service layer? Would views (for eg. html pages) also display DTO object properties not actual Entities (as in calling #{UIBean.entityProperty})?
First of all, I would use the DTO beans on the front-end part only, but since u already mention UI-beans, i suppose these will do the trick just fine, the facade uses these to pass them to the controller for displaying your web-components.
in between the Service and the facade you map the entities of the backend towards dto-beans.
In this way your front-end will be completely loosely coupled to your backend.
Regarding your 2nd question I would like to point out an exact valable reason why your UI should always use dto or view beans.
You can combine several backend entity-beans into one dto bean for easier processing on the front-end.
In general I keep always in mind DTO's for public acces, eta a web-service exposing it or a web-front end or a swing app, or...
Entity classes only used in dao and service layer never further up.
As rule of thumb try to divide logical layers according to your context. Inspire you of the theory but use it with care. I give you my humble understanding of layer's interest with few examples. This vision is of course not complete but I hope it will help you to answer your questions.
So is it overkill to use UIBean instead of Service DTO ? I would say it depends of your context.
Maybe there are user inputs data inside your UI beans ? You have to validate them with JSR 303 annotations for example. If those annotations have a meaning in this layer they are useless for underneath layers. That's why you will have a UIBean with JSR 303 annotations and a DTOBean without JSR 303 annotations.
But if they are exactly the same why duplicate ? Maybe at UIBean layer a date could be represented as a String type and you want to manipulate Date type instead of String at DTO layer. That's why you need to adapt your data between layers to work with objects that make sense to a particular layer. For example, you could add a BOAdapter (between UIView and Service) and DTOAdapter (between Service and DAO). Those adapters are usefull for transforming your data inside each POJO's format. For example, you could have in your BO(=UIBean) a date expressed inside three strings and you want a Date object for DTO so you transform it inside the BOAdapter:
public class BOAdapter(){
private BOAdapter(){}
public static DTO toDTO(BO objectBO){
DTO objectDTO = new DTO();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-aa");
objectDTO.setDate(df.parse(objectBO.getYear()+"-"+objectBO.getMonth()+"-"+objectBO.getDay());
[...]
}
}
Why I need DTOAdapter ? Maybe you have a database that contains at least two tables Customers and Adresses with an integrity constraint between them. JPA will automatically generate the right code. But do you really need all this code up to UIView ? I mean if the functionnality you are coding needs only the name, surname and date of birth of your customer, their adress is useless. Again that's why you need to adapt your data between layers to work with objects that make sense to a particular layer. In this case you could create a DTO object only with name, surname and date of birth information and create a method inside your DTOadapter to transform your custom DTO into an heavy JPA object to work properly with database.
But I need the whole entity for coding my fonctionnality ? Maybe you need to add validation constraints inside this layer besides JSR 303. So it could be interesting to have DTO classes besides your entity for the same reason as BO objects.
But my entity is big how duplicate it easily ? Try to use a tool to map data (like dozer) automatically. If it is not too big do it manually.
Since you have Spring tag,
I will replace your [DAO] with Spring Data Repository. So most of the time, you write interface method / #query annotation, Spring Data write implement.
Replace DTO with JPA Entity. So I could use some reverse engineering.
[UI Bean] will most be composite of JPA Entity. With some validation

Where should be placed business logic in the three-layer system?

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.

How does the Integration Tier interface with the Business Tier?

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.

Categories