How to check annotation before loading class? - java

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");
}

Related

#Inject interface with two implementation

I am using Microprofile and I have a question. I have an interface with a method inside:
public interface CheckData extends Serializable{
MyObject retrieveData(String name);
}
This interface is implemented by 2 different classes( Class A and Class B).
In the service class I need to use class A or class B based on a condition.
I did the #Inject of my interface:
#ApplicationScoped
public class MyService{
#Inject
private CheckData checkData;
public Response manageData{
...
if(condition)
checkData.retrieveData(name) // i needed Class A implementation
if(condition)
checkData.retrieveData(name) // i needed Class B implementation
}
}
how do you specify which implementation to use?
I solved it this way.
I have created a class with two qualifiers:
public class MyQualifier {
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
public #interface ClassifierOne {
}
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.FIELD, ElementType.TYPE,ElementType. METHOD})
public #interface ClassifierTwo {
}
}
later I added the qualifiers to the classes that implement the interface:
#ClassifierOne
public class A implements CheckData{
...
}
#ClassifierTwo
public class B implements CheckData{
...
}
Finally I injected the interface specifying the qualifier:
#Inject
#ClassifierOne
private CheckData myClassA;
#Inject
#ClassifierTwo
private CheckData myClassB;
I hope it is correct and can help others.
Thanks to #Turo and #Asif Bhuyan for the support

#ConfigurationProperties does not work when using classes in the #SpringBootTest

application.yml
foo:
name: hun
FooConfigurationProperty
foo.name in application.yml is bound.
#Getter
#Setter
#Component
#ConfigurationProperties("foo")
public class FooConfigurationProperty {
private String name;
}
For quick testing, the FooConfigurationProperty bean was added using the classes property.
FooTest
#SpringBootTest(classes = FooConfigurationProperty.class)
public class FooTest {
#Autowired
FooConfigurationProperty fooConfigurationProperty;
#Test
public void fooTest() {
System.out.println(fooConfigurationProperty.getName());
}
}
The above results are output null rather than hun.
Why is null output when classes have specified to use a specific bean?

How to add a user define annotation in spring JPA save method

How to add a user define annotation in spring jpa save method only.
I have created a annotation and wanted to use it on the save method of the repository, but the save method is inherited method from CrudRepository of JPA, not sure how can annotation be applied on only that method and not the other method of that repository.
Tried overriding that method in the repository interface and applied the annotation but it didn't worked
Please refer the code below -
Annotation :
#Target({ ElementType.METHOD })
#Retention(RetentionPolicy.RUNTIME)
public #interface MyAnnotation {
}
#Aspect
#Configuration
#Slf4j
#ComponentScan(value = "com.somepackage.service")
public class MyAnnotationInterceptor {
#Value("${val}")
private String val;
#Around("#annotation(com.somepackage.service.application.annotation.MyAnnotation)")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
if("TEST".equalsIgnoreCase(val)){
log.info("Test Event")
}else{
joinPoint.proceed();
}
}
}
Repository :
#Transactional
public interface EmployeeEntityRepository extends CrudRepository<EmployeeEntity, String> {
List<EmployeeEntity> findAllByEmpIdAndStatusNot(String empId, String status);
#Query("SELECT emp.empId FROM EmployeeEntity emp WHERE emp.orderId IN ?1")
List<String> findEmployeeIds(List<String> orderIds);
#Override
#MyAnnotation
<S extends EmployeeEntity> Iterable<S> save(Iterable<S> iterable);
}
Service Class:
class EmployeeService {
#Autowired
EmployeeEntityRepository employeeEntityRepo;
public void saveEmployee(List<EmployeeEntity> employeeData) {
employeeEntityRepo.save(employeeData);
employeeEntityRepo.clearCache(employeeData);
/***
.
.
.
Some other logic calculations
.
.
***/
}
}

Spring DTO validation using ConstraintValidator

The DTO that I use is annotated with javax.validation annotations
For example
#JsonIgnoreProperties(ignoreUnknown = true)
public class StudentDTO {
#NotEmpty
private String name;
#Positive
private Long studentId;
}
What if I have to validate using ConstraintValidator for StudentDTO
Spring MVC has the ability to automatically validate #Controller
inputs. In previous versions it was up to the developer to manually
invoke validation logic.
But in your case , you are trying to validate a DTO object in which case , springboot might not be automatically binding your validator to your model and call the validator.So, in that case, you will need to manually bind the object to the validator.
or you can manually invoke the validator on a bean like :
#AutoWired
Validator validator;
...
validator.validate(book);
You can define a custom validator in springboot for model classes if you want and use annotations :
#Documented
#Constraint(validatedBy = CustomDataValidator.class)
#Target( { ElementType.METHOD, ElementType.FIELD })
#Retention(RetentionPolicy.RUNTIME)
public #interface CustomDataConstraint {
String message() default "Invalid data";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
and then define a validator class like :
public class CustomDataValidator implements
ConstraintValidator<CustomDataConstraint, String> {
#Override
public void initialize(CustomDataConstraint data) {
}
#Override
public boolean isValid(String field,
ConstraintValidatorContext cxt) {
return field!= null;
}
}
Your validator class must implement the ConstraintValidator interface and must implement the isValid method to define the validation rules, define the validation rules can be anything as you wish.Then, you can simply add the annotation to your field like :
#CustomDataConstraint
private String name;

CDI method injection and bean inheritance in Java

What I want to do - I have a child and parent class. Child has SimpleFoo, Parent needs Advaced foo. So,
#Dependent
public class SimpleFoo {
}
#Dependent
public class AdvancedFoo extends SimpleFoo {
}
#Dependent
public class Child {
private SimpleFoo foo;
#Inject
protected void setFoo(SimpleFoo foo) {
this.foo = foo;
}
}
#Dependent
public class Parent extends Child {
#Inject
#Override
protected void setFoo(SimpleFoo foo) { //How to inject here AdvancedFoo
super.setFoo(foo);
}
}
I know that I can do it via constructor injection but I need method injection. How to do it? Can it be done without using names (like MyBean1) but only using classes (AdvancedFoo)?
Use qualifiers - you now have two beans which both fulfill your requirements on type; you need to limit that and qualifiers are made for such cases.
Here is how to do it, first the qualifier:
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
#Target({ ElementType.TYPE, ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD })
public #interface MyQualifier {
}
Now, make your AdvancedFoo bean use that qualifier:
#Dependent
#MyQualifier
public class AdvancedFoo extends SimpleFoo {
...
}
And finally, in the init method, inject a bean of type SimpleFoo and with qualifier #MyQualifier:
#MyQualifier
public class Parent extends Child {
#Inject
protected void setFoo(#MyQualifier SimpleFoo foo) {
this.foo = foo;
}
}

Categories