Custom Hibernate business validation model: possible risks - java

I'm planning to create a custom validation model that depends on the Pre and Post Listeners of Hibernate.
Each Validation class should contain a business rule (not input checking) that needs to be checked before doing an insert, update or delete.
That's why it depends on Listeners like PreInsertEventListener, PreUpdateEventListener, PreInsertDeleteListener.
A validation class sometimes needs to check something in the DB. I've read in other posts that it is not advised to insert or update something from a Listener? But I'm planning to do only read-only calls.
To resume:
Validation class is related to one specific entity;
Validaton class is invoked by a Hibernate Listener;
Validation class might do some 'read-only' calls in DB;
Validation class is executed within same Hibernate Session and Transaction;
When a rule is not satisfied, some RuntimeException will be thrown causing a rollback of the current Transaction;
The advantage of this concept is that all business rules can be put in Validation classes which are specifically related to one entity. This avoids business rules to be spread over different Services.
What do you think of this approach? Are there any disadvantages/risks (specifically Hibernate related) wich I need to take care of?

I think the important thing here is predicting that your validation rules will only be specific to the entity being persisted. Its quite possible that you will run into situations that require data from parent/child entities to validate or to fetch related data.
The business rules spread over different services is a real world case, where usually to validate an entity you need to invoke different services. For example, if you want to persist a debit transaction for an account, you want to validate if the account holder exists, account is in a valid state & account has sufficient balance.

Related

How to design and validate access to a sub-resource in a jax-rs REST API avoiding code duplication?

Specifications
I'm currently developing a JavaEE app using JAX-RS and in the process of exposing various resources I'm faced with the following design dilemma that I haven't found a proper answer to.
Two entities, Customer and Address, are interconnected with the One-To-One, Total
Participation relationship, meaning one Address per Customer. Deriving from these I created a resource CustomerResource that exposes various endpoints relating to the Customer entity that lead to basic CRUD operations. Some of these endpoints are:
POST (/customers/create)
GET (/customers/get)
GET (/customers/get/{id})
PUT (/customers/update/{id})
DELETE (/customers/delete/{id}
The problem arises when I create the second resource AddressResource which will handle endpoints relating to operations for the Address entity. This entity cannot exist without a Customer and as such I came to the decision to convey that using nested URI scheme, as opposed to using QueryParams. Now, as you can imagine, some of the endpoints that the AddressResource exposes are:
POST (/customers/{id}/address/create)
GET (/customers/{id}/address/get)
PUT (/customers/{id}/address/update)
DELETE (/customers/{id}/address/delete)
I'm faced with validating IF the Customer ID exists and then continuing on to the actual operation that the endpoint entails. Looking the app design from a top down viewpoint, right after the Resource classes come the Service classes. For each Resource class there is a Service class which carry out any necessary business logic and call for the DAO classes to reflect all the necessary changes to the physical DB and the persistence context. So, any validation happens on the Service layer. The thing is that the AddressService class will have to make a call to check if the Customer exists using the CustomerDao class, which queries the database for the given customerId and returns its findings. If the customer exists then the AddressDao gets called to perform the corresponding query on the DB relating to the Address entities.
So, in a sense, I want to avoid the coupling of the Service classes passing calls to multiple Dao classes, as well as, avoid any duplicate code that validation for multiple resources might lead to.
This is due to the fact that I want to introduce a new One-To-Many resource that also requires validation on the customerId level and this would entail its Service class also calling the CustomerDao. I'm aware of the N+1 query problem and I'm keeping the nested resource depth at a maximum of 2. The validation would have to be performed regardless of the URI design as it derives from the Total Participation rule.
Sry for the long and maybe oversimplified explanation of the problem and thank you all in advance!
First, "One-To-One, Total Participation relationship, meaning one Address per Customer" also means "just one Customer at one Address". In this case you don't need separate Entity for Address, it might be the part of Customer.
So, let me suppose, you meant One-To-Many relation: "many Customers at one Address". Didn't you? In this case you can create Addresses as a dictionary with separate resource then bind that to some Customers with web-method of Customer resource.
Finally, to avoid code duplication you can encapsulate business logic within appropriate facades then inject those anywhere you need like:
#Inject
CustomerFacade customerFacade;
...
customerFacade.bindAddress(customerId, addressId);

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).

Where should business validation to be done

Suppose the architecture is such that there is
Struts framework or jersey resource
Facade layer
Business layer
Data access object layer DAO
Though the Input field validation is to be done at presentation layer i.e Struts Action class or jersey resource class
But my question is where should business level validation to be done and same outcome to be passed to UI.
I.e suppose resource is
employee/{employeeId} method DELETE
Now first need to verify that employeeId exist or not , so for that validation should be done at resource level, facade level or business level and how it should be any best practice is highly appreciated.
Also please note that this business validation require DAO layer access since to check in DB if employeeId really exist.
Thanks in advance
There are as many arguments as approaches for what you're asking. I prefer to leave validation to the business layer and let the service layers above that more or less just handle routing and error reporting. Good luck!
Depends on the architectures and frameworks you have choosen.
In example: If you have one Database but a server-farm, the Validation should be more near the Database. If you can lock/unlock the Database in the DAO, you shall lock the employee-row first before you validate.
Also it depends on the configuration:
If you use optimistic or pessimistic locking.
If you have a #version field on the entitys.
many many more.
I suggest you to write logic related database access at dao layer, which returns the result to service layer and it returns to the Action class. And you should validate it in your action class.

JPA merge in a RESTful web application with DTOs and Optimistic Locking?

My question is this: Is there ever a role for JPA merge in a stateless web application?
There is a lot of discussion on SO about the merge operation in JPA. There is also a great article on the subject which contrasts JPA merge via a more manual Do-It-Yourself process (where you find the entity via the entity manager and make your changes).
My application has a rich domain model (ala domain-driven design) that uses the #Version annotation in order to make use of optimistic locking. We have also created DTOs to send over the wire as part of our RESTful web services. The creation of this DTO layer also allows us to send to the client everything it needs and nothing it doesn't.
So far, I understand this is a fairly typical architecture. My question is about the service methods that need to UPDATE (i.e. HTTP PUT) existing objects. In this case we have these two approaches 1) JPA Merge, and 2) DIY.
What I don't understand is how JPA merge can even be considered an option for handling updates. Here's my thinking and I am wondering if there is something I don't understand:
1) In order to properly create a detached JPA entity from a wire DTO, the version number must be set correctly...else an OptimisticLockException is thrown. But the JPA spec says:
An entity may access the state of its version field or property or
export a method for use by the application to access the version, but
must not modify the version value[30]. Only the persistence provider
is permitted to set or update the value of the version attribute in
the object.
2) Merge doesn't handle bi-directional relationships ... the back-pointing fields always end up as null.
3) If any fields or data is missing from the DTO (due to a partial update), then the JPA merge will delete those relationships or null-out those fields. Hibernate can handle partial updates, but not JPA merge. DIY can handle partial updates.
4) The first thing the merge method will do is query the database for the entity ID, so there is no performance benefit over DIY to be had.
5) In a DYI update, we load the entity and make the changes according to the DTO -- there is no call to merge or to persist for that matter because the JPA context implements the unit-of-work pattern out of the box.
Do I have this straight?
Edit:
6) Merge behavior with regards to lazy loaded relationships can differ amongst providers.
Using Merge does require you to either send and receive a complete representation of the entity, or maintain server side state. For trivial CRUD-y type operations, it is easy and convenient. I have used it plenty in stateless web apps where there is no meaningful security hazard to letting the client see the entire entity.
However, if you've already reduced operations to only passing the immediately relevant information, then you need to also manually write the corresponding services.
Just remember that when doing your 'DIY' update you still need to pass a Version number around on the DTO and manually compare it to the one that comes out of the database. Otherwise you don't get the Optimistic Locking that spans 'user think-time' that you would have if you were using the simpler approach with merge.
You can't change the version on an entity created by the provider, but when you have made your own instance of the entity class with the new keyword it is fine and expected to set the version on it.
It will make the persistent representation match the in-memory representation you provide, this can include making things null. Remember when an object is merged that object is supposed to be discarded and replaced with the one returned by merge. You are not supposed to merge an object and then continue using it. Its state is not defined by the spec.
True.
Most likely, as long as your DIY solution is also using the entity ID and not an arbitrary query. (There are other benefits to using the 'find' method over a query.)
True.
I would add:
7) Merge translates to insert or to update depending on the existence of the record on DB, hence it does not deal correctly with update-vs-delete optimistic concurrency. That is, if another user concurrently deletes the record and you update it, it must (1) throw a concurrency exception... but it does not, it just inserts the record as new one.
(1) At least, in most cases, in my opinion, it should. I can imagine some cases where I would want this use case to trigger a new insert, but they are far from usual. At least, I would like the developer to think twice about it, not just accept that "merge() == updateWithConcurrencyControl()", because it is not.

How to control JPA persistence in Wicket forms?

I'm building an application using JPA 2.0 (Hibernate implementation), Spring, and Wicket. Everything works, but I'm concerned that my form behaviour is based around side effects.
As a first step, I'm using the OpenEntityManagerInViewFilter. My domain objects are fetched by a LoadableDetachableModel which performs entityManager.find() in its load method. In my forms, I wrap a CompoundPropertyModel around this model to bind the data fields.
My concern is the form submit actions. Currently my form submits pass the result of form.getModelObject() into a service method annotated with #Transactional. Because the entity inside the model is still attached to the entity manager, the #Transactional annotation is sufficient to commit the changes.
This is fine, until I have multiple forms that operate on the same entity, each of which changes a subset of the fields. And yes, they may be accessed simultaneously. I've thought of a few options, but I'd like to know any ideas I've missed and recommendations on managing this for long-term maintainability:
Fragment my entity into sub-components corresponding to the edit forms, and create a master entity linking these together into a #OneToOne relationship. Causes an ugly table design, and makes it hard to change forms later.
Detach the entity immediately it's loaded by the LoadableDetachableModel, and manually merge the correct fields in the service layer. Hard to manage lazy loading, may need specialised versions of the model for each form to ensure correct sub-entities are loaded.
Clone the entity into a local copy when creating the model for the form, then manually merge the correct fields in the service layer. Requires implementation of a lot of copy constructors / clone methods.
Use Hibernate's dynamicUpdate option to only update changed fields of the entity. Causes non-standard JPA behaviour throughout the application. Not visible in the affected code, and causes a strong tie to Hibernate implementation.
EDIT
The obvious solution is to lock the entity (i.e. row) when you load it for form binding. This would ensure that the lock-owning request reads/binds/writes cleanly, with no concurrent writes taking place in the background. It's not ideal, so you'd need to weigh up the potential performance issues (level of concurrent writes).
Beyond that, assuming you're happy with "last write wins" on your property sub-groups, then Hibernate's 'dynamicUpdate' would seem like the most sensible solution, unless your thinking of switching ORMs anytime soon. I find it strange that JPA seemingly doesn't offer anything that allows you to only update the dirty fields, and find it likely that it will in the future.
Additional (my original answer)
Orthogonal to this is how to ensure you have a transaction open when when your Model loads an entity for form binding. The concern being that the entities properties are updated at that point and outside of transaction this leaves a JPA entity in an uncertain state.
The obvious answer, as Adrian says in his comment, is to use a traditional transaction-per-request filter. This guarantees that all operations within the request occur in single transaction. It will, however, definitely use a DB connection on every request.
There's a more elegant solution, with code, here. The technique is to lazily instantiate the entitymanager and begin the transaction only when required (i.e. when the first EntityModel.getObject() call happens). If there is a transaction open at the end of the request cycle, it is committed. The benefit of this is that there are never any wasted DB connections.
The implementation given uses the wicket RequestCycle object (note this is slightly different in v1.5 onwards), but the whole implementation is in fact fairly general, so and you could use it (for example) outwith wicket via a servlet Filter.
After some experiments I've come up with an answer. Thanks to #artbristol, who pointed me in the right direction.
I have set a rule in my architecture: DAO save methods must only be called to save detached entities. If the entity is attached, the DAO throws an IllegalStateException. This helped track down any code that was modifying entities outside a transaction.
Next, I modified my LoadableDetachableModel to have two variants. The classic variant, for use in read-only data views, returns the entity from JPA, which will support lazy loading. The second variant, for use in form binding, uses Dozer to create a local copy.
I have extended my base DAO to have two save variants. One saves the entire object using merge, and the other uses Apache Beanutils to copy a list of properties.
This at least avoids repetitive code. The downsides are the requirement to configure Dozer so that it doesn't pull in the entire database by following lazy loaded references, and having yet more code that refers to properties by name, throwing away type safety.

Categories