Java ConstraintValidator Purpose - java

I am trying to understand the purpose of Java's ConstraintValidator interface.
It's an interface, however how does it make coding more quick or more efficient? Trying to understand benefits of using it with our team.
From Baeldung's Spring MVC Custom Validation:
The validation class implements the ConstraintValidator interface, and
must also implement the isValid method; it's in this method that we
defined our validation rules.
Naturally, we're going with a simple validation rule here in order to
show how the validator works.
ConstraintValidator defines the logic to validate a given constraint
for a given object. Implementations must comply with the following
restrictions:
Code Example:
public class ContactNumberValidator implements
ConstraintValidator<ContactNumberConstraint, String> {
#Override
public void initialize(ContactNumberConstraint contactNumber) {
}
#Override
public boolean isValid(String contactField,
ConstraintValidatorContext cxt) {
return contactField != null && contactField.matches("[0-9]+")
&& (contactField.length() > 8) && (contactField.length() < 14);
}
}

The purpose is to define custom validation-logic for a custom annotation.
Purpose of ConstraintValidator
In the given example the ConstraintValidator implementation can be used as annotation on your property (assuming ContactNumberConstraint is a public #interface, defined as annotation for fields):
#ContactNumberConstraint
String contactField;
As such shorthand it combines several validations like otherwise have to be listed separately:
#NotNull // contactField != null
#Pattern(regexp="[0-9]+" ) // contactField.matches("[0-9]+")
#Length(min=9, max=13) // (contactField.length() > 8) && (contactField.length() < 14)
String contactField;
Here the implemented ConstraintValidator is used to validate the property, for example if used as parameter (in a REST-controller, or any other validated method).
How does it make coding more quick or more efficient?
With this pair of annotation and validator you can simply declare a rather complex validation at any field or class by just annotating the field - by adding one line. Spring would care about initiating the validation. It executes the logic defined in validator and handles errors.
This predefined validation component as pair of annotation-interface and validator can be reused easily at many places (reduce code duplication), it can be composed and allows giving complex validations a name (using an expressive annotation name). Through its declarative way (annotation) it is loosely coupled.
More on benefits of Java Bean Validation (JSR 303, 380)
See also
Validation in Java Applications - DZone Java
Java Bean Validation Basics | Baeldung

Related

How do you figure out whether a CLASS is a spring proxy?

In a nutshell
In the AopUtils, we have
/**
* Check whether the given object is a JDK dynamic proxy or a CGLIB proxy.
* <p>This method additionally checks if the given object is an instance
* of {#link SpringProxy}.
* #param object the object to check
* #see #isJdkDynamicProxy
* #see #isCglibProxy
*/
public static boolean isAopProxy(#Nullable Object object) {
return (object instanceof SpringProxy && (Proxy.isProxyClass(object.getClass()) ||
object.getClass().getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)));
}
In now want to check whether a bean class is proxied without instantiating the bean (i.e. just with its class) in a BeanFactoryPostProcessor.
I thought I could just "translate" above method:
private fun <T> isAopProxyClass(candidate: Class<T>): Boolean {
return SpringProxy::class.java.isAssignableFrom(candidate)
&& (
Proxy.isProxyClass(candidate)
|| candidate.name.contains(CGLIB_CLASS_SEPARATOR)
)
}
But this does not detect proxies because SpringProxy::class.java.isAssignableFrom(candidate) is false even for obviously proxied classes.
How do I make this work?
Full picture
I'm in a BeanFactoryPostProcessor and I need the un-proxied bean classes to access certain annotated methods by reflection.
Access happens in a lambda function that will first use the ApplicationContext to retrieve the bean for the class. The bean must not be forcibly instantiated in this BeanFactoryPostProcessor (and in fact should throw an exception if it does because some beans are session-scoped).
Interesting question. 😀
The three classes highlighted in your screenshot are CGLIB proxies but not AOP proxies. Look at their class names: They are all Spring configuration classes. But that does not make them normal Spring proxies, especially not AOP proxies. For the difference between #Component and #Configuration, also with regard to proxying and self-invocation behaviour, please read my answer here.
Consequently, a Spring #Configuration class also does not implement SpringProxy like normal Spring proxies.
So basically your solution works just fine, no need to worry, as far as I can see.
P.S.: I am a Java guy, not a Kotlin person. So I re-implemented your code from the screenshot in Java, so I could debug into it and reproduce your situation. But even in Kotlin I would have had to re-type everything. Please next time publish the code as copyable text, not just as an image.
Update: If you check something like the content of
beanClasses.stream()
.filter(aClass ->
aClass.getName().contains(CGLIB_CLASS_SEPARATOR) &&
aClass.getSuperclass().getAnnotation(Configuration.class) == null
)
.collect(Collectors.toList())
you should see an empty collection, whereas
beanClasses.stream()
.filter(aClass ->
aClass.getName().contains(CGLIB_CLASS_SEPARATOR) &&
aClass.getSuperclass().getAnnotation(Configuration.class) != null
)
.collect(Collectors.toList())
should yield the same list of classes as simply
beanClasses.stream()
.filter(aClass -> aClass.getName().contains(CGLIB_CLASS_SEPARATOR))
.collect(Collectors.toList())
I.e. all remaining CGLIB proxies in beanClasses should in fact be configurations, not normal Spring proxies.
In now want to check whether a bean class is proxied without instantiating the bean (i.e. just with its class) in a BeanFactoryPostProcessor.
This task seems impossible to me since there are 100500 ways to proxy bean at runtime (bean post processor, advice, etc). Technically you can use random to decide whether to proxy some bean. You can have two instances of a given class (e.g. with different qualifiers), one proxied, other not.

Spring conditional annotations (NOT #Conditional)

Can you make Spring annotations conditional?
I mean for example having the following method:
#CachePut(value = "latestALLFXRatesCache", key = "#definition.key")
public AssetValueSnapshot refreshCacheLatestFXValue(DataSource definition) {
AssetValueSnapshot assetsnap = getLatestFXValueSnapshot(true,definition);
}
Can I make the #Cacheput annotation conditional (preferably with another spring annotation)?
For example:
if #Profile("XXX") or #Conditional(XXX)
#Cacheput
else
#Cacheable
public AssetValueSnapshot ...
Regardless whether this makes sense and knowing that #Profile and #Conditional are not made for this, can I do what I want with annotations or is there some other way in Spring?
Edit after comments:
I'm talking about a broader scope than just a specific annotation (cacheput in this case). I'm wondering if there is an annotation/other way that makes any annotation conditional; regardless of that annotations own conditional behavior.

Java design, calling the associated business logic/service

I have 3 objects, a DTO called BalanceDTO which implements a interface RequestDTO and a Balance Entity. I created the DTO because the entity I can't use, JAXB compliance (legacy code).
The DTO is used in the web service layer, BalanceService, and the Entity in the API I integrate to from the web service. Between the web service and the API there is validation. RequestValidation which has sub validations for each type of RequestDTO i.e. BalanceRequestValidation.
The validation component takes in a RequestDTO as a parameter and then needs to do validation for the specific component. At the point of input the validation component doesn't know which object has been passed to it i.e. BalanceDTO, it only sees the interface.
I want to avoid using instanceof so I was thinking of using a visitor on the DTO so that it delegates itself to the validation that needs to be performed on it.
But the validation needs more/other components as well not just the BalanceDTO as input parameters and different validations needs different input params.
Is there another way to know which object you are working with and the validation to choose without using instanceof? Another design that I can follow?
You are well on the right track here - the Visitor design pattern is often the best way to avoid downcasting.
I am going to suggest a combination of the visitor and delegation design patterns, though let's walk through some alternatives.
Having the object do the validation itself via the RequestDTO interface is not viable since you need different components and the validation is not trivial in nature.
Using instanceof and downcasting looks a little messy, and the compiler won't complain if you add a new validatable class and forget to add the validator - you'll be relying on a runtime error via ...else { throw new IllegalArgumentException("Unknown RequestDTO subtype!"); }
The visitor design pattern is the classic way to avoid downcasting plus it also gives you a compiler error if you add a new class that should be validatable and forget to add the validation.
You can use accept() and visit() methods, or you can use method naming that is closer to your domain, e.g. validate(), like this:
public interface RequestDTO {
boolean validate(RequestValidation validator);
}
public class BalanceDTO implements RequestDTO {
// ...
#Override
public boolean validate(RequestValidation validator) {
return validator.validate(this);
}
}
public class RequestValidation {
// components...
public boolean validate(BalanceDTO balanceDTO) {
return true; // todo...
}
public boolean validate(AnotherDTO anotherDTO) {
return true; // todo...
}
}
If you want to go a bit further you can delegate the validation to specific validation components, like this:
public class RequestValidation {
BalanceRequestValidation balanceRequestValidation;
AnotherRequestValidation anotherRequestValidation;
public boolean validate(BalanceDTO balanceDTO) {
return balanceRequestValidation.validate(balanceDTO, a, b, c);
}
public boolean validate(AnotherDTO anotherDTO) {
return anotherRequestValidation.validate(anotherDTO, x, y, z);
}
}
Given I have understood your problem correctly, the visitor design pattern, possibly combined with the delegation design pattern, is indeed a good approach.

Java - Custom/standard validation with Annotations

I'm using annotations in a project. The thing is i'm making custom validation that (partly) depends on annotations. I'm also making own annotations, but I want to use as much as I can from the JSR 303 standard.
to check if a field 'passes' the annotation constraints i've written some methods. Example:
static boolean isNotNullValid(Field f){
boolean valid = true;
if(f.isAnnotationPresent(NotNull.class)){
Object o = ObjectGetter.getFieldValue(f);
if(o==null){
valid = false;
}
}
return valid;
}
It's quite a lot of work to do this type of validation for all annotations. Is there some method i'm missing, like .isValid() ? I mean, of course, for the standard annotations.
Thanks in advance
You're not supposed to code that by yourself. You should instead rely on an implementation of the JSR, for example Hibernate Validator. The Validator it implements allows getting a set of constraint violations based on the annotations on the bean.

How to make Spring accept fluent (non-void) setters?

I have an API which I am turning into an internal DSL. As such, most methods in my PoJos return a reference to this so that I can chain methods together declaratively as such (syntactic sugar).
myComponent
.setID("MyId")
.setProperty("One")
.setProperty2("Two")
.setAssociation(anotherComponent)
.execute();
My API does not depend on Spring but I wish to make it 'Spring-Friendly' by being PoJo friendly with zero argument constructors, getters and setters. The problem is that Spring seems to not detect my setter methods when I have a non-void return type.
The return type of this is very convenient when chaining together my commands so I don't want to destroy my programmatic API just be to compatible with Spring injection.
Is there a setting in Spring to allow me to use non-void setters?
Chris
Thanks to all (and especially Espen who went to a lot of effort to show me the various options within Spring).
In the end, I found a solution myself that doesn't require Spring configuration.
I followed the link from Stephen C then found a reference to the SimpleBeanInfo class within that set of Threads. This class allows a user to write their own bean method resolution code by placing another class in the same package as the class with the non-standard setters/getters to override the logic of with 'BeanInfo' appended onto the classname and implementing the 'BeanInfo' interface.
I then did a search on Google and found this blog which pointed the way. The solution on the blog was quite basic so I padded it out for my purposes.
Per Class (with fluent setters)
public class MyComponentBeanInfo<T> extends SimpleBeanInfo {
private final static Class<?> _clazz = MyComponent.class;
PropertyDescriptor[] _properties = null;
public synchronized PropertyDescriptor[] getPropertyDescriptors() {
if (_properties == null) {
_properties = Helpers.getPropertyDescriptionsIncludingFluentSetters(_clazz);
}
return _properties;
}
public BeanDescriptor getBeanDescriptor() {
return new BeanDescriptor(_clazz);
}
}
PropertyDescriptor generation method
public static PropertyDescriptor[] getPropertyDescriptionsIncludingFluentSetters( Class<?> clazz) {
Map<String,Method> getterMethodMap = new HashMap<String,Method>();
Map<String,Method> setterMethodMap = new HashMap<String,Method>();
Set<String> allProperties = new HashSet<String>();
PropertyDescriptor[] properties = null;
try {
Method[] methods = clazz.getMethods();
for (Method m : methods) {
String name = m.getName();
boolean isSetter = m.getParameterTypes().length == 1 && name.length() > 3 && name.substring(0,3).equals("set") && name.charAt(3) >= 'A' && name.charAt(3) <= 'Z';
boolean isGetter = (!isSetter) && m.getParameterTypes().length == 0 && name.length() > 3 && name.substring(0,3).equals("get") && name.charAt(3) >= 'A' && name.charAt(3) <= 'Z';
if (isSetter || isGetter) {
name = name.substring(3);
name = name.length() > 1
? name.substring(0,1).toLowerCase() + name.substring(1)
: name.toLowerCase();
if (isSetter) {
setterMethodMap.put(name, m);
} else {
getterMethodMap.put(name, m);
}
allProperties.add(name);
}
}
properties = new PropertyDescriptor[allProperties.size()];
Iterator<String> iterator = allProperties.iterator();
for (int i=0; i < allProperties.size(); i++) {
String propertyName = iterator.next();
Method readMethod = getterMethodMap.get(propertyName);
Method writeMethod = setterMethodMap.get(propertyName);
properties[i] = new PropertyDescriptor(propertyName, readMethod, writeMethod);
}
} catch (IntrospectionException e) {
throw new RuntimeException(e.toString(), e);
}
return properties;
}
Advantages to this approach:
No custom spring configuration (Spring is not aware of the non-standard setters and sees them as normal). No dependancy on any Spring .jar files but accessible from Spring.
Just seems to work.
Disadvantages to this approach:
I have to place create a BeanInfo class for all of my API classes with non-standard setters. Luckily there are only around 10 such classes and by moving the method resolution logic into a seperate class I only have one place to maintain.
Closing Thoughts
In my opinion, Spring should deal with fluent setters natively, they don't hurt anyone and it should just ignore the return value.
By requiring that setters be rigidly void, it has forced me to write a lot more boiler plate code than I would have needed otherwise. I appreciate the Bean Specification, but bean resolution is trivial using reflection without even using the standard bean resolver so Spring should offer the option of its own bean resolver that will handle this situations.
By all means, leave the standard mechanism as the default, but offer a one-line configuration option. I look forward to future versions where this might be optionally relaxed.
Is there a setting in Spring to allow me to use non-void setters?
The simple answer is No - there is no such setting.
Spring is designed to be compatible with the JavaBeans spec, and that requires the setters to return void.
For a discussion, refer to this Spring Forums thread. There are possible ways around this limitation mentioned in the forum, but there is no simple solution, and I don't think anyone actually reported that they had tried this and that it worked.
Spring can also be configured with Java configuration.
An example:
#Configuration
public class Config {
#Bean
public MyComponent myComponent() {
return MyComponent
.setID(id)
.setProperty("One", "1")
.setProperty("Two", "2")
.setAssociation(anotherConfig.anotherComponent())
.execute();
}
#Autowired
private AnotherConfig anotherConfig;
#Value("${id}")
private String id;
}
You have a nice immutable object. You have actually implemented the Builder pattern!
Updated to respond to Chris's comment:
I guess it's not exactly what you want, but using properties files solves some issues. See the id field in the example above.
Else, you can use Spring's FactoryBean pattern:
public class MyComponentFactory implements FactoryBean<MyComponent> {
private MyComponent myComponent;
public MyComponentFactory(String id, Property propertyOne, ..) {
myComponent = MyComponent
.setID(id)
.setProperty("One", "1")
.set(..)
.execute();
}
public MyComponent getObject() throws Exception {
return myComponent;
}
public Class<MyComponent> getObjectType() {
return MyComponent.class;
}
public boolean isSingleton() {
return false;
}
}
With the FactoryBean, you shield the configuration from the object returned from the getObject() method.
In the XML configuration, you configure the FactoryBean implementation. In this case with <constructor-arg /> elements.
One simple suggestion, it is customary not to use setters, but the properties names themselves. So have a setter, and have another method for the builder:
component.id("MyId")
.property("One")
.property2("Two")
.association(anotherComponent)
.execute();
As far as I know, there is no simple switch. Spring uses the Beans convention, and expects a void setter. Spring works with beans at the property level via an instance of the BeanWrapper interface. The default implementation, BeanWrapperImpl, uses introspection, but you could create your own modified version that uses reflection to find methods matching your pattern.
EDIT: Looking at the Spring code, BeanWrapperImpl is hard-wired into the bean factories, there is no simple way to replace this with another implementation. However, as spring uses introspection, we can work on getting java.beans.Introspector to produce the results we want. Here are the alternatives in order of decreasing pain:
change the method signature on your setters to comply.
implement your own BeanInfo classes for each of your beans
Use reflection to plug dynamically generated BeanInfo classes into the introspector.
The first two options are probably not really options for you, as they involve quite a lot of changes. Exploring the third option in more detail:
To know which beans are being instantiated by spring, implement your own BeanFactoryPostProcessor. This gets to see all the bean definitions before they are used by the BeanFactory. Your implementation iterates over all the BeanDefinitions in the factor, and fetches the bean class from each definition. Now you know all the classes that are being used.
With a list of classes, you can set about creating your own BeanInfos for these classes. You use the Introspector to generate the default BeanInfo for each class, which would give you read-only properties for your properties with return value setters. You then create a new BeanInfo, based on the original, but with PropertyDescriptors referencing setter methods - your return value setters.
With new beanInfos generated for each class, you need to make sure that the Introspector returns these when asked for the beaninfo for your class. The introspector has a private Map that is used to cache beanInfos. You can get hold of this via reflection, enable access - setAccessible(true) - and add your BeanInfo instances to it - map.put(Class,BeanInfo).
When spring asks the Introspector for the BeanInfo for your bean class, the introspector returns your modified beanInfo, complete with setter methods mapped to your setters with return values.
As others have said, it's not just Spring-friendliness you risk losing. A non-void setter isn't really a setter as far as JavaBeans are concerned, and all sorts of other tools (validators, marshallers, viewers, persisters, whatever else you can dream up) will probably use Introspector and BeanInfo, which expect setters to be null.
With this in mind, how flexible is the requirement that they be called setX? A lot of fluent interfaces in Java use withX instead. If you're using Eclipse, you can probably create a code generation template to make X getX(), void setX(X x), and X withX(X x) for you. If you're using some other codegen tool, I can imagine adding withX fluent setter/getter methods would also be easy.
The with word seems a bit odd, but when you see it alongside a constructor it reads really well.
Request r = new Request().withEndpoint("example.com")
.withPort(80)
.withSSL(false)
.withFoo("My Foo");
service.send(r);
One such API is the AWS SDK for Java, which you can consult for examples. An off-topic caveat is that boolean getters may be called isX, but Boolean getters must be called getX.

Categories