Where is implementation of #Future defined? - java

Java persistence & hibernate make it easy to add property-level constraints to entities.
#Entity
#Table(name = "party")
public class PartyEntity {
#Future
public DateTime start;
}
The javax.validation.constraint.Future annotation is defined without a specific implementation.
#Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
#Retention(RUNTIME)
#Documented
#Constraint(validatedBy = {})
public #interface Future {
// ...
}
Where is actual validation implemented? How can this be extended to allow an administrator override?
Though not shown here, I am already using groups for another purpose on this constraint.

Implementations for many validators supplied by hibernate-validator: http://docs.jboss.org/hibernate/validator/5.0/reference/en-US/html/validator-usingvalidator.html#validator-defineconstraints-builtin
If you are using Maven just add following dependency to pom.xml file:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.0.0.Alpha1</version>
</dependency>
How can this be extended to allow an administrator override?
The simplest way is to write your own instead.

JSR 303 validation does not have too much directly to do with JPA. Of course also JPA entities can be validated with it. What it comes to actual question - most likely you want to follow php-coder's advice and implement new annotation and validation of contraints set via annotation usage.
If because of some mysterious reason you really have to change how Future annotation is processed in your implementation, then solution is of course implementation specific. Assuming that you use Hibernate Validator 4.3, actual check of validation constraint takes place in:
org.hibernate.validator.internal.constraintvalidators.FutureValidatorForDate
org.hibernate.validator.internal.constraintvalidators.FutureValidatorForCalendar
How these implementations get picked can be affected in org.hibernate.validator.internal.metadata.core.ConstraintHelper. I suggest to attach sources of implementation you use to your IDE, because then it is easy to navigate to this kind of details.

Related

Spring validation: method parameter constraint not called

everyone.
So, I have a SpringBoot application with a controller that has several methods, taking the following POJO as a parameter:
package com.example.dto;
import lombok.Data;
#Data
public class MyEntity {
#NotNull
private String fieldA;
private String fieldB;
}
For one of the controller endpoints I would like to apply additional validation logic, so in the validation.xml I add the following:
<constraint-mappings>
<bean class="com.example.controller.SampleController" ignore-annotations="false">
<method name="doFoo">
<parameter type="com.example.dto.MyEntity">
<valid />
<constraint annotation="com.example.validation.ValidEntity" />
</parameter>
</method>
</bean>
</constraint-mappings>
com.example.validation.ValidEntity is the constraint annotation I would like to apply.
My problem is that this additional constraint is only invoked if #NotNull checks defined in MyEntity have passed successfully. If fieldA is null, ValidEntity constraint is ignored, and the client receives an imcomplete validation result. What am I missing?
I'm not entirely sure about this because I've never worked with the validation.xml file.
However, I would say that Spring is first creating the object and then applying the validations. The #NotNull validation is performed in the creation of the instance. This means that if that validation fails the construction will throw an exception and Spring won't even try to check your constraint (which makes sense in my opinion).
I think you can "fix" it by creating an annotation with your constraint and using it in your class. If I'm right, both annotations will be checked and the thrown exception will contain all errors.
It's just a guess. Let me know if it works.
I don't know if there is an easy way to configure the validator to aggregate constraint violations from both annotation and XML configurations when first or both fails.
As demonstrated by your code Hibernate Validator can work with mixed annotation and XML configurations, but the lack of documentation for that specific case is a hint that it is at least not recommended.
When XML configuration file is used, it takes precedence over annotations by default. ignore-annotations is used to overcome this (text highlight is mine):
Setting ignore-annotations to true means that constraint
annotations placed on the configured bean are ignored. The default for
this value is true. ignore-annotations is also available for the nodes
class, fields, getter, constructor, method, parameter, cross-parameter
and return-value. If not explicitly specified on these levels the
configured bean value applies.
Using Hibernate Validator to Cover Your Validation Needs article states that:
The default for a field is ignore-annotations=”false”. This means
that by default annotations for a field are stronger (this is of
course after you indicated that that the bean itself wont ignore
annotations). If you wont that the XML will be stronger than you have
to indicate that by ignore-annotations=”true”
It seems possible to disable annotation configuration for a specific field which is configured in XML.
Another solution to switch between annotation and XML configuration is to use Grouping constraints.
I'm not sure if anything of the above is of any use for you, but if it is possible I would probably switch to a single configuration (XML, assuming that annotation config comes from external library you cannot modify) and enforce it everywhere instead of relying on undocumented features.

How to extend non-modifiable model to use with JPA?

What's the best practice to create persistence (say via Spring Boot or just JPA or Hibernate itself) for a data model coming from a non-modifiable dependency? Typical limitations like not being able to override a field or what patterns like Decorator allow and what not slowed my progress down. I tried some things, but I always end up with the result that it would be necessary to either modify the source model (like adding annotations to make it natively compatible -> the fork I don't want) OR write a ton of wrapper code which would replicate the original model too much - but even this isn't working right now:
I tried
Creating a JpaRepository for the original class. Doesn't work, because casting the extended class to its parent class is not working.
Extend the original class with a custom class that gets necessary annotations like #Entity can be used in such a repository. But problems here were
that the original class is missing an #Id annotation, which could be fixed by using a new ID in the extended class, but
the given model also has a non-simple architecture, including lists of other classes that are part of the model itself. So other annotations like #ElementCollection might be necessary, which can't be added because overriding of fields is not possible.
Hiding it with creating a new field with the same name in the new class is not working:
An error like Could not determine type for: java.util.List, at table: yeah_this_one, for columns:[org.hibernate.mapping.Column(objects)] indicates that the original field can't be hidden completely (changed table and column name in new class to verify that).
So of course adding #ElementCollection (which is said to solve that) isn't helping here, too.
#AttributeOverride is also not working to override annotations to set the ID or other settings, only the name and column can be changed.
I'm stuck at this state and am wondering if this is even the right approach at all.
The setup or what I would expect to work from my understanding:
The general idea is based on this Spring Boot REST tutorial, which I tried to expand with a model from a dependency.
Let's assume there is the original model class Model from a dependency that can not be modified. The ModelEntity would be the extended class to act as way to pull the model into Spring persistence.
In the scope of the dependency the original class would be like:
// Given dependency, not modifiable
#Some existing annotation
public class Model extends AnotherClassFromDep {
#more annotations
private IdLikeClassFromDep modelId;
//more complex attribute
#Nullable
private List<RefClassFromDep> objects = new ArrayList<>();
// more attributes, getter, setter etc.
}
In the scope of my program:
In combination with this little additional orm.xml it is possible to annotate the original Model as MappedSuperclass without modifying it (according to https://stackoverflow.com/a/2516951/1844976).
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" version="1.0">
<mapped-superclass class="package.name.of.original.Model">
</mapped-superclass>
</entity-mappings>
This allows to create a class like this, which extends the original POJO model to add JPA annotations:
#Entity
public class ModelEntity extends Model {
// some #Id attribute is necessary, which should correspond to
// the already existing ID attribute from the original `Model`
// in the best case, but an additional one would work too
private #Id #GeneratedValue Long id;
// Different approaches to solve the List error from above, for
// instance hiding the original attribute
#ElementCollection
private List<RefClassFromDep> objects;
public ModelEntity(){
super();
}
}
At the current state the issues are blocking me from going further. But, altogether I would expect this to work with a JpaRepository:
// of course, creating a JpaRepository with original `Model` wouldn't
// work, because it has no `#Entity`
public interface ModelRepository extends JpaRepository<ModelEntity, IdLikeClassFromDep> {
}
In a way that actually accessing it like that is possible:
#Configuration
public class LoadDatabase {
#Bean
CommandLineRunner initDatabase(ModelRepository modelRepository) {
return args -> {
// depending on the implementation above, either create a
// Model and cast it or directly create a ModelEntity, set
// attriubtes and save it through the JpaRepository
modelRepository.save(model);
};
}
}
Both more abstract and specific code-related ideas and comments would help me. Thanks!
In the old days, Jpa/Hibernate were configured via XML.
You needed to provide persistence.xml for general configuration. In this file, you added <mapping-file> tag pointing to another file orm.xml In this file you configured mapping for your entities (which is done via JPA annotations these days).
See https://vladmihalcea.com/how-to-use-external-xml-mappings-files-outside-of-jar-with-jpa-and-hibernate/
While the methods described above are considered legacy, they are still supported. LocalContainerEntityManagerFactoryBean has method setMappingResources allowing you to point to the orm.xml file. There is some funkiness about search paths and default locations, but it is well documented:
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.html#setMappingResources-java.lang.String...-
Note that the third-party class you are configuring this way needs to conform to Java Beans conventions (no-args constructor, getters and setters)

When to use Bean Validation vs a customized validation framework?

I am validating fields of my Data Access Object classes. In one attempt, I have started adding Bean Validation annotations to the properties (#NotNull, #NotBlank, #Min, #Max and so on). I also have more annotations Jackson (JsonProperty (..)) for swagger library and documentation (#Api (...)). In my opinion the class was very "dirty" with many annotations (each property has at least three annotations). Example of one field:
#JsonProperty("ownName")
#Api(description="it is my own name" required=true)
#Valid
#NotNull
private SomeObject object;
In another attempt, I have performed my own validation with the Spring Validator interface. If a custom validator such as the Spring Interface is used it seems to be cleaner and also allows you freedom to generate more than one validator for different situations. Also, the class does not seem to be so overloaded with annotations and validations are independent of the class. Example of Validator:
public class UserValidator implements Validator {
#Override
public boolean supports(Class<?> arg0) {
return User.class.isAssignableFrom(arg0);
}
#Override
public void validate(Object obj, Errors error) {
User user = (User) obj;
if(user.getPassword().length() < 10)
{
error.reject("Password must be lesser than 10");
}
//more validations....
}
}
When would you use one or another?
What are the pros and cons of each?
I think it is a matter of taste and use case. I agree that sometimes it feels one ends up in some sort of annotation overload.
Some reasons for using Bean Validation are that it is a standard. The constraint annotations are standardized and many frameworks integrate with it, for example JPA in case you want to add yet another annotation based framework ;-)
Using something like Spring binds you to a specific library/framework. Your code will be less portable. If you of course never see a scenario where you would leave Spring behind, this might not matter.
Of course you could do something home grown altogether, but in this case you need to write the whole integration code into for example Spring, REST, JPA, etc.
Also writing a general purpose validation framework is not trivial. There are many things to consider.

JSR303 Hibernate dynamic validator

I'm new to hibernate validator
I would like to have one annotation and many implementations. Problem is, that annotation should be placed in domain (api) module and implementations in corresponding implementation modules (xx-command, xx-query). So the parameter validatedBy of #Constraint annotation has to be empty.
Can I somehow dynamically tell to hibernate to use all implementations of specified annotation which can pass type which I need. Also I would like to have implementations in more than one submodule.
#Target({FIELD, PARAMETER})
#Retention(RUNTIME)
#Documented
#Constraint(validatedBy = {})
public #interface CanNotExists {
String message() default "com.foo.api.domain.validation.annotation.CanNotExists.message";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
this is my project structure (in dependency order accessor-command depends on accessor-query, accessor-query dependes on infrastrucutre ...)
-api
-infrastructure
-accessor-query
-accessor-command
I found this question and wanted to use xml configuration (see the edit section in answer), but it's not helpful because I would like to use implementation in many modules >>> as mentioned here
A given entity can only be configured once across all configuration files. The same applies for constraint definitions for a given constraint annotation. It can only occur in one mapping file. If these rules are violated a ValidationException is thrown.
So I can't split constraints to multiple xml configurations.
Basic need of this validator is to look into repository and validate if specified object already exists. I'm also using spring in my project so if somebody have better approach how to do this (even with spring or another framework), it will be welcome.
Thanks
Your question is tagged with 'spring', so may be you can use springs validation that under the hood uses hibernate :
[spring validation][1]
Let your validator implement the interface spring Validator, create a bean of it, thats it.

Programmatic Bean Validation (JSR 303) without Annotation [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
using Hibernate Validator without calling annotation.
I have this composite constraint annotation (only for illustration):
#Target... #Retention...
#Constraint(validatedBy = {})
#Pattern(regexp = PasswordComplexity.AT_LEAST_TWO_NONE_ALPAH_CHARS)
#Length(min = 6, max = 20)
public #interface PasswordComplexity {
...
}
And I use it in Spring Controllers and Entity Classes.
But now I need to check a single String in a Service method, where I need to apply the same constraint to a single String. Because of the fact that the constraint is the same, I want to use the same definition of the constraint (#PasswordComplexity) (single source of truth). Something like:
public void createUser(UserDto userDto, String password) {
if(hasViolation(validator.validate(password,PasswordComplexity.class))) {
throw new PasswordComplexityViolationException();
} else {
…
}
}
But I do not know how to run the JSR 303 Validator for an not annotated simple object (String). Is it at least possible, and how?
(I use Hibernate Validator as JSR 303 provider)
One way to do this would be write a full custom validator, and push the logic down into that class having the annotation just use the validator. This would mean you then had an independent compilation unit (A full class PasswordComplexityValidator implements implements ConstraintValidator<PasswordComplexity, String> ...) which you could use independently of the annotation. This approach would also make it easier for you to unit test the validation.
However, since you are using the annotation as a way of configuring the existing regex validator provided by Hibernate, you could use that one instead, passing it the constant pattern from the annotation class. You should also be able to package your length constrain into the regex too, which would be simpler and faster than having both annotations anyway.

Categories

Resources