Forcing validation annotation to provide a message - spring-boot

I am using hibernate validator to do POJO validation, and also i have created some custom ones. Here is an example:
//lombok annotations
public class Address {
#NotNull // standard
#State //Custom created
String country;
}
We have a requirement to represents all the validations errors with specific codes rather than messages. In order to achieve this we have decided to specify codes in every annotation that we use. The above example now looks like this:
//lombok annotations
public class Address {
#NotNull(message="ERR_001")
#State(message="ERR_002")
String country;
}
But we have a problem with this approach. We could not enforce to provide a message(error code in our case) all the time in an annotation. For custom annotation, it is still ok as we do not provide a default message, but for the standard ones there is chance to miss it and a string message will silently generated if we accidentally miss to provide a custom message.
Is there a way to enforce to provide message all the time in the annotation. It will probably help to have some consistency.

To my knowledge no, there is no way to do that. Maybe your best option is to create your own annotation and make the attribute mandatory.

Sevntu-Checkstyle provides additional checks to Checkstyle, including a check that an annotation is used with all required parameters.
<module name="RequiredParameterForAnnotation">
<property name="annotationName" value="NotNull"/>
<property name="requiredParameters" value="message"/>
</module>

I could not find a good way to handle it. But for now i have implemented a test which give us some control over it. Its not the best solution but solves the issue for now.
I am using classgraph to read all the annotations on POJO classes inside a package and filtering it on javax validations and if the default messages appears to be from javax.validation, then i am adding to a list.
Later on a unit test, i am checking if this list is empty or not.
private List<String> getAnnotationProperties(String appliedOn, AnnotationInfoList annotationInfos) {
return annotationInfos.stream()
.filter(annotationInfo -> annotationInfo.getName().contains("javax.validation.constraints"))
.filter(annotationInfo -> ((String) annotationInfo.getParameterValues().getValue("message")).contains("javax.validation.constraints"))
.map(annotationInfo -> annotationInfo.getName())
.collect(Collectors.toList());
}

Related

How to handle optional service dependency of service in Spring Boot?

I've a service called InformationService. It optionally depends on ReleaseService. If the property external.releaseservice.url is set, the InformationService shall make a request to it and enrich it's own response with aggregate data.
If however the url is not defined, the response shall simply return a string like not available for the fields in question.
What's the spring boot way to achieve this? Inject an Optional<ReleaseService> into the InformationService? Is there another pattern for this?
You have three ways to achieve this.
#Autowired(required = false)
This works, but it requires field injection, which is not great for unit tests as is well known.
#Autowired(required = false)
private ReleaseService releaseService;
Java Optional type
As you said, Optional will also do the job and it allows you to stick to constructor injection. This is my suggested approach.
Spring's ObjectProvider
There is also an ObjectProvider designed specifically for injection points which you can use to achieve this as follows.
public InformationService(ObjectProvider<ReleaseService> releaseServiceProvider) {
this.releaseService = releaseServiceProvider.getIfAvailable();
}
It is more cumbersome and therefore I would avoid it. There is an advantage that allows you to specify a default instance if none is available but I guess that is not what you need.

Can MongoTemplate provide automatic translation?

I have a simple persistent pojo like:
public class Peristent {
private String unsafe;
}
I use Spring Data mongoTemplate to persist and fetch the above object. I also need to encrypt the Persistent.unsafe variable and store a complex representation of that in backend, everytime I try to save Persistent object.
Can I annotate Persistent, or provide some sort of hooks where I can make the aforementioned translations without me having to do that in the Pojo code manually. This has to happen automatically during mongoTemplate.insert.
Spring Data currently only support Type based conversions. There is an issue for supporting property based conversion, which you might want to track.
Therefore annotating won't work. What you could do is, create use a separate class for the property, which just wraps the String and register a custom converter for that type. See http://docs.spring.io/spring-data/data-mongo/docs/1.10.4.RELEASE/reference/html/#mongo.custom-converters for details, how to do that.

Update field annotated with #Value in runtime

Let's imagine we have such a component in Spring:
#Component
public class MyComponent {
#Value("${someProperty}")
private String text;
}
If we define the property placeholder:
<context:property-placeholder location="classpath:myProps.properties"/>
And myPropos.properties contains the value for someProperty the value will be injected to the text field when the context is initialized. That's quite simple and easy.
But let's say that I have a service that enables user to change the value of the someProperty:
public void changeProp(String name, String newValue);
Is there a chance I can re-inject the newValue to text field. I mean it should be quite straight forward.. Basically it's nothing different than the after-initialization injection. I can not imagine that Spring does not have support for this? Can I fire some event or something?
I could do this on my own basically, but I wander is it maybe something there already? If not does anyone know what Spring class is in fact handling the injections at the first place? I could probably reuse the code there do perform this on my own if a solution does not exists.
I expect spring does not have a support for this, because the normal injection is done while creating the bean, but not will it is put in service.
Anyway: in this blog entry "Reloadable Application Properties with Spring 3.1, Java 7 and Google Guava", you can find the idea for an solution.
The key idea is to use a post processor to build a list of all fields with property fields. And if the properties are changed on can use this list to update the fields.

Bean Validation for POST requisition in JAX-RS with Jersey implementation

I'm using the Jersey implementation for JAX-RS, and I was looking for an example where I can use the Bean Validation in POST requisitions. I have this operation, for example:
#POST
#Path("document/annotations/save")
#Produces("application/json")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Map<String, Object> saveAnnotation(
#FormParam("user") String userStr,
#FormParam("documentId") String documentId,
#FormParam("documentPage") Integer documentPage,
#FormParam("annotationContent") String annotationContent,
#FormParam("annotationId") Long annotationId,
#FormParam("isMobile") Boolean isMobile) { // the code... }
I wanna use validations constraints (#NotNull, #Pattern, etc) for each method param. I saw this doc where they're using the Seam Framework to do that.
Currently, I'm trying to use the javax.validation implementation to validate my requests, but it doesn't working.
Is there a way to use the JSR-303 specification with JAX-RS?
Tnks.
This is currently not possible using Jersey; one possible alternative is to write a customer resource filter and bind to the #NotNull, etc. annotations.
It would be simpler if it was encapsulated in a resource class because you could then bind to a #Valid annotation on your method and validate the bean in one shot.
Because JSR-303 is designed to deal with beans and not a collection of parameters then it ends up being very verbose when you try to bend it to your will.
IMHO it's better not to keep validation inside your class anyway and to either use the pipes and filters pattern, i.e. ContainerRequestFilter, or to use something like AspectJ as #Willy suggested.
It's possible. See docs for latest Jersey
https://jersey.java.net/documentation/latest/bean-validation.html#d0e9380
https://jersey.java.net/documentation/latest/bean-validation.html

Can I inject code in spring using AOP annotations?

Is it possible to do something like the following:
public void doStuff(#RequirePrivilege("foo") User user) {
// ...
}
and have it effectively run as if it were the following?
public void doStuff(User user) {
if(!user.hasPrivilege("foo"))
throw new UserHasInsufficientPrivileges(); // this is a RuntimeException
// ...
}
I know that Spring has various sorts of AOP support, but the best I could find was AOP code which was annotated so that it would execute before or after a specific method. I want to do the inverse and annotate the code that should be changed.
Ultimately I could just do the above check inside the method, but the annotation way of doing things provides additional documentation which makes it obvious that the user requires a particular privilege without having to keep the documentation in sync with the code.
You can look at using AspectJ for doing this, as it will match on annotations. You can then use an around aspect to decide if the user meets the requirements to use this method.
Spring allows you to use AspectJ, and I would suggest that if possible you not do this at run-time, but at compile-time, as there is no reason to pay the price for using this aspect whenever you start the application. But, if you must do it at run-time then that is doable, to me I try to use compile-time as much as possible.
You may want to look at AspectJ In Action (http://www.manning.com/laddad2/) but here is an example from there:
Signature pattern:
* *(#RequestParam
(#Sensitive *))
Description
*Any method with one parameter marked with the #RequestParam annotations and the parameter’s type is marked with the #Sensitive annotation.*
Example
void create(#RequestParam
MedicalRecord mr), assuming
MedicalRecord carries the
#Sensitive annotation.
I'm certain that your "insufficient privileges" example can be done with Spring AOP, because that's how Spring Security works. You can do some very sophisticated things with around advice and AspectJ.

Resources