Creating default custom Hystrix Property - annotations

I'm new on Hystrix, I'm just adding it to my project, but I'd like to know whether I can create a custom annotation "HystrixDefaultTimeoutProperty" that extends the HystrixProperty, so each time I want to use a default value for the timeout I can use that custom annotation instead of using:
#HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
Thanks in advance!

No, it is not possible, If you were to look at the source code of HystrixCommand and #HystrixProperty
#Target({ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
#Inherited
#Documented
public #interface HystrixCommand {
.....
}
and
#Target({ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
#Documented
public #interface HystrixProperty {
.....
}
Both of these annotations has
#Target({ElementType.METHOD})
which implies you can use these annotations only on Methods

Related

Pass value from a Spring meta-annotation to another annotation

My use case:
I will have a lot of #PreAuthorize annotation in the form #PreAuthorize("hasAuthority('RESPECT_MY_AUTHORITY')").
I'd like to create a meta-annotation #HasAuthority which takes the authority as a value and pass it to #PreAuthorize("hasAuthority(<value>)").
It feels like it's not possible. The closest I get to what I want is something like the #AliasFor annotation. but the problem is that I can't add anything to the value I'll get in #HasAuthority. So I would have to repeat the hasAuthority part everytime.
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
#PreAuthorize("hasAuthority('RESPECT_MY_AUTHORITY')")
public #interface HasAuthority {
#AliasFor(annotation = PreAuthorize.class, attribute = "value")
String value();
}
I'd like something like:
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
#PreAuthorize("hasAuthority(#value)")
public #interface HasAuthority {
String value();
}
Any idea how I could do that, or if it's possible at all?

Abstract components via org.osgi.service.component annotations

I am migrating from org.apache.felix.scr annotations to org.osgi.service.component annotations. I have a set of Components that inherit from a common abstract class. In the felix case, I can use a #Component annotation with the option componentAbstract=true on the super class, and then use #Reference annotation in the super class. I cannot find how to migrate this to osgi annotations.
Is it possible to use Component annotations in a super class of a Component? And if so, what is then the appropriate way to handle the properties and metatype generation?
So, what I am looking for, is something like this
/* No component definition should be generated for the parent, as it is
abstract and cannot be instantiated */
#Component(property="parent.property=parentValue")
public abstract class Parent {
#Reference
protected Service aService;
protected activate(Map<String,Object> props) {
System.out.println("I have my parent property: "+props.get("parent.property"));
#Override
public abstract void doSomething();
}
/* For this class, the proper Component definition should be generated, also
including the information coming from the annotations in the parent */
#Component(property="child.property=childValue")
public class Child extends Parent {
#Activate
public activate(Map<String,Object> props) {
super.activate(props);
System.out.println("I have my child property: "+props.get("child.property"));
}
public void doSomething() {
aService.doSomething();
}
}
By default BND will not process DS annotations in parent classes. You can change that with -dsannotations-options: inherit but please see http://enroute.osgi.org/faq/ds-inheritance.html why you shouldn't!
2021-02-23 UPDATE: It seems like the page mentioned above is no longer available. I don't know if it was moved elsewhere or simply removed but its content (in Markdown format) is still available on GitHub: https://github.com/osgi/osgi.enroute.site/blob/pre-R7/_faq/ds-inheritance.md

Spring AOP : Interface method with Parameter annotation captured, but annotation is not present

I'm using Spring AOP to intercept a method execution.
I have an interface that looks like the following:
public interface MyAwesomeService {
public Response doThings(int id, #AwesomeAnnotation SomeClass instance);
}
Here is the implementation of the interface:
public class MyAwesomeServiceImpl implements MyAwesomeService {
public Response doThings(int id, SomeClass instance) {
// do something.
}
}
Now i would like any method which has a parameter annotated with #AwesomeAnnotation should be captured by Spring AOP.
So I wrote the following aspect which works.
#Aspect
#Component
public class MyAwesomeAspect {
#Around("myPointcut()")
public Object doAwesomeStuff(final ProceedingJoinPoint proceedingJoinPoint) {
final MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
Annotation[][] annotationMatrix = methodSignature.getMethod().getParameterAnnotations();
// annotationMatrix is empty.
}
#Pointcut("execution(public * *(.., #package.AwesomeAnnotation (package.SomeClass), ..))")
public void myPointcut() {}
}
However when I try to find the parameter annotations I don't get any annotations back. As mentioned above, the annotationMatrix is empty.
So here are my questions:
Why is the annotationMatrix empty? Probably because parameter annotations are not inherited from an interface.
Why I'm able to capture the method execution. Since Spring AOP is able match the pointcut, Spring somehow is able to see the method's parameter annotations but when I try to see that using methodSignature.getMethod().getParameterAnnotations() it doesn't work.
I also faced this issue with one of my parameter annotations. I was able to fix the same by making sure that the parameter annotation definition had RetentionPolicy as RUNTIME and Target as PARAMETER
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.PARAMETER)
public #interface Param {
public String name();
}
The answers to your questions:
Parameter annotations are not inherited from interfaces to implementing methods. In fact, annotations are almost never inherited, only from class (not interface!) to subclass if the annotation type itself is annotated by #Inherited, see JDK API documentation.
Update: Because I have answered this question several times before, I have just documented the problem and also a workaround in Emulate annotation inheritance for interfaces and methods with AspectJ.
Because during compile or weave time AspectJ can match your pointcut against the interface method and thus sees the annotation.
You can fix the situation by adding the annotation to the parameter in your interface implementation, e.g. like this:
#Override
public Response doThings(int id, #AwesomeAnnotation SomeClass instance) {
// ...
}
Then with an aspect like this...
#Aspect
#Component
public class MyAwesomeAspect {
#Pointcut("execution(public * *..MyAwesomeService.*(*, #*..AwesomeAnnotation (*), ..)) && args(*, instance, ..)")
static void myPointcut(SomeClass instance) {}
#Around("myPointcut(instance)")
public Object doAwesomeStuff(Object instance, ProceedingJoinPoint proceedingJoinPoint) {
System.out.println(proceedingJoinPoint);
System.out.println(" instance = " + instance);
MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
Annotation[][] annotationMatrix = methodSignature.getMethod().getParameterAnnotations();
for (Annotation[] annotations : annotationMatrix) {
for (Annotation annotation : annotations) {
System.out.println(" annotation = " + annotation);
}
}
return proceedingJoinPoint.proceed();
}
}
... you get a console log similar to this:
execution(Response de.scrum_master.app.MyAwesomeServiceImpl.doThings(int, SomeClass))
instance = de.scrum_master.app.SomeClass#23fc625e
annotation = #de.scrum_master.app.AwesomeAnnotation()

use GwtCreateResource to provide text programatically

I would like my uiBinder to use a ClientBundle which will provide some runtime customized labels. Kind of a TextResource but not from a text file !
I tried with GwtCreateResource but from the DevGuide it seems like it's not possible. Am I right ? (create() and name() are the only methods available)
What I would like to achieve is something like this:
client bundle:
public interface MyWidgetResources extends ClientBundle {
GwtCreateResource<WidgetLabels> labels();
#Source("lol.css")
CssResource style();
}
labels class:
public final class MyWidgetLabels {
public String title() {
return load("mywidget-title");
}
public String banner() {
return load("mywidget-banner");
}
private String load(String key) {
// load from external..
}
}
uiBinder:
<ui:with type="com.package.MyWidgetResources" field="res"/>
<gwt:SimplePanel>
<gwt:Label text="{res.labels.title}"></gwt:Label>
<gwt:Label text="{res.labels.banner}"></gwt:Label>
</gwt:SimplePanel>
My code looks like this already but res.label.title does not work because GwtCreateResource can only serve as class instantiator (res.labels.create().title()).
Is there a solution for me ? Maybe with a custom ResourceGenerator ?
As long as MyWidgetLabels can be created by GWT.create, you can put anything you want into that type, and you can make it behave however you'd like. You will need the create reference in your uibinder as you suggested at the end of the post to actually build the object, so your lines will look about like this:
<gwt:Label text="{res.labels.create.title}"></gwt:Label>
Each . separated piece (except the first, which is a ui:field/#UiField) is a no-arg method to be called - you declared labels() in MyWidgetResources, create() already existed in GwtCreateResource, and you created title() in your own MyWidgetLabels type.
Since that first piece is a ui:field/#UiField, you could have another that references res.labels.create as something like labels so that later you could instead say:
<gwt:Label text="{labels.title}"></gwt:Label>
Finally, yes, you could build your own ResourceGenerator which would enable you to do whatever you wanted to emit the type in question, as long as you extended the ResourcePrototype type and had a getName() method.

How to test annotation object in the class that implement AbstractModule

I got a question regarding binding and annotation.
I have the following class:
public class MailFacadeImpl implements MailFacade {
private final PersonDao personDao;
#Inject
public MailFacadeImpl(#Mail PersonDao personDao) {
super();
this.personDao = personDao;
}
The PersonDao is annotated with a custom annotation.
I would like to be able to test this annotation inside the class that implement AbstractModule.
here is a piece of code:
bind(new TypeLiteral<SecurityRulesFactory<Person>>(){}).toProvider(FactoryProvider.newFactory(
new TypeLiteral<SecurityRulesFactory<Person>>(){}, new TypeLiteral<MailSecurityRulesCrdb>(){}));
I would like to have somthing similar to :
if(PersonDAO is annotated with(Mail.class) ){
bind(new TypeLiteral<SecurityRulesFactory<Person>>(){}).toProvider(FactoryProvider.newFactory(
new TypeLiteral<SecurityRulesFactory<Person>>(){}, new TypeLiteral<MailSecurityRulesCrdb>(){}));
}
Do you think it's possible?
thx for your help :-)
Have a nice friday!
It's not clear why you want your module to do this test. Instead, your module can specify how to get or create an instance of PersonDao for injection points annotated with Mail:
bind(PersonDao.class).annotatedWith(Mail.class).to(EmailAwarePersonDao.class);
Note that your PersonDao.class.isAnnotationPresent(Mail.class) won't help here, since the PersonDao class itself isn't annotated with Mail; the parameter to the MailFacadeImpl constructor has that annotation. There are ways to test for that, but if you are trying to do that from a Guice module, you're probably doing something wrong.