Custom class level annotation in spring boot - spring-boot

I created a custom class level annotation.
Below is the aspect class:
#Aspect
#Slf4j
#Component
public class LoggingAspect {
private String generateLogMessage() {
return ("Entering method");
}
#Before("#within(mypackage.logging.Loggable) || #annotation(mypackage.logging.Loggable)")
public void logMethodEntry(JoinPoint joinPoint) {
String logMessage = generateLogMessage();
log.debug(logMessage);
}
}
Below is my custom annotation:
#Target(value = {ElementType.TYPE, ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
public #interface Loggable { }
When I use the annotation at class level it works. But if I am calling different methods within the same class the logging is done only once. I want to do the logging for each methods called using the class level #Loggable annotation.
I tried to use it at method level it works. But I want to use it at class level.

Related

Spring #Bean - creation of Spring Bean depends on service class name

I use Spring 4.2.8 and I do have the service class below. If this class has the name ScheduleEmailCreateAndSendServiceImpl than everything works fine (method generalEmailMessage is invoked at start time in order to create the Spring Bean)
If I rename this class to EmailCreateAndSendServiceImpl than method generalEmailMessage will not be invoked at start time - does anyone know why?
#Service("emailCreateAndSendService")
public class ScheduleEmailCreateAndSendServiceImpl extends AbstractService
implements EmailService {
protected EmailMessage generalMessage;
#Override
public void createAndSendMessage(String receiver, boolean emailActive, Object[] values) throws BusinessException {
// create and send email
}
#Bean
public EmailMessage generalEmailMessage() {
this.generalMessage = new GeneralEmailInformationMessage();
return generalMessage;
}
}
[EDIT]
with this code it is the same
#Configuration
public #Data class ScheduleGeneralEmailConfiguration {
protected EmailMessage generalMessage;
public ScheduleGeneralEmailConfiguration() {
System.out.println("asdf");
}
#Bean
public EmailMessage generalEmailMessage() {
this.generalMessage = new GeneralEmailInformationMessage();
return generalMessage;
}
}
#Bean annotated methods should be in #Configuration annotated class.
You can also put the #Bean annotated methods in the main class of the Spring Boot application annotated with #SpringBootApplication which encapsulates #Configuration, #EnableAutoConfiguration, and #ComponentScan annotations.
Make sure your #Configuration annotated class is placed in the same package or sub package of the Spring Boot Application class

Aspect annotation for class

I have a custom annotation, that is handled with AOP in Spring boot. It works perfect when I put it above a method, but when I put it above class I am not able to extract its value :(
Annotation
#Target({ElementType.METHOD, ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
public #interface UserAuthorization {
UserRoleEnum[] userRoles();
String paramName() default "userDetails";
String errorMessage() default "NOT AUTHORIZED";
}
Aspect:
#Aspect
#Component
public class UserAuthorizationAspect {
#Around("#annotation(UserAuthorization)")
public Object validateAuthoritiesAspect(ProceedingJoinPoint pjp) throws Throwable {
MethodSignature signature = (MethodSignature) pjp.getSignature();
UserAuthorization userAuthorization = signature.getMethod().getAnnotation(UserAuthorization.class);
// Some code
}
}
Change your aspect to check if the class has annotation
signature.getMethod().getDeclaringClass()
.getAnnotation(UserAuthorization.class)
Change you annotation to support both class level and method level annotations
#Target({ElementType.TYPE, ElementType.METHOD})

Spring Data Rest: custom Converter<Entity, Resource> is never invoked

I'm trying to implement a custom Converter for an Entity to a Resource object with Spring Data Rest, but the Converter is never invoked.
I'm following this documentation:
If your project needs to have output in a different format, however,
it’s possible to completely replace the default outgoing JSON
representation with your own. If you register your own
ConversionService in the ApplicationContext and register your own
Converter, then you can return a Resource
implementation of your choosing.
That's what I've tried to do.
I have a #Configuration class that extends RepositoryRestMvcConfiguration, with this method:
#Configuration
#EnableWebMvc
#EnableHypermediaSupport(type = HypermediaType.HAL)
public class RepositoryBaseConfiguration extends RepositoryRestMvcConfiguration {
#Override
public DefaultFormattingConversionService defaultConversionService() {
return super.defaultConversionService();
}
}
And I have a Class that extends RepositoryRestConfigurerAdapter, with this implementation:
#Configuration
public class RepositoryBaseConfigurerAdapter extends RepositoryRestConfigurerAdapter {
#Override
public void configureConversionService(ConfigurableConversionService conversionService) {
if(!conversionService.canConvert(Entity.class, Resource.class))
conversionService.addConverter(new EntityConverter());
super.configureConversionService(conversionService);
}
}
Both methods of those two classes are correctly invoked and managed, so it's natural to think that the Converter has been registered in the Application Context...
This is my custom converter EntityConverter:
#Component
public class EntityConverter implements Converter<Entity, Resource> {
#Override
public Resource convert(Entity source) {
System.out.println("method convert of class EntityConverter");
return null;
}
}
The method "convert" is never invoked by Spring Data Rest.
What's wrong/missing ?
Thanks in advance.

Inject a list of classes that extends an abstract class with Spring

Hy,
I have the next code:
public abstract class MyClass{
protected abstract void method1();
}
Classes that extend the first one:
#Component
public class MyClass1 extends MyClass{
.....
}
#Component
public class MyClass2 extends MyClass{
.....
}
My class where I try to inject list of classes that extends an abstract class
#Component
public class SpringClass{
#Autowired **//It doesnt work, nothing is inyected!**
List<MyClass> classes
}
My problem is it doesnt work, it doesnt inject the list of classes that extend MyClass in property classes. Why?
Thanks
You can remove #Autowired annotation for the instance variable and add it to the setter method. After doing this your spring class would be
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class SpringClass {
List<MyClass> classes;
#Autowired
public void setClasses(List<MyClass> classes) {
this.classes = classes;
}
}
Hope this helps.
#Component
public class SpringClass {
#Autowired
private Map<String, YourInterface> map;
}
String in map will be contain all classes name that implements the YourInterface as String.
if you want to get all instances - use map.values()
if you want to get specific instance - get it by class name.
in additional, you can customize the key by another recognize such as Enum.
in this case - you need to configure this as #Bean
as bellow :
#Configuration
public class CalculationHandlerConfig {
#Bean
public HashMap<OperatorTypeEnum, CalculatorService> CalculationHandlers(Map<String, CalculatorService> beansMap) {
HashMap<OperatorTypeEnum, CalculatorService> map = new HashMap<>();
for (CalculatorService bean : beansMap.values()) {
map.put(bean.getOperatorType(), bean);
}
return map;
}
}
It looks like it could be dependent on the version of Spring being used, however, you may also want to try using an interface that all the desired classes implement, and injecting the list referencing the interface.
In other words, instead of this..
List<AbstractOrConcreteBaseClass>
use...
List<Interface>

Spring can you autowire inside an abstract class?

Spring is failing to autowire my object? Is it possible to autowire an object within an abstract class. Assume all schemas are supplied in application-context.xml
Question: What annotation should be on the base and extending classes (if any) #Service #Component?
Example
abstract class SuperMan {
#Autowire
private DatabaseService databaseService;
abstract void Fly();
protected void doSuperPowerAction(Thing thing) {
//busy code
databaseService.save(thing);
}
}
Extending class
public class SuperGirl extends SuperMan {
#Override
public void Fly() {
//busy code
}
public doSomethingSuperGirlDoes() {
//busy code
doSuperPowerAction(thing)
}
application-context.xml
<context:component-scan base-package="com.baseLocation" />
<context:annotation-config/>
I have that kind of spring setup working
an abstract class with an autowired field
public abstract class AbstractJobRoute extends RouteBuilder {
#Autowired
private GlobalSettingsService settingsService;
and several children defined with #Component annotation.
Normally, Spring should do the autowiring, as long as your abstract class is in the base-package provided for component scan.
See this and this for further reference.
#Service and #Component are both stereotypes that creates beans of the annotated type inside the Spring container. As Spring Docs state,
This annotation serves as a specialization of #Component, allowing for
implementation classes to be autodetected through classpath scanning.
What if you need any database operation in SuperGirl you would inject it again into SuperGirl.
I think the main idea is using the same object reference in different classes.
So what about this:
//There is no annotation about Spring in the abstract part.
abstract class SuperMan {
private final DatabaseService databaseService;
public SuperMan(DatabaseService databaseService) {
this.databaseService = databaseService;
}
abstract void Fly();
protected void doSuperPowerAction(Thing thing) {
//busy code
databaseService.save(thing);
}
}
#Component
public class SuperGirl extends SuperMan {
private final DatabaseService databaseService;
#Autowired
public SuperGirl (DatabaseService databaseService) {
super(databaseService);
this.databaseService = databaseService;
}
#Override
public void Fly() {
//busy code
}
public doSomethingSuperGirlDoes() {
//busy code
doSuperPowerAction(thing)
}
In my opinion, inject once run everywhere :)
In my case, inside a Spring4 Application, i had to use a classic Abstract Factory Pattern(for which i took the idea from - http://java-design-patterns.com/patterns/abstract-factory/) to create instances each and every time there was a operation to be done.So my code was to be designed like:
public abstract class EO {
#Autowired
protected SmsNotificationService smsNotificationService;
#Autowired
protected SendEmailService sendEmailService;
...
protected abstract void executeOperation(GenericMessage gMessage);
}
public final class OperationsExecutor {
public enum OperationsType {
ENROLL, CAMPAIGN
}
private OperationsExecutor() {
}
public static Object delegateOperation(OperationsType type, Object obj)
{
switch(type) {
case ENROLL:
if (obj == null) {
return new EnrollOperation();
}
return EnrollOperation.validateRequestParams(obj);
case CAMPAIGN:
if (obj == null) {
return new CampaignOperation();
}
return CampaignOperation.validateRequestParams(obj);
default:
throw new IllegalArgumentException("OperationsType not supported.");
}
}
}
#Configurable(dependencyCheck = true)
public class CampaignOperation extends EO {
#Override
public void executeOperation(GenericMessage genericMessage) {
LOGGER.info("This is CAMPAIGN Operation: " + genericMessage);
}
}
Initially to inject the dependencies in the abstract class I tried all stereotype annotations like #Component, #Service etc but even though Spring context file had ComponentScanning for the entire package, but somehow while creating instances of Subclasses like CampaignOperation, the Super Abstract class EO was having null for its properties as spring was unable to recognize and inject its dependencies.After much trial and error I used this **#Configurable(dependencyCheck = true)** annotation and finally Spring was able to inject the dependencies and I was able to use the properties in the subclass without cluttering them with too many properties.
<context:annotation-config />
<context:component-scan base-package="com.xyz" />
I also tried these other references to find a solution:
http://www.captaindebug.com/2011/06/implementing-springs-factorybean.html#.WqF5pJPwaAN
http://forum.spring.io/forum/spring-projects/container/46815-problem-with-autowired-in-abstract-class
https://github.com/cavallefano/Abstract-Factory-Pattern-Spring-Annotation
http://www.jcombat.com/spring/factory-implementation-using-servicelocatorfactorybean-in-spring
https://www.madbit.org/blog/programming/1074/1074/#sthash.XEJXdIR5.dpbs
Using abstract factory with Spring framework
Spring Autowiring not working for Abstract classes
Inject spring dependency in abstract super class
Spring and Abstract class - injecting properties in abstract classes
Spring autowire dependency defined in an abstract class
Please try using **#Configurable(dependencyCheck = true)** and update this post, I might try helping you if you face any problems.

Resources