Java validation of object with annotation directly - java

The conventional way of java validation is to define a class with properties and annotated with one or many validation constraint annotations such as #NotNull or #Future.
Is it possible to validate an object directly with validator constraint annotation without specifying a class. For example:
String a = "";
validator.validate(a, javax.validation.constraints.NotNull.class);

That's clearly not a use case for which Hibernate Validator has been designed.
What you would have to do is to create a ConstraintValidator from the constraint and the type of the object and then use the isValid() method. The entry point would be ConstraintValidatorManager.
It's an internal class so it's subject to change without warning, even in a micro version so I wouldn't recommend using it.

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.

#Transient not working in hibernate

I am using hibernate 4.1.9.
My code is
#Transient
private String ldapIdTemp;
package is
import javax.persistence.Transient;
Still in hibernate query, it is not working and putting the attribute in the query.
part of query snippet (assetasset0_.ldapIdTemp as ldapIdTemp16_0_, )
I am not sure what I am doing wrong.
Can you try creating setter and getter for the field and annotate the get method with #Transient, as follows:
private String ldapIdTemp;
#Transient
public String getLdapIdTemp() {
return ldapIdTemp;
}
public void setLdapIdTemp(String ldapIdTemp) {
this.ldapIdTemp = ldapIdTemp;
}
Much depends on how you "integrated" this field in your Entity or class hierarchy. Moreover, field vs. property-access could cause an issue for your setting. See this post for a detailed explanation.
In your case, I could imagine that you either:
mixed field and property-access in your entity inheritance strategy
use XML-based configuration for Hibernate in your application.
In both cases the JPA 2.0/2.1 specification clearly states in Section 2.3.1:
It is an error if a default access type cannot be determined and an access type is not explicitly specified
by means of annotations or the XML descriptor. The behavior of applications that mix the placement of
annotations on fields and properties within an entity hierarchy without explicitly specifying the
Access annotation is undefined.
Please check that your persistent Entity classes have either field OR property-based annotations.
Check the #Transient annotation fully qualified name.
It can be from either,
org.springframework.data.annotation.Transient or javax.persistence.Transient.
Try to use javax.persistence.Transient.

Getting value of attribute specified in JPA annotation

Assuming that I have some entity with a field annotated as follows:
#Column(name="title", length=255)
private String title;
how could I get the value of the 'length' attribute with Java?
Hibernate Validator (the reference implementation of the Bean Validation specification) can be used to do this type of validation without implementing your own annotation-based validator. Integration with JPA allows to execute the validation during the persist or update of an entity. It's an Hibernate project, but it can be used with other JPA providers like EclipseLink.
Using reflection try something like this.
Class<?> cls = Class.forName(name);
Annotation ety = cls.getAnnotation(Column.class);
int value1 = a.length();
Although this can be done with the code above. I don't recommend use reflections to do this at all.
Try to use JSR-303 and javax.validation.constraints, there are pretty easy to use.

org.apache.struts2.json.annotations.JSON doesn't show right format

My web application uses struts2-json-plugin-2.2.1
I have an action that exposes an object loaded from DB (through hibernate).
This object contain a java.util.Date field that is so annotated:
#JSON(format = "dd-MM-yyyy")
#Column(name = "DATA_CREAZIONE", nullable = false)
public Date getDataCreazione() {
return this.dataCreazione;
}
Instead of getting:
"dataCreazione":"15-02-2013"
I get this:
"dataCreazione":"2013-02-15T16:51:06"
In debug I notice that the org.apache.struts2.json.JSONWriter class doesn't find any annotation over the getDataCreazione method and that the proxy class is of the "$$_javassist" type rather than "$$EnhancerByCGLIB$$" as other cases...
In the same application I have a lot of this situations and the annotation works fine.
I don't understand what is the problem (or the difference) with other classes.
Do you have any suggestions?
You didn't specify name of the annotation attribute. By default annotations with empty names are not deserialized. For further references take a look at the Apache docs.
btw I confirm the origin of my problem. As I said before it resides in the proxy class that are used. In my case - if I load the object (through hibernate) then the proxy used is $$_javassist - if I get the object (through hibernate) then the object isn't proxied and then JSonWriter can resume the annotation -> so it's able to format as I have annotated –

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