Grouping Multiple Annotations - java

I have java 1.7. Is there any way to group multiple annotations to single one. So that i annotate with single annotation and gets all the properties of all grouped multiple annotations. I want to avoid multiple annotation lines repeated every time.
Can we use the 3 annotation into one
Does java core libraries or others support this.
Thnx

No, that's not possible. An established idiom for this is to meta-annotate the #Combined annotation with its composing annotations:
#A
#B
#C
public #interface Combined {}
This pattern expresses that annotating an element with #Combined is equivalent to specifying #A, #B and #C at that element.
This of course requires the library consuming these annotations to be aware and make use of this pattern. That's e.g. the case for constraint annotations in Bean Validation or stereotypes in CDI.

I'm not sure if this is what you're looking for, but CDI provide stereotype annotations.

Related

Guice multiple annotations

I have an interface called StatsStore. I have 2 implementations of this store. An in-memory and an SQL implementation called InMemoryStatsStore and SqlStatsStore. In order to inject them I've create 2 annotations #InMemoryStore and #SqlStore. the injections are:
bind(StatsStore.class)
.annotatedWith(InMemoryStore.class)
.to(InMemoryStatsStore.class);
bind(StatsStore.class)
.annotatedWith(SqlStore.class)
.to(SqlStatsStore.class);
Now I want to add a new layer of annotation to separate between InMemoryStringStore and InMemoryNumberStore but I can't add more than one annotation to the binding lines e.g. the following does not compile:
bind(StatsStore.class)
.annotatedWith(InMemoryStore.class)
.annotatedWith(NumberStoreAnnotation.class) // using named doesn't work as well
.to(InMemoryNumberStore.class);
How can I add more than one annotation without using a single named one which would be quite complicated the more layers I add to it?
The other solution I had in mind is Injecting twice:
bind(StatsStore.class)
.annotatedWith(InMemoryStore.class)
.to(InMemoryStatsStore.class);
bind(InMemoryStatsStore.class)
.annotatedWith(NumberStoreAnnotation.class)
.to(InMemoryNumberStore.class);
Thanks all.
As Amit said, you can't have more than one #BindingAnnotation apply to any given injection. Internally, Guice works like a Map<Key, Provider> where a Key is a possibly-parameterized class with an optional single annotation instance. However, because these are instances, you're welcome to create your own instantiable annotation that works the way Named works.
#Inject #InMemoryStore(NUMBER) StatsStore inMemoryNumberStore;
#Inject #SqlStore(STRING) StatsStore sqlStringStore;
// or
#Inject #Store(dataType=NUMBER, backend=SQL) sqlNumberStore;
The annotation must have the fields defined like so. (If you have one element named value, you can omit the property name per JLS 9.7.3.) Equal annotations are defined as in the Annotation.equals docs.
public enum DataType { NUMBER, STRING; }
public enum Backend { SQL, IN_MEMORY; }
#BindingAnnotation #Retention(SOURCE) #Target({ FIELD, PARAMETER, METHOD })
public #interface Store {
DataType dataType();
Backend backend();
}
That works nicely for #Provides, when you can invoke the annotation the same way you inject it, but how can you create a factory method for instances like Names.named? For that, you'll need to do one of the following:
Create an anonymous implementation, with accessors for each attribute as well as correct implementations of equals and hashCode. Note that the hashCode contract is much stricter than for Object, but you can get compatible implementations from Apache annotation utils or similar libraries.
Use AnnotationLiteral, which provides equals and hashCode implementations for arbitrary subclasses.
Use Google Auto or a similar code generator to generate code for a compatible implementation for you. Familiarity with this type of solution is particularly useful for Android and other memory-constrained environments for which reflection is slow, though such environments usually preclude you from using Guice. (#Qualifier annotations work the same way in other JSR-330 compatible dependency injection frameworks, though, including Dagger.)
If the above seems a little complicated, or if you want more complex logic than Guice's map-based implementation can accomplish, one alternative is to add a layer of indirection that you control:
public class StoreStore {
#Inject Provider<InMemoryNumberStore> inMemoryNumberStoreProvider;
// ...
// You can also inject the Injector to call getInstance with a class literal.
public StatsStore getStore(DataType dataType, Backend backend) {
// This can also be a switch or any other sort of lookup, of course.
if (dataType == NUMBER && backend == IN_MEMORY) {
return inMemoryNumberStoreProvider.get();
} // ...
}
}
You can't do that:
#BindingAnnotation tells Guice that this is a binding annotation. Guice will produce an error if ever multiple binding annotations apply to the same member.
You could use named bindings instead, or you should consider redesigning your solution.

Can MapStruct be told to not perform automatic mappings?

I have a rather big bean (~ 100 properties) that is mapped into several smaller objects. It may occur that the smaller target objects have properties with the same name as in my source bean, but not with the same semantic meaning.
I would like MapStruct to behave in this specific case to map only what I explicitly tell using a #Mapping annotation and not perform the usual automatic mapping.
The MapStruct documentation tells me just this:
In the generated method implementations all readable properties from the
source type (...) will be copied into the corresponding property
in the target type (...).
I didn't find any configuration option switching this behavior off.
Can it be done?
Switching off implicit field mapping is possible via #BeanMapping(ignoreByDefault = true) mapping method annotation since MapStruct 1.3. From MapStruct 1.3.1 Reference Guide:
By means of the #BeanMapping(ignoreByDefault = true) the default
behavior will be explicit mapping, meaning that all mappings have to
be specified by means of the #Mapping and no warnings will be issued
on missing target properties.
As stated in Mohamed's comment, you could ignore these properties explicitly.
There is no switch as you describe it. Personally I'd probably write that specific mapping from hand instead of explicitly configuring all the mappings through annotations. Granted, you'd still benefit from type conversion etc., so it may still be beneficial, it really depends on your use case.
I had a similar problem like you say, I solved it using decorators
#Mapper
#DecoratedWith(PersonMapperDecorator.class)
public interface PersonMapper {...}
see the documentation (MapStruct 1.2.0.Final Reference Guide), chapter: 12. Customizing mappings
I hope that it is also useful for you

Purpose of #NotNull.List

When I looked among the standard constraints in Bean Validation API (JSR-303), I found the NotNull.List annotation. Its description is:
Defines several #NotNull annotations on the same element
This is valid syntax:
#NotNull.List({#NotNull, #NotNull})
private Object myObject;
But it makes no sense. Either the object is null or it is not. When would you use this annotation?
There are several other similar annotations like AssertFalse.List and AssertTrue.List.
You can have multiple #NotNull annotations that are mutually exclusive based on the group attribute.
#NotNull.List({#NotNull(groups=Foo.class,message="Some message!"),
#NotNull(groups=bar.class, message="Some other message!"})
private Object myObject;
I do agree it's a little silly for this example since only the payload and message can be affected, but it's probably there to remain consistent with the other annotations.
See here for more details.
As to the #NotNull case, multiple #NotNull annotations might be needed
for different validation groups as #dfb explained. But the same may be
accomplished by listing those groups in the groups attribute.
This is well explained here with test cases
In the bean validation API javadoc, for every constraint annotation,
there's a corresponding .List annotation. For example, for #NotNull,
there's #NotNull.List, for which JavaDoc says:
Defines several #NotNull annotations on the same element
What would you accomplish with multiple #NotNull annotations that you
cannot accomplish with one #NotNull?

Component scanning filter types in Spring

I am learning Spring using Spring In Action 3rd Edition, I came across the different filter types in component scanning of Spring.
Here is the list available:
annotation - Filters scan classes looking for those annotated with a given annotation at the type level. The annotation to scan for is specified in the expression attribute.
assignable - Filters scan classes looking for those that are assignable to the type specified in the expression attribute.
aspectj - Filters scan classes looking for those that match the AspectJ type expression specified in the expression attribute.
custom - Uses a custom implementation of org.springframework.core.type.TypeFilter, as specified in the expression attribute.
regex - Filters scan classes looking for those whose class names match the regular expression specified in the expression attribute.
I got some idea on the use of the filter types for assignable and annotation based on examples given in book.
But for the remaining filter types, I am not able to understand how these types are used and when we need to use one of them. Can you please help me in understanding the concepts here.
A component scan tells Spring to recursively look for classes in a package, instantiate an object for each class that's found, and manage the lifecycle of those objects. The objects are called beans. (That's a very coarse explanation; Spring checks scopes, creates proxies, and does a ton of other stuff, but those details aren't relevant for talking about filters.)
A component scan filter narrows down which of those classes to instantiate beans for.
You might only want to consider classes which have a certain annotation, e.g. #Component, and you'd use an annotation filter for that.
You might want to consider classes that implement a certain interface, e.g. Dao, and you'd use assignable for that.
You might want to pick out some classes by name, e.g. com.foo.**.service.*, and you'd use a regex for that.
You might want to use expressions to pick out a complex subset of classes, e.g. com.foo..service.* && !com.foo..MockService, and you'd use aspectj for that.
You might extremely rarely want to pick out classes by their metadata, e.g. create a bean if the class has an enclosing class named Foo, and you'd write a custom TypeFilter to do that, which gives you access to that metadata.
I've listed these in order of popularity from my personal experience, and I'd guess that annotation, assignable are by far the most popular.
Update: All filters are implemented as TypeFilters, and they look at different pieces of class metadata in their match method. For example, RegexPatternTypeFilter implements the regex filter, and its match method looks like
#Override
protected boolean match(ClassMetadata metadata) {
return this.pattern.matcher(metadata.getClassName()).matches();
}
Writing your own custom TypeFilter lets you use the methods in the org.springframework.core.type.ClassMetadata and org.springframework.core.type.AnnotationMetadata interfaces to decide whether Spring should create a bean for a class with some particular metadata.
AspectJ type expression refers to pointcut expression used by AspectJ framework. AspectJ is framework for aspect oriented programming. More info here http://www.eclipse.org/aspectj/doc/next/progguide/semantics-pointcuts.html
"Custom" means that you can provide your own class for finding spring components instead of using spring defaults
Regex means regular expression. Basicly this filter type works similar to aspectj filter but instead of finding components using aspectj type expression it uses normal regular expression.

Combine annotations in Java

How can I combine annotations in Java?
EDIT I was asking if I two annotations a and b, can I combine to a single annotations c?
If possible, how do I do that?
You cannot combine the annotations by e.g. annotating the annotations, unless the annotation consumer will process the meta-annotation tree explicitly. For example, Spring supports such feature for #Transactional, #Component and some other annotations (you may wish to have a look at SpringTransactionAnnotationParser#parseTransactionAnnotation()). Nice to have this feature in Java core, but alas...
However you can declare the common parent class that has a set of annotations you need and extend it. But this is not always applicable.
Assuming you want to have multiple annotations on a single element, you can just list them in sequence.
The Wikipedia page on Java annotations has quite a few useful examples, e.g.
#Entity // Declares this an entity bean
#Table(name = "people") // Maps the bean to SQL table "people"
class Person implements Serializable {
...
}

Categories

Resources