I have this enum, used in a dto.
public enum MetadataType {
TRANSACTION(new TransactionMetadataHandler());
private MetadataHandler handler;
public MetadataHandler getHandler() {
return handler;
}
MetadataType(MetadataHandler handler) {
this.handler = handler;
}
}
public class MetadataInfo {
private MetadataType type;
public MetadataType getType() {
return this.type;
}
}
The idea being to be able to change what handler is used for each metadata type.
This is used in a service. Note, everything is simplified here. There are many functions that I want to be able to perform on any type of metadata without having a giant switch statement.
@Service
public class MetadataService {
public String formatMetadata(MetadataInfo info) {
String formattedMetadata = info.getType().getHandler().format(info);
return formattedMetadata;
}
}
public interface MetadataHandler {
String formatMetadata(MetadataInfo info);
}
@Configurable
public class TransactionMetadataHandler implements MetadataHandler {
@Autowired
private SomeOtherBean someOtherBean;
public String formatMetadata(MetadataInfo info) {
someOtherBean.doSomething(); // NullPointerException here
}
}
How do I fix this NullPointerException? It's like the enum is being processed too early and Spring never gets around to autowiring the TransactionMetadataHandler
. Not sure what to do here.
CodePudding user response:
When the Enums are constructed on project startup, Spring hasn't had a chance to get up and running yet. So, instead, we can do this.
public enum MetadataType {
TRANSACTION(TransactionMetadataHandler.class);
private Class<? extends MetadataHandler> handlerClass;
public MetadataHandler getHandlerClass() {
return handlerClass;
}
MetadataType(Class<? extends MetadataHandler> handlerClass) {
this.handlerClass = handlerClass;
}
}
And then in the service, use reflection to get an instance.
@Service
public class MetadataService {
public String formatMetadata(MetadataInfo info) {
try {
String formattedMetadata = info.getType().getHandlerClass().newInstance().format(info);
return formattedMetadata;
} catch (InstantiationException | IllegalAccessException e) {
// do whatever with the exception
}
}
}
This way, though nothing material changes, since the instantiation of TransactionMetadataHandler
is at runtime, Spring will actually be up and running, and so will field-inject properly.
CodePudding user response:
What version of java and aspectj-maven-plugin are you using ? When i follow step mentioned in https://www.baeldung.com/aspectj i got the null pointer exception , however i had to replace codehaus plugin with `
<plugins>
<plugin>
<groupId>dev.aspectj</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.13.M3</version>
<configuration>
<complianceLevel>16</complianceLevel>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
` on java version 16 and then compile team weaving worked fine for @Configurable annotation