Spring AOP: UnsatisfiedDependencyException error with configuration with annotation - java

I'm having a trouble while configuring Spring AOP.
I created an aspect class which is below:
#Slf4j
#Aspect
#RequiredArgsConstructor
#Component
public class LoggingAspect {
private static final Logger logger = CommonLogger.getLogger(LoggingAspect.class);
private final ObjectMapper mapper;
private final JobExecutionService jobExecutionService;
}
Then I added a configuration file:
#Configuration
#EnableAspectJAutoProxy(proxyTargetClass = true)
#RequiredArgsConstructor
public class AspectConfiguration {
private final ObjectMapper objectMapper;
private final JobExecutionService jobExecutionService;
#Bean
public LoggingAspect loggingAspect() {
return new LoggingAspect(objectMapper, jobExecutionService);
}
}
But when I started the application, I am getting below errors:
Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.context.support.ClassPathXmlApplicationContext]: Constructor threw exception; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'aspectConfiguration' defined in URL: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.fasterxml.jackson.databind.ObjectMapper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
I have added aspectjrt and aspectjweaver dependencies to pom.xml.
Spring version is 4.3.6
I couldn't figure out where the problem is. Any help would be appreciated.

Add class:
#Configuration
public class BeanConfig {
#Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
}

Related

Spring #Bean Inject Enum

In my Config I define two beans of the same class that differ in the value of an enum:
#Bean
public MyClass myClassNew() {
return new MyClass(Source.NEW);
}
#Bean
public MyClass myClassOld() {
return new MyClass(Source.OLD);
}
The Class looks like this:
#Component
#RequiredArgsConstructor
public class MyClass {
private final Source source; // Source is an enum
}
When I autowire a bean in a test:
public class MyClassTest {
#Autowired
private MyClass myClassNew;
}
Spring gives me the following error:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type '...AClass$Source' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
This is totally weird. Why does Spring trying to find a bean of an enum?

MappingMongoConverter not available for autowiring on unit test with #EnableMongoAuditing

I have a spring boot application where I have enabled mongo auditing. The application starts fine and stores mongo documents with all auditing fields (createdDate, updatedDate, etc.). However, when running unit test I get the following exception:
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoAuditingHandler': Cannot create inner bean '(inner bean)#115c946b' of type [org.springframework.data.mongodb.config.MongoAuditingRegistrar$MongoMappingContextLookup] while setting constructor argument; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name '(inner bean)#115c946b': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.data.mongodb.core.convert.MappingMongoConverter' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name '(inner bean)#115c946b': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.data.mongodb.core.convert.MappingMongoConverter' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.data.mongodb.core.convert.MappingMongoConverter' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Here is my main class
#SpringBootApplication
#EnableMongoAuditing
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(PatientstoreApplication.class, args);
}
}
And here is my test class:
#WebMvcTest(TestController.class)
public class TestTest {
#Autowired MockMvc mockMvc;
#MockBean TestService testService;
#Test
public void test() {
}
}
A reproducible example can be found here: https://github.com/jota87r/testapp
My question is: is there any configuration missing? should I manually create a bean of type for MappingMongoConverter for my test cases?
You can mock the MappingMongoConverter.class.
So your test class should be as follows:
#WebMvcTest(TestController.class)
public class TestTest {
#Autowired
MockMvc mockMvc;
#MockBean
TestService testService;
//Mock MappingMongoConverter
#MockBean
private MappingMongoConverter mappingMongoConverter;
#Test
public void test() {
}
I encountered the same situation.
In your #WebMvcTest class, try to add a test configuration like:
#TestConfiguration
static class TestConfig {
#Bean
public MappingMongoConverter mongoConverter() {
return new MappingMongoConverter(mock(DbRefResolver.class), mock(MappingContext.class));
}
}

Can we Autowired below class into Configuration class in springboot

I have a Component class and a config class,so can we autowire component class which uses #value internally,I tried using it but it throws exception,Can anyone please help me understanding
#Component
public class UserAction {
#Value("${cp.user.name}")
private String userName;
#Value("${cp.user.actiontype}")
private String actionType;
#Value("${cp.user.designation}")
protected Designation designation;
public void show() {
System.out.println(userName);
System.out.println(actionType);
System.out.println(designation);
}
}
#Configuration
#ComponentScan("com.example")
public class AppConfig {
#Autowired
UserAction userAction;
------
}
So My question is : can I autowire my UserAction bean into my AppConfig class?
I tried using it but its throwing exception,so can we autowire a component which internally uses #value :
Unable to start web server; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'AppConfig ': Unsatisfied dependency expressed through field 'userAction'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userAction': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'cp.user.actiontype' in value "${cp.user.actiontype}"
Yes you can Autowire beans in Configuration class, but the issue here is that a property in your bean has no value set in properties/yml file
#Value("${cp.user.actiontype}")
set the property cp.user.actiontype in your .properties or .yml file

Do not register the component if there are no dependent beans using spring-boot-starter

I create spring-boot-starter, which registers some bean:
#Configuration
#EnableConfigurationProperties(ClusterJProperties.class)
#ConditionalOnProperty(prefix = "clusterj", name = {"connectString", "dataBaseName"})
public class ClusterJAutoConfiguration {
private final ClusterJProperties clusterJConfigProperties;
#Autowired
public ClusterJAutoConfiguration(ClusterJProperties clusterJConfigProperties) {
this.clusterJConfigProperties = clusterJConfigProperties;
}
#Bean
#ConditionalOnMissingBean
public SessionFactory sessionFactory() {
Properties clusterJProperties = new Properties();
clusterJProperties.setProperty("com.mysql.clusterj.connectstring", clusterJConfigProperties.getConnectString());
clusterJProperties.setProperty("com.mysql.clusterj.database", clusterJConfigProperties.getDataBaseName());
clusterJProperties.putAll(clusterJConfigProperties.getProperties());
return ClusterJHelper.getSessionFactory(clusterJProperties);
}
}
I want using this starter in another module. For this, I created a component, and inject this bean there:
#Component
public class GetEntityHandler implements VoidTreeNodeHandler {
private final SessionFactory sessionFactory;
#Autowired
public GetEntityHandler(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
#Override
public void handle(TreeContext context, Map<String, Object> parameters) {
//do smth
}
}
But, when, properties clusterj.connectString and clusterj.connectString not present in application.yml, bean SessionFactory not create. It is ok, but GetEntityHandler want to create, and fall with error:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'getEntityHandler' defined in file [GetEntityHandler.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.mysql.clusterj.SessionFactory' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
How to make my GetEnityNandler component not be created if the SessionFactory bean is not present in context?

Autowiring fails in Junit testing and spring #configuration

I have two #Configuration classes. I need a bean from one configuration class to another. I have autowired the configuration 1 into 2. All works fine. When executing the unit testing, am getting the below exception.
setUpContext(com.trafigura.titan.framework.services.messaging.loader.SpringLoadTest)
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.xxx.MessagingServicesConfig': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.xxx.EMSJMSConfig com.xxx.MessagingServicesConfig.emsJmsConfig;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type[com.xxx.EMSJMSConfig] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Is there anything I need to do additionally to make this working?
Below is the setup for testing.
#Configuration
#Import({MessagingServicesConfig.class,...,EMSJMSConfig.class
})
public class MessagingConfig {}
#Profile("EMS-MESSAGING")
#Configuration
public class EMSJMSConfig {
#Bean
public javax.jms.ConnectionFactory jmsSubscriberConnectionFactory() throws JMSException {
SingleConnectionFactory singleConnectionFactory = new SingleConnectionFactory(tibjmsConnectionFactory());
return singleConnectionFactory;
}
}
#Configuration
public class MessagingServicesConfig {
#Autowired
private EMSJMSConfig emsJmsConfig;
#Bean(destroyMethod = "shutdown")
public MessagingService messagingService() throws JMSException {
...
ConnectionFactory cf=emsJmsConfig.jmsSubscriberConnectionFactory(); // Getting NPE at this line.
}
}
and finally the test class,
public class MessagingServicesConfigTest {
private MessagingServicesConfig config;
private EMSJMSConfig emsJmsConfig;
#BeforeMethod
public void setUp() throws Exception {
config = new MessagingServicesConfig();
... //what needs to be done here to have the EMSJMSConfig
}
#Test
public void testBuildsCorrectService() throws JMSException {
MessagingService service = config.messagingService();
...
}
}
By calling new you're creating object yourself, Spring doesn't know anything about it.
Moreover, you should have a test configuration which will be aware of your beans.
Use an appropriate Runner to load SpringContext.
#ContextConfiguration(classes = TestConfig.class)
#RunWith(SpringRunner.class)
class Tests {
#Autowired // if needed
private MessagingServicesConfig config;
}
While in TestConfig you can create beans or import configuration from the Application:
#Configuration
#Import({MessagingServicesConfig.class})
public class TestConfig {}
#Configuration
#Import({EMSJMSConfig.class})
public class MessagingServicesConfig {}
Or you can refer to your config classes directly:
#ContextConfiguration(classes = {MessagingServicesConfig.class, EMSJMSConfig.class})

Categories