Custom Annotations in Java using array with different array object values - java

can anybody help me to write code for below annotation?
#Encryption( sensitiveTypeInfo={sensitiveTag=9, logHidingScheme='MASK', databaseHidingScheme='ENCRYPT', sensitiveTypeDescription='First name '})
code snippet:
#Documented
#Retention (RetentionPolicy.RUNTIME)
#Target (ElementType.METHOD)
public #interface Encryption
{
String[] sensitiveTypeInfo() ;
}

Based on your comments you should probably try a solution with nested annotations:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface A
{
String author();
B[] nested();
}
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface B
{
String label();
C[] moreNested();
}
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface C
{
int value();
}
You can then do the following:
#A(author="Vijay", nested={
#B(label="First", moreNested=#C(5)),
#B(label="Second", moreNested={#C(6), #C(7)})
})

Related

Spring Async Annotation: Executor Id by Enum

I have a custom #Async annotation with the specified Executor ID.
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.TYPE, ElementType.METHOD})
#Async("fixedThreadPool")
public #interface AsyncFixedPool {
}
I wonder is it possible to specify executor id by enum? For example, something like that.
public enum ExecutorType {
EXECUTOR_1, EXECUTOR_2
}
...
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.TYPE, ElementType.METHOD})
#Async
public #interface AsyncFixedPool {
// value converts as Enum.name()
#AliasFor(annotation = Async.class, attribute = "value")
ExecutorType value();
}
...
#AsyncFixedPool(EXECUTOR_1)
public void myAsyncMethod() {...}

Validating member List variables for null values

The structure that I have is something like below:
Class A{
String str;
int i;
List<B> bs;
C c;
#NotNull
List<D> ds;
}
Class B{
#NotNull
List<E> es;
}
Class C{
List<String> s;
}
Class E{
#NotNull
List<String> s;
}
For the list variables that are annotated with #NotNull I need to throw validation error if any of them variables has one or more null objects. While for the other list variables I just need to remove the nulls;
What would be the best way to achieve this?
If you are using validation 2.0+ you can put annotation inside: List<#NotNull String> s;
You should define custom annotation for validating.
so define custom annotation like bellow.
#Target({ElementType.FIELD, ElementType.PARAMETER,ElementType.ANNOTATION_TYPE})
#Retention(RUNTIME)
#Constraint(validatedBy = ValidateListValidator.class)
#Documented
public #interface ValidateList {
}
and implement ValidateListValidator like this:
public class ValidateListValidator implements ConstraintValidator<ValidateList, List<Object>> {
private ValidateList validateList;
#Override
public void initialize(ValidateList validateList) {
this.validateList = validateList;
}
#Override
public boolean isValid( List<Object> list, ConstraintValidatorContext constraintValidatorContext) {
return list.stream().noneMatch(Objects::isNull);
}
}
and for test it
#Test
public void test() {
boolean valid = validator.isValid(Arrays.asList("test","this",null),context);
assertThat(valid, is(false));
}
This is the final code that I wrote, just a few tweaks to the code that Hadi posted. I hope it helps:
Annotation:
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
#Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Constraint(validatedBy = ListValidator.class)
#Documented
public #interface ValidList {
String message() default "Null values are not allowed in array fields.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Validator Class:
import java.util.List;
import java.util.Objects;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class ListValidator implements ConstraintValidator<ValidList, List<? extends Object>> {
#Override
public boolean isValid(List<? extends Object> list, ConstraintValidatorContext context) {
return list.stream().noneMatch(Objects::isNull);
}
#Override
public void initialize(ValidList constraintAnnotation) {}
}

AspectJ- combining method annotation and set field

I have a requirement where in I need to time various method calls into a time series db.
For the same, I have created 2 annotations one for the method call:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface Auditable {
String event();
String entity();
}
and another one for a field
#Target(ElementType.FIELD)
#Retention(RetentionPolicy.RUNTIME)
public #interface Id {
String id();
}
The reason I need the #ID annotation is that, the id field to be pushed to influx db would be known only at run time.
So, in my method, something like this would happen:
#Id
String key;
#Auditable(event="xxx",entity="yyy")
public void methodToBeIntercepted(){
String key = <logic to generate key>;
}
The idea that I wanted to use was add an annotation advice along with a field set advice.
#After("#annotation(auditable) && (set(#<package>.ID java.lang.String sample..*.*) && args(id))")
public void pointcutMethod(Auditable auditable,String id){
}
But the flow is never entering into the pointCutMEthod. If I change the condition to || above, then it enters but it clearly suggests that only 1 condition would be true at any given point of time.
What is it that I am doing wrongly here?
Your analysis is correct: The advice will never trigger. It just cannot because the two pointcuts you combine are mutually exclusive: Where #Auditable is (method call or execution) is a different joinpoint from set(). What you intend to express is the following: "Intercept member variable assignment within the control flow of a method execution." I.e. you need cflow(#annotation(auditable)).
Annotations and driver application:
package de.scrum_master.app;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Target(ElementType.FIELD)
#Retention(RetentionPolicy.RUNTIME)
public #interface Id {
String id();
}
package de.scrum_master.app;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface Auditable {
String event();
String entity();
}
package de.scrum_master.app;
public class Application {
#Id(id = "my ID")
String key;
public static void main(String[] args) {
Application application = new Application();
application.methodToBeIntercepted();
}
#Auditable(event = "xxx", entity = "yyy")
public void methodToBeIntercepted() {
key = "I am the key";
}
}
Aspect:
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import de.scrum_master.app.Auditable;
#Aspect
public class MyAspect {
#After("cflow(#annotation(auditable)) && set(#de.scrum_master.app.Id String de.scrum_master..*.*) && args(id)")
public void pointcutMethod(JoinPoint thisJoinPoint, Auditable auditable, String id) {
System.out.println(thisJoinPoint);
System.out.println(" " + auditable);
System.out.println(" " + id);
}
}
Console log:
set(String de.scrum_master.app.Application.key)
#de.scrum_master.app.Auditable(event=xxx, entity=yyy)
I am the key

Inject EJB annotation

When I use annotation #EJB in my code all work fine
public class CatalogueDetailsPage extends AbstractBasePage {
#EJB(lookup = "java:global/mobile.bank.services-1.0.5/api.ejb-1.1/CatalogueFacadeBean!by.softclub.common.api.ICatalogueService")
private ICatalogueService iCatalogueService;
}
But when I want use #Inject & #Produces I have error null pointer
public class CatalogueDetailsPage extends AbstractBasePage {
#Inject
#EJBBean
private ICatalogueService iCatalogueService;
}
#Stateless
public class EJBFactory {
#EJB(lookup = "java:global/mobile.bank.services-1.0.5/api.ejb-
protected ICatalogueService iCatalogueService;
#Produces
#EJBBean
public ICatalogueService getiCatalogueService() {
return iCatalogueService;
}
}
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
#Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
public #interface EJBBean {
}
}
Why is this happening?

How to check annotation before loading class?

I have my own class loader. I'd like to load class only if it has some specified annotation.
How to check annotation before loading the class?
Here's a simple example of class annotation:
#SomeAnnotation(name="someName", value="someValue")
public class Meta {}
The Meta definition:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface SomeAnnotation {
public String name();
public String value();
}
Access to the class annotation and load class:
Class clazz = Meta.class;
ClassLoader classLoader = clazz.getClassLoader();
Annotation annotation = clazz.getAnnotation(SomeAnnotation.class);
if (annotation instanceof SomeAnnotation) {
classLoader.loadClass("Meta");
}

Categories