Purpose of #NotNull.List - java

When I looked among the standard constraints in Bean Validation API (JSR-303), I found the NotNull.List annotation. Its description is:
Defines several #NotNull annotations on the same element
This is valid syntax:
#NotNull.List({#NotNull, #NotNull})
private Object myObject;
But it makes no sense. Either the object is null or it is not. When would you use this annotation?
There are several other similar annotations like AssertFalse.List and AssertTrue.List.

You can have multiple #NotNull annotations that are mutually exclusive based on the group attribute.
#NotNull.List({#NotNull(groups=Foo.class,message="Some message!"),
#NotNull(groups=bar.class, message="Some other message!"})
private Object myObject;
I do agree it's a little silly for this example since only the payload and message can be affected, but it's probably there to remain consistent with the other annotations.
See here for more details.

As to the #NotNull case, multiple #NotNull annotations might be needed
for different validation groups as #dfb explained. But the same may be
accomplished by listing those groups in the groups attribute.
This is well explained here with test cases
In the bean validation API javadoc, for every constraint annotation,
there's a corresponding .List annotation. For example, for #NotNull,
there's #NotNull.List, for which JavaDoc says:
Defines several #NotNull annotations on the same element
What would you accomplish with multiple #NotNull annotations that you
cannot accomplish with one #NotNull?

Related

DDD validation on full object graph

#Value
#Builder
public class Parent {
#NotNull
private String firstName;
private Child child;
#Builder
public class Child {
#NotNull
private String firstName;
here is my challenge, we are doing DDD and we do the validation of objects within constructor or via a build method (builder pattern). What's I would like to achieve is to be able to construct the full object tree in a way that I can collect all validation errors.
As you can see with the following code, I will with this only collect the errors of the child missing the missing firstname of the parent.
Note that these objects are created manually, otherwise, I would just add #Valid's and such, but I don't think this can work when you do build objects manually.
FYI : I use the spring boot stack.
Parent.builder()
.firstName(null)
.child(Child.builder()
.firstName(null)
.build())
.build();
For providing a list of errors from domain model objects I usually collect all the potentially produced errors in the aggregate root which again collects the potential errors from its child domain objects. This approach follows the idea to collect errors instead of immediately throwing exceptions at the first occurrence of an error.
You can look into this answer which already illustrates an example of such an approach (although it is C# code the pattern is language agnostic).
I generally dissociate validation and domain models.
For example, I apply validation on the views representing a request body (see an example of such validation here) and then try to instantiate the value object only once I am sure that validation passed. In your case, it means that you will put your annotations on the views, not the VOs.
Note that it does not make sense to apply validation on a VO: the fact that you were able to create it implies that all constraints are already met.
If you are using the spring stack here would be an approach:
Create a new #Component called ParentFactory. the factory encapsulates the creation of valid objects in DDD.
inside of this factory you can use builder patterns or constuctor calls - it does not matter since object creation is abstracted away.
Furthermore the ParentFactory gets the javax Validator injected and thus is able to perform the mentioned task above
In DDD your Entities are not responsible for doing things like "collecting" errors unless that is part of your ubiquitous language. What you want to do is have the entities raise a DomainEvent and you can use a single listener to collect and consume all the raised events.

Using bean Validation in hibernate

I was wondering if it was possible to use Java Bean Validation in hibernate, and how they integrate with each other.
I have a stack that consists of a Jax-rs API, and JPA in my data layer.
I was wondering if I it could use Java Bean validation to validate my Hibernate Entities, without using Spring.
Could I use the annotations from hibernate along with the ones from the javax.validation.contraints together
for example:
#Column(nullable = false)
#Size(min =8, max = 12)
#NotNull(message = "Phone Number must be entered")
private String phoneNumber;
here I specify that I the column, can't be null through hibernate and the bean validation.
Is this a good practice?
Or is there an alternative to validating data in hibernate, without bean validation like such?
The Bean Validation specification integrates with Hibernate and all other implementations of the JPA 2.x specification. I explained that in great detail in my article How to automatically validate entities with Hibernate Validator.
Let me give a quick summary:
If you add an implementation of the Bean Validation specification, e.g., Hibernate Validator, to your project, Hibernate automatically triggers the validation before inserting and updating an entity. You can customize that and also trigger validation before removing an entity. I explained that in more details in my article.
You can use all features of the Bean Validation specification, including custom validation rules, to validate your entity attributes. I used that here to validate that the value of an entity attribute is within a defined range and here to check that only one out of 2 associations is set.
The example mapping that you posted in your question is a very good practice!
The #Column(nullable = false) part is not strictly necessary because the validation rule already ensures that the attribute can't be null.
Since Hibernate also have their own validation annotations, for example #NotBlank, I don't think it's a bad practice to use javax.validation.constraint here. As far as I know, Hibernate even tries to consider all of these annotations.
So for example a field annotated with #NotNull will not be nullable in the generated table (so adding nullable = false is redundant), a String field annotated with #Size(max=2047) will be a varchar(2047) in MySQL instead of the default varchar(255).
This can be useful to read: http://hibernate.org/validator/
The whole reference docs for the project: https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#preface
EDIT: Based on Thorben Janssen's answer, the rest of my original answer below this can be discarded :)
I'm unsure if some more complicated constraints (for example a regular expression for phone numbers) are automatically enforced at the data layer or not. For example if you have a #Pattern for your phoneNumber field, that will work when your input is deserialized into your object. But if your setter methods dont have the same validation constraints, you might have an object in memory from some source with an incorrectly formatted phoneNumber that could be saved to the database. The safest way to use these constraints would probably include using programmatic validation with Validator.validate() before your database saves and updates.
Since Hibernate also have their own validation annotations, for example #NotBlank, I don't think it's a bad practice to use javax.validation.constraint here. As far as I know, Hibernate even tries to consider all of these annotations.
So, for example, a field annotated with #NotNull will not be nullable in the generated table (so adding nullable = false is redundant), a String field annotated with #Size(max=2047) will be a varchar(2047) in MySQL instead of the default varchar(255).

Is is possible to create a combo-annotation which combines multiple field annotations?

I have some boolean fields in my JPA entities which are annotated in the following way:
#Column(length = 1)
#Type(type = "yes_no")
private final boolean myField;
Is it possible to create a combo-annotation (e. g. MyAnnotation) which combines both of this annotations?
#MyAnnotation
private final boolean myField;
How?
Obviously you could create an annotation that provides the equivalent of multiple other annotations.
Equally obviously no JPA provider will support it, since they will check for the javax.persistence annotations only (not that #Type is javax.persistence).
What you want is similar to CDI stereotypes - unfortunately, JPA does not support such a concept, therefore you must copy recurring annotations all over.
If you can afford to wrap your field into an object, you may mark it as #Embeddable and put your field into it - the annotations on that field will be copied wherever you embed that object into an entity. You may extend the annotations using #AnnotationOverrides. Obviously, the drawback of such solution is additional complexity when accessing the field in your entity.

How to migrate a Hibernate NamingStrategy to (Implicit|Physical)NamingStrategy? Where is the documentation?

The NamingStrategy was already being marked as deprecated in Hibernate 4.2/4.3 (HHH-7079). Starting with Hibernate 5, now it will shipped with two replacements(?) interfaces ImplictNamingStrategy and PhysicalNamingStrategy (HHH-7078) and have finally ditched support for the old NamingStrategy. That's why Spring's upcoming Hibernate5 supported has even removed the configurer namingStrategy() and favor of implicitNamingStrategy() and physicalNamingStrategy(). So far, so good.
Although it is mentioned in some documents (i.e. in the incomplete working-5.0-migration-guide.md) and in (generated) release notes for the upcoming Hibernate 5 (as of today), I've found no concrete example how to use these actually.
Perhaps I've missed something, but neither the JavaDoc nor the issues shows any evidence of the idea both strategy types. Furthermore I've already one strategy based on NamingStrategy: a custom OracleNamingStrategy which is based on the well-known one.
While I'm interested in a proper solution in code (obviously), the actual issue is getting a working migration document and/or the conceptual idea of the restructured naming strategy.
Also related:
ImprovedNamingStrategy no longer working in Hibernate 5
Put below key value pair in your hibernate configuration file
hibernate.implicit_naming_strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl
hibernate.physical_naming_strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
If you are providing #Table and #Column annotation in your entity classes with names provided with an underscore i.e. user_id i.e. #Column(name="user_id"), it will take the column name as user_id; if you give it as userid then it will change to user_id if you use no strategy or implicit strategy (specifically spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl). So, if you want a strategy where the entity attribute name changes to one with underscore and lowercase letters i.e. something from userId to user_id, you should use implicit or no strategy (which actually uses implicit strategy).
If you don't want your naming strategy to add an underscore to the column name or class name, then the strategy that you need to use would look like:
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl. The things that you provide in annotations #Table and #Column’s name attribute would remain as it is.
If you don't want to provide annotations and want to manually handle the table name and column names, you should extend the class org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl and override the required methods. If you still use annotations for some of the cases here, remember the overridden methods will apply on the names written in those annotations.
spring.jpa.hibernate.naming.physical-strategy=example.CustomStrategy

Combine annotations in Java

How can I combine annotations in Java?
EDIT I was asking if I two annotations a and b, can I combine to a single annotations c?
If possible, how do I do that?
You cannot combine the annotations by e.g. annotating the annotations, unless the annotation consumer will process the meta-annotation tree explicitly. For example, Spring supports such feature for #Transactional, #Component and some other annotations (you may wish to have a look at SpringTransactionAnnotationParser#parseTransactionAnnotation()). Nice to have this feature in Java core, but alas...
However you can declare the common parent class that has a set of annotations you need and extend it. But this is not always applicable.
Assuming you want to have multiple annotations on a single element, you can just list them in sequence.
The Wikipedia page on Java annotations has quite a few useful examples, e.g.
#Entity // Declares this an entity bean
#Table(name = "people") // Maps the bean to SQL table "people"
class Person implements Serializable {
...
}

Categories

Resources