Situation: you have module with DTO objects used in your API, so that other project(s) can reuse then when sending requests. These DTO classes does have bean-validation annotations in them. And you would like to use your custom validations to validate DTO "arriving" via requests. The sender typically does not validate outgoing data, IIUC, and might not be interested in importing validators along with annotations.
Problem(?): bean-validation is defined in a way, where annotation defines who implements it (which is incorrect and it should be otherwise around imo), with possibility to specify empty array as annotation validator (seems like hack) and then pairing is done via manual hashmap manipulations instead of stuff like service loader etc.
How do you do this?
Would you split annotation and it's validator in separate modules?
How would you bind them together? I think it should be possible to use {} as validator and then use org.hibernate.validator.internal.metadata.core.ConstraintHelper#putValidatorDescriptors to bind them together, but I did not test it yet + maybe there is better way...
I agree that the annotation defining the validator does feel backwards. While not ideal, I've been able to work around this by separating my custom ConstraintValidator into an interface and implementation.
Example:
In api module define constraint and interface validator
#Constraint(validatedBy = MyConstraintValidator.class)
public #interface MyConstraint
{
}
public interface MyConstraintValidator
extends ConstraintValidator<MyConstraint, String>
{
}
In your service module define the implementation
public class MyConstraintValidatorImpl implements MyConstraintValidator
{
private FooService foo;
#Override
public boolean isValid( String value, ConstraintValidatorContext ctx)
{
// Implement your constraint logic
}
}
I we need to separate interface class and validator implementation into separate modules, it's possible. And even in a way, which I said in original question, that should be used. In API module you declare validation for example as:
#Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
#Retention(RUNTIME)
#Documented
#Constraint(validatedBy = {})
#SupportedValidationTarget(ValidationTarget.ANNOTATED_ELEMENT)
#ReportAsSingleViolation
public #interface AnyUuid {
//...
notice validatedBy = {}. The validator implementation looks like:
public class AnyUuidValidator implements ConstraintValidator<AnyUuid, Object> {
//...
and pairing can be setup using service loader(see javadoc if you don't know how that works). Put into file META-INF/services/javax.validation.ConstraintValidator FQDN of AnyUuidValidator shown above. And all other custom validators. And that should be it.
There is a bug I found with this. If I'm not mistaken. If you have DTO you cannot change (~annotate with constraints) and still want to validate them via bean validation, you can register validation definitions via xml file. If you are doing so and use service loader for pairing definition and implementation of custom validators, there is probably some bug and your custom validators won't be found. So verify this scenario before relying on service loader. But maybe I'm wrong, for me it was feasible to drop this validation trivially so I did to save some time and could ignore this.
Related
I am reviewing open source spring projects. I am confused about the use of annotations around here. I want to ask to clarify this.
#Target(ElementType.METHOD)
#Retention(RUNTIME)
#Bean
public #interface Merge {
#AliasFor("targetRef")
String value() default "";
#AliasFor("value")
String targetRef() default "";
Placement placement() default Placement.APPEND;
int position() default 0;
Class<MergeBeanStatusProvider> statusProvider() default MergeBeanStatusProvider.class;
boolean early() default false;
}
An annotation has been created here named Merge. It has different parameters and default values.
#Configuration
public class LocalConfiguration {
#Merge(targetRef = "mergedList", early = true)
public List<String> blLocalMerge() {
return Arrays.asList("local-config1", "local-config2");
}
}
And this is usage of #Merge annotation in any class I choosed randomly.
When I examined the code, I could not find any class related to the implementation of Merge annotation. By the way, this problem I'm having isn't just about this annotation. Almost all the annotations I have examined are used without being implemented in any way.
I think I will understand the others if we start from this annotation.
What does this anotation do? What kind of message does it give to the place where it is used. How does the application understand what that annotation does in runtime without being implemented anywhere.
Thanks.
Annotations don't have implementations. They are processed by external classes or tools depending on the RetentionPolicy. In this case, the Merge annotation has Runtime retention so it will be available via reflection once the class is loaded. At runtime any interested party (in this case I assume the Spring Framework) can use getAnnotations on your LocalConfiguration class to detect the Merge annotation and take whatever action that needs to be taken. The possibilities are really up to the framework that defined the annotation. A lot of Spring injection works like this with annotations but they are also used by many other frameworks such as Hibernate, Jersey, etc. The main idea is that annotations act as markers on specific code points to be used by an external entity at a later point.
When we are using Play Framework Action Composition we can directly use the #With annotation, as explained here. Alternatively, we can define custom action annotations.
But what are the advantages of defining your own annotations? It's like we are just adding a middle-man (interface).
And one more doubt: while implementing the action class we use generics to specify a corresponding interface. Is it just because Play is type safe? In the docs they have mentioned "Action definition retrieves the annotation as configuration". Is it just because we can configure using custom annotations?
Think about the following annotation:
#With(CacheAction.class)
#Target({ElementType.TYPE, ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
public #interface Cached {
String key();
Long expires();
String region();
}
With the annotation above, you can annotate your actions like:
#Cached(
key = "my.cached.page",
expires = 30,
region = "pages"
)
public Result index() {
...
}
So, how would you pass these cache configurations to the composing action using the #With annotation? You could not. #With is good if you don't have to configure how the composing action will behave, like logging in the documentation examples. But if you need, then declaring your own annotations is necessary.
The Action class expects the annotation type because you can then retrieve the configuration while calling the composing action:
public CompletionStage<Result> call(Context ctx) {
Cached cacheConfiguration = this.configuration;
String key = cacheConfiguration.key();
Long expires = cacheConfiguration.expires();
string region = cacheConfiguration.region();
...
}
Finally, defining your annotations is good because you can better express their semantics (this is a #Cached action, an #Authenticated action, etc.).
I would like to use Lombok's #NonNull annotation to generate the null-checking code automatically for method parameters while also using FindBugs' #NonNull to use static analysis tools and generate appropriate warnings whenver the case applies.
As of now, I need to do the following:
public void doSomething (#lombok.NonNull #edu.umd.cs.findbugs.annotations.NonNull Object parameter)
{
// Do something
}
This is quite ugly, so I would like to avoid using this syntax. I read about nested annotations (here and here), but I can't seem to find a way to create my own custom annotation with both NonNull annotations as nested annotations. Am I trying to do something that cannot work?
Here's my latest attempt:
#Documented
#Retention (RetentionPolicy.CLASS)
#Target (value={ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
public #interface MyNonNull
{
public lombok.NonNull lombokNonNull () default #lombok.NonNull;
public edu.umd.cs.findbugs.annotations.NonNull findBugsNonNull () default #edu.umd.cs.findbugs.annotations.NonNull;
}
You cannot "merge" annotations with custom annotations, however you can use #ParametersAreNonnullByDefault on the class scope, which should allow edu.umd.cs.findbugs.annotations.NonNull to be inferred.
I think neither of your links will help you. You would need to extend from both with your custom annotation, yet you cannot even extend from one, as all annotations have an implicit extends clause for Annotation.
I'm reviewing Guice. Let's say I've got the following setup:
public interface IsEmailer {...}
public interface IsSpellChecker {...}
public class Emailer implements IsEmailer {
#Inject
public class Emailer(final IsSpellChecker spellChecker)....
}
public class FrenchSpellChecker implements IsSpellChecker {....}
public class EnglishSpellChecker implements IsSpellChecker {....}
#BindingAnnotation public #interface English {}
#BindingAnnotation public #interface French {}
Then in my module I've bound the interfaces to their respective implementations, and annotated the spell checkers with the respective binding-annotation.
Now, let's say based on a runtime variable I need to construct an emailer that either uses the English or the French spell checker.
I thought of using a named providers in my module:
#Provides
#English
IsEmailer provideEnglishEmailer() {
return new Emailer(new EnglishSpellChecker());
}
#Provides
#French
IsEmailer provideFrenchEmailer() {
return new Emailer(new FrenchSpellChecker());
}
This works like this:
IsEmailer emailer = myModule.getInstance(Key.get(IsEmailer.class,
French.class));
Is this the cleanest way to do something like this? After all, I'm forced to construct the object by hand (in the providers).
Thanks
First some notes:
Generally you want to avoid using getInstance as much as possible, except for your "root" element (e.g. YourApplication). Within anything that Guice provides, your best bet is to ask for an injection of Provider<IsEmailer>, or perhaps #English Provider<IsEmailer> and #French Provider<IsEmailer>. Guice will not actually create the elements until you call get on the Provider, so the overhead of creating the Provider is very very light.
You don't have to bind to a provider to get a provider. Guice will resolve any binding of X, Provider<X>, or #Provides X to any injection of X or Provider<X> automatically and transparently.
Provider implementations can take injected parameters, as can #Provides methods.
If you want to bind a lot of things to #English or #French, you may also investigate private modules, since this sounds like the "robot legs" problem to me.
The easiest way is simply to go with the first bullet and inject a Provider of each, especially if you're only doing this once.
You can also bind it in a Module, if your runtime variable is accessible via Guice. Put this in your module along with the #Provides annotations above. (As noted, you may want to rewrite them to accept an EnglishSpellChecker and FrenchSpellChecker as parameters respectively, to enable the spell checkers to inject their own dependencies.)
#Provides IsEmailer provideEmailer(Settings settings,
#English Provider<IsEmailer> englishEmailer,
#French Provider<IsEmailer> frenchEmailer) {
if (settings.isEnglish()) {
return englishEmailer.get();
} else {
return frenchEmailer.get();
}
}
You could use a MapBinder. That would allow you to inject a Map<Language, IsSpellChecker>, and then retrieve the appropriate spell checker at runtime.
Java annotations are marked with a #Target annotation to declare possible joinpoints which can be decorated by that annotation. Values TYPE, FIELD, METHOD, etc. of the ElementType enum are clear and simply understandable.
Question
WHY to use #Target(ANNOTATION_TYPE) value? What are the annotated annotations good for? What is their contribution? Give me an explanation of an idea how it works and why I should use it. Some already existing and well-known example of its usage would be great too.
You can use an annotated annotation to create a meta-annotation, for example consider this usage of #Transactional in Spring:
/**
* Shortcut and more descriptive "alias" for {#code #Transactional(propagation = Propagation.MANDATORY)}.
*/
#Target({ElementType.METHOD, ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Transactional(propagation = Propagation.MANDATORY)
public #interface RequiresExistingTransaction {
}
When you enable Spring to process the #Transactional annotation, it will look for classes and methods that carry #Transactional or any meta-annotation of it (an annotation that is annotated with #Transactional).
Anyway this was just one concrete example how one can make use of an annotated annotation. I guess it's mostly frameworks like Spring where it makes sense to use them.
Each annotation annotated by #Target(ElementType.ANNOTATION_TYPE) is called Meta-annotation. That means, you can define your own custom annotations that are an amalgamation of many annotations combined into one annotation to create composed annotations.
A good example from Android world is StringDef
Denotes that the annotated String element, represents a logical type and that its value should be one of the explicitly named constants.
#Retention(SOURCE)
#StringDef({POWER_SERVICE, WINDOW_SERVICE, LAYOUT_INFLATER_SERVICE})
public #interface ServicesName {}
public static final String POWER_SERVICE = "power";
public static final String WINDOW_SERVICE = "window";
public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater";
Code inspector will treat #ServicesName and #WeekDays in the same way as #StringDef.
As a result we can create as much named StringDef's as we need and override set of constants. #Target(ElementType.ANNOTATION_TYPE) it is a tool that allows to extend the use of annotations.
Annotation is defined like a ordinary Java interface, but with an '#' preceding the interface keyword (i.e., #interface ). Annotations are used to provide supplemental information about a program. On the other hand, an interface can be defined as a container that stores the signatures of the methods to be implemented in the code segment.
WHY to use #Target(ANNOTATION_TYPE) value?
When there is need to apply an annotation to an another annotation. If you look at the source codes of the common Java annotations, you see often this code pattern:
#Target(ANNOTATION_TYPE)
public #interface TheAnnotation
{
...
}
For example,
#Documented
#Target({ ANNOTATION_TYPE })
#Retention(RUNTIME)
public #interface Constraint {
public Class<? extends ConstraintValidator<?, ?>>[] validatedBy();
}
What are the annotated annotations good for?
They are good or more precisely necessary if they are used to annotate other annotations.
What is their contribution?
They make possible to apply an annotation directly to an another annotation, that is a different thing than applying an annotation to a standard Java class or to method and so on.
Give me an explanation of an idea how it works and why I should use it.
For example, if you create a data model class and you may want that the program checks data validity. In that case, there might be need to create a new annotation and apply another annotations to this annotation. It is simple to add some data validity checks to this model by adding annotations to the class. For example, to check that some value is not null (#notNull) or email is valid (#ValidEmail) or length of a field is more than x characters (#Size). However, it is possible that there is not built in Java annotations for all purposes. For example, it is so if you liked to check if password and its matchingPassword are same. This is possible by creating the annotation class PasswordMatches:
#Target({TYPE})
#Retention(RUNTIME)
#Constraint(validatedBy = PasswordMatchesValidator.class)
#Documented
public #interface PasswordMatches {
String message() default "Passwords don't match";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Note, there is line
#Constraint(validatedBy = PasswordMatchesValidator.class).
In other words, the annotation class Constraint, like the other annotations in this class also, must have ANNOTATION_TYPE as a value of target annotation.
Now the password equality check is easy to include to data model class simply by adding annotation #PasswordMatches:
#PasswordMatches
public class UserDto {
...
}
The PasswordMatchesValidator class could look like this:
public class PasswordMatchesValidator implements ConstraintValidator<PasswordMatches, Object> {
#Override
public void initialize(final PasswordMatches constraintAnnotation) {}
#Override
public boolean isValid(final Object obj, final ConstraintValidatorContext context) {
final UserDto user = (UserDto) obj;
return user.getPassword().equals(user.getMatchingPassword());
}
}
Some already existing and well-known example of its usage would be great too.
There is quite well-known example in item 4, but another known annotations which are applied frequently to custom annotations are #Retention, #Documented and #Target itself.
For example, if annotation looks like
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface SomeAnnotation {
String description() default "This is example for class annotation";
}
the compiler will complain in this situation
#SomeAnnotation
public class SomeClass {
#SomeAnnotation // here it's complaning
public void someMethod(){}
}
If you change
#Target(ElementType.TYPE)
to
#Target({ElementType.METHOD, ElementType.TYPE})
it won't complain anymore.
Annotation are basically additional metadata (information) that goes along with your code. It can be placed along side types (Classes, Interfaces), methods, and arguments.
It is often useful during compile time and runtime. Many popular APIs such as Java EE 5+, Spring, AspectJ leverage annotation for code clarity and consistency.
Using annotation often allows code to be more readable, more easily understood.
I'd recommend you read through the annotation chapter on Java tutorial
In the past metadata are often given as an xml file, and it's difficult for someone trying to understand the code if they have to lookup a different xml configuration file. The latest Java servlet API allows mapping of servlet simply by using annotation -- as opposed of web.xml mapping:
#WebServlet("/response")
public class ResponseServlet extends HttpServlet {
// servlet code here...
}