Patterns for Data validation when using a DAO - java

I am developing a web application and am trying to determine the best practice for validating data before it is persisted.
I currently have 2 DAO interfaces:
UserDAOInt - defines what operations a user can perform, throws data validation exceptions
UserDAOPersistenceInt - defines what operations a user can perform, throws jpa exceptions
I have corresponding implementations for the DAO Interfaces:
UserDAOImpl - implements UserDAOInt, validates the data by making sure all data required is present, making sure that the entities being updated or deleted exist in the database. If there is an issue, an exception is thrown. If everything is ok, a call is made to the corresponding method in the classes UserDAOPersistenceInt implementation.
UserDAOPersistenceImpl - implements the UserDAOPersistenceInt. The only validation that occurs is checking for null objects returned by EntityManager calls, just in case they were removed between the time the validation occurred and the call to the method. Throws persistence related exceptions or Exception if a null object was returned by the EntityManager.
When the data comes in from the servlets, I validate the data on the web tier side before even attempting to use a DAO.
My question is, is it bad practice to validate the data on both the web tier side, and again within the DAO's?
I'm asking because I'm finding that I'm maintaining 2 sets of validations.
The validation that takes place on the servlet is the validation of the data coming in from the user, mainly in forms. If a validation error happens here, I generally use the text of the validation error as feedback that is presented to the user, for example, First Name is required, when filling out a form.
Once I make it to the DAO, I'm expecting for the operation to complete successfully, because I have 'vetted' the data within the web tier. Any exceptions that occur in the validation at the DAO level I use as the text that is logged, and then send a 500 error response, for example, but the underlying message in the exception is not something that I display to the user.
I would really like to only have 1 place where validations are maintained so that I don't have to make changes in 2 places, but I'm really just looking to find out what the established best practices are.

I would hand this over to the bean validation framework. It allows you to manage the validation rules in a single place, as annotations to the bean, like this:
#Entity
public class Contact implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#NotNull
protected String firstName;
#NotNull
protected String lastName;
#Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\."
+"[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#"
+"(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?",
message="{invalid.email}")
protected String email;
#Pattern(regexp="^\\(?(\\d{3})\\)?[- ]?(\\d{3})[- ]?(\\d{4})$",
message="{invalid.phonenumber}")
protected String mobilePhone;
#Pattern(regexp="^\\(?(\\d{3})\\)?[- ]?(\\d{3})[- ]?(\\d{4})$",
message="{invalid.phonenumber}")
protected String homePhone;
#Temporal(javax.persistence.TemporalType.DATE)
#Past
protected Date birthday;
}
Validation will then be performed automatically during the JPA lifecycle events (PrePersist, PreUpdate, and PreRemove).
Manual validation can be done like this:
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<Contact>> errors = validator.validate(bean);
See the JPA Entity tutorial and the Bean validation tutorial for more information on what's possible.

Related

How to save entities with manually assigned identifiers using Spring Data JPA?

I'm updating an existing code that handles the copy or raw data from one table into multiple objects within the same database.
Previously, every kind of object had a generated PK using a sequence for each table.
Something like that :
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
In order to reuse existing IDs from the import table, we removed GeneratedValue for some entities, like that :
#Id
#Column(name = "id")
private Integer id;
For this entity, I did not change my JpaRepository, looking like this :
public interface EntityRepository extends JpaRepository<Entity, Integer> {
<S extends Entity> S save(S entity);
}
Now I'm struggling to understand the following behaviour, within a spring transaction (#Transactional) with the default propagation and isolation level :
With the #GeneratedValue on the entity, when I call entityRepository.save(entity) I can see with Hibernate show sql activated that an insert request is fired (however seems to be only in the cache since the database does not change)
Without the #GeneratedValue on the entity, only a select request is fired (no insert attempt)
This is a big issue when my Entity (without generated value) is mapped to MyOtherEntity (with generated value) in a one or many relationship.
I thus have the following error :
ERROR: insert or update on table "t_other_entity" violates foreign key constraint "other_entity_entity"
Détail : Key (entity_id)=(110) is not present in table "t_entity"
Seems legit since the insert has not been sent for Entity, but why ? Again, if I change the ID of the Entity and use #GeneratedValue I don't get any error.
I'm using Spring Boot 1.5.12, Java 8 and PostgreSQL 9
You're basically switching from automatically assigned identifiers to manually defined ones which has a couple of consequences both on the JPA and Spring Data level.
Database operation timing
On the plain JPA level, the persistence provider doesn't necessarily need to immediately execute a single insert as it doesn't have to obtain an identifier value. That's why it usually delays the execution of the statement until it needs to flush, which is on either an explicit call to EntityManager.flush(), a query execution as that requires the data in the database to be up to date to deliver correct results or transaction commit.
Spring Data JPA repositories automatically use default transactions on the call to save(…). However, if you're calling repositories within a method annotated with #Transactional in turn, the databse interaction might not occur until that method is left.
EntityManager.persist(…) VS. ….merge(…)
JPA requires the EntityManager client code to differentiate between persisting a completely new entity or applying changes to an existing one. Spring Data repositories w ant to free the client code from having to deal with this distinction as business code shouldn't be overloaded with that implementation detail. That means, Spring Data will somehow have to differentiate new entities from existing ones itself. The various strategies are described in the reference documentation.
In case of manually identifiers the default of inspecting the identifier property for null values will not work as the property will never be null by definition. A standard pattern is to tweak the entities to implement Persistable and keep a transient is-new-flag around and use entity callback annotations to flip the flag.
#MappedSuperclass
public abstract class AbstractEntity<ID extends SalespointIdentifier> implements Persistable<ID> {
private #Transient boolean isNew = true;
#Override
public boolean isNew() {
return isNew;
}
#PrePersist
#PostLoad
void markNotNew() {
this.isNew = false;
}
// More code…
}
isNew is declared transient so that it doesn't get persisted. The type implements Persistable so that the Spring Data JPA implementation of the repository's save(…) method will use that. The code above results in entities created from user code using new having the flag set to true, but any kind of database interaction (saving or loading) turning the entity into a existing one, so that save(…) will trigger EntityManager.persist(…) initially but ….merge(…) for all subsequent operations.
I took the chance to create DATAJPA-1600 and added a summary of this description to the reference docs.

How to hardcode group information on field for cascading validation

I have the following bean;
public class Customer {
#NotNull(groups = New.class)
private String id;
#Valid
private List<CustomerDetail> detailList;
}
As you see, I cascade validation down to each CustomerDetail in detailList by annotating the field with #Valid, but I wish to propagate the validation with a hard-coded group, is that possible? Whatever group is supplied for validation, I wish a fixed group, namely New to be active in validation of detailList.
This is due to my conflicting requirements, one wishes to treat details as a sub-resource of Customer therefore I need full validation on it all the time when it is validated within a customer pojo. Another requirement is to treat each detail as a separate resource, therefore I need to do patch for some fields, so when it is validated separately, different groups can be applied.
public class CustomerDetail {
#NotNull(groups = New.class)
private String desc;
private String remark;
}
So when it is any sort of operation for Customer, every CustomerDetail in customerList should use New group, even if Customer does not necessarily use that group for validation.
In a way, I want to do this;
public class Customer {
#NotNull(groups = New.class)
private String id;
#Validated(New.class)
private List<CustomerDetail> detailList;
}
But I was unable to find such a feature, I wanted to do this to evade creating multiple groups, which was deemed confusing.
You need to introduce your own annotation to have class level constraints. Create a custom annotation with own validation logic implemented in the validator.
See the chapter 6.2. Class-level constraints of the doc
Or see the example

Hibernate lazily loading fields

I have this issue with hibernate. the scenario is that i'am remaking my project. my previous project is with JMS which runs smoothly with my POJOs. and now i am trying to recreate it using Apache Mina(socket programming) with Google's Gson.
I am having problem with lazy loading of my fields, because the project that uses JMS runs smooth with lazy loading but now i am trying to retrieve some value in the database but there is always a hibernate exceptiong stating that failed to lazily initialize a collection of role: class.field, no session or session was closed which i want to load lazily, i dont want to retrieve it everytime.
public class User {
#Id
#GeneratedValue
#Column(name = "iduser")
private Integer iduser;
#Column(name = "firstname")
private String firstname;
#Column(name = "lastname")
private String lastname;
// this field causes the lazy loading exception
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
#BatchSize(size = 4)
private Set<Transaction> transaction;
}
and i am retrieving it in my DAO like this
public User findByUser(String username, String pass) {
// TODO Auto-generated method stub
try {
User instance = (User) getSession().createCriteria(User.class)
.add(Restrictions.eq(USERNAME, username))
.add(Restrictions.eq(PASS, pass)).uniqueResult();
return instance;
} catch (RuntimeException re) {
throw re;
}
}
the method where i call the service
public ModelAndView processSignin(User currentUser, BindingResult result,
HttpServletRequest request) {
User user = service.signin(currentUser);
//i try to convert it to GSON but when i comment this line of code it works fine. but when gson tries to convert it to json string it seems that the annotations are being executed
System.out.println(gson.toJson(user));
}
signin method that calls the DAO class
public User signinDealer(User user) {
// TODO Auto-generated method stub
User currentUser = userDAO.signinUser(user);
return currentUser;
}
If you use Spring and Hibernate (which seems the case according to the tags of the question), you may want to configure Spring transaction management (small tutorial: http://www.baeldung.com/2011/12/26/transaction-configuration-with-jpa-and-spring-3-1/).
Then, you'll have to annotate any method (on a Spring bean) that uses a Hibernate entity with #Transactional. This will guarantee that any Hibernate object will be loaded in the context of a session, and that if you happen to trigger a lazy initialization, Hibernate will be able to fetch the objects using that session.
In your case you may want to have the method that both loads and serializes the User to JSON be annotated with #Transactional. Note that if you have 2 Spring application contexts (one root and one for Spring MVC), the annotation will most likely only work on beans defined in the root application context (so annotating the controller might not work, see #Transactional methods in #Controller class are not considred as transactional).
#Transactional
public String signinAndSerialize(String username, String password) {
User user = service.signin(username, password);
return gson.toJson(user);
}
When working with Hibernate, the lazy loading only works when the getter of the field is invoked inside the same transaction that loads the entire object. That means, if the getter is invoked when the transaction has finished, and the Hibernate session closed, the lazy loading exception is thrown.
You can make the conversion inside the transaction block, or exclude the specific field from serialization as explained here
By default Hibernate enables lazy loading. You could do following:
First evaluate whether you really need the relationship data. If you don't need the relationship data then there are ways / annotations to ignore it during JSON conversion. For eg. annotating the field with #JsonIgnore (import org.codehaus.jackson.annotate.JsonIgnore;).
If you really need the data then retrieve it while your hibernate session is still open.
Explicitly convert to EagerLoading by adding following attribute to your #OneToMany annotation fetch=FetchType.EAGER. However, this will have a performance impact.

Bean validation on REST API input, and API versioning

I have a bean like:
#Data
public static class ClassUnderTest {
#NotNull
private String field1;
#NotNull
#Since(2.0)
private String field2;
#NotNull
#Until(3.0)
private String field3;
}
#Since and #Until are Gson annotations that permits to avoid serializing / deserializing some fields on my REST API, for certain API versions.
I perform bean validation on the input payload of this API to raise constraint violations.
I'd like to be able to not raise the same violations per version, based on the Gson annotations (and not groups!).
Is there a way, from a ConstraintViolation<T>, to get the Member (like Method / Field) which produced the violation, so that I check if it is annotated by something?
Is there a way to handle validation versionning with Bean Validation?
The only solution I have seems to retrieve that member from the path (getPropertyPath), but it seems not easy to do...
You could retrieve the property name from the violation via getPropertyPath(). That said, assigning your constraints to groups corresponding to the versions might be the better approach. Note that validation groups can also extend existing groups, this might be helpful to model constraints added in a newer version.

Objectify + JSP: displaying 1:N relationships

My bean looks like that:
#Entity
public class Fattura {
#Id
Long id;
#NotEmpty
String numero;
#Min(value=0)
Double importo;
Key<User> utente;
// gets & sets....
}
The "utente" property is the key of another bean I created: a "Fattura" can have only one "User", one "User" can have many "Fattura"s
My Spring MVC controller will manage a request for a list of Fattura and display them in a simple jsp:
#RequestMapping( value = "/fatture" , method = RequestMethod.GET )
public ModelAndView leFatture() {
ModelAndView mav = new ModelAndView("fatture");
mav.addObject("fatture",fatturaService.listFatture());
return mav;
}
the code of the jsp is really simple: only a foreach cycle in a table
My question is:
how can I display the "utente"?
The only thing I have is its key, but I'd like to do something like ${fattura.utente.firstName} in my JSP, how can I do it?
Unfortunately you would have to manually fetch "utente" in your DAO class. There is no automatic fetching in Objectify like in Twig. In my POJOs I have following fields
#Transient private Organization sender; // Pickup location (for client RPC)
transient private Key<Organization> senderKey; // Pickup location (for Datastore)
I load entity from Datastore and then load manually Organization using senderKey.
In new Objectify4 you'll be able to do what you want like this:
class Beastie {
#Parent
#Load
ParentThing parent;
#Id Long id;
#Load({"bigGroup", "smallGroup"})
SomeThing some;
#Load("bigGroup")
List<OtherThing> others;
#Load
Ref<OtherThing> refToOtherThing;
Ref<OtherThing> anotherRef; // this one is never fetched automatically
}
Here is evolving design document of new version.
Update at Nov 17, 2011: This is big news. Twig author, John Patterson, joined Objectify project today.
I know it sounds annoying that you have to manually fetch the two objects, but it's actually very useful to know that you're doubling your work and time to do this - each "get" call take a while and the second won't start until the first is complete. It a typical NoSQL environment, you shouldn't often need to have two separate entities - is there a reason that you do?
There are only two reasons I can easily think of:
The class references another object of the same type - this is the example in the Objectify documentation, where a person has a reference to their spouse, who is also a person.
The class that you're embedding the other into ("Fattura" in your case) has masses of data in it that you don't want fetched at the same time as you want to fetch the "User" - and you need the user on it's own more often than you need the "Fattura" and the "User". It would need to be quite a lot of data to be worth the extra datastore call when you DO want the "Fattura".
You don't necessarily have to use temporary field for just getting a object.
This works:
public User getUtente() {
Objectify ofy = ObjectifyService.begin();
return ofy.get(utenteKey);
}
This will of course do a datastore get() each time the getter is called. You can improve this by using #Cached on your User entity, so they turn into memcache calls after the first call. Memcache is good, but we can do a little better using the session cache:
public User getUtente() {
Objectify ofy = myOfyProvider.get();
return ofy.get(utenteKey);
}
The key thing here is that you need to provide (through myOfyProvider) an instance of Objectify that is bound to the current request/thread, and that has the session cache enabled. (ie, for any given request, myOfyProvider.get() should return the same instance of Objectify)
In this setup, the exact same instance of User will be returned from the session cache each time the getter is called, and no requests to the datastore/memcache will be made after from the initial load of this Entity.

Categories