Spring boot - #Autowired is not working on #Configuration class - spring-boot

I used #ComponentScan on the Application class and use the #Configuration on my config class, in my config class, I want to inject beans defined in other config class by using #Autowired annotation, but when I run the application, I got null for these fields.
#Configuration
public class AConfiguration {
#Bean
public A getA(){
return ..;
}
}
#Configuration
public class BConfiguration {
#Autowired
private A a;
#Bean
public B getB() {
**something need a, but a is null**
}
}
#EnableCaching
#Configuration
public class EhcacheConfiguration extends CachingConfigurerSupport {
#Bean
#Override
public CacheManager cacheManager() {
return new EhCacheCacheManager(ehCacheCacheManager().getObject());
}
#Bean
public EhCacheManagerFactoryBean ehCacheCacheManager() {
EhCacheManagerFactoryBean cmfb = new EhCacheManagerFactoryBean();
cmfb.setConfigLocation(new ClassPathResource("ehcache.xml"));
cmfb.setShared(true);
return cmfb;
}
}
#Configuration
#DependsOn("ehcacheConfiguration")
public class ShiroConfiguration {
#Autowired
private org.springframework.cache.CacheManager cacheManager;
}
#SpringBootApplication
#EnableTransactionManagement
public class JarApplication {
public static void main(String[] args) {
SpringApplication.run(JarApplication.class, args);
}
}

You can try this.
#Configuration
public class AConfiguration {
#Bean
public A getA(){
return ..;
}
}
#Configuration
public class BConfiguration {
#Autowired
private A a;
public B getB() {
**something need a, but a is null**
}
}

Related

Why did #TestConfiguration not create a bean for my test?

My service
#Service
public class StripeServiceImpl implements StripeService {
#Override
public int getCustomerId() {
return 2;
}
}
My test
public class StripeServiceTests {
#Autowired
StripeService stripeService;
#TestConfiguration
static class TestConfig {
#Bean
public StripeService employeeService() {
return new StripeServiceImpl();
}
}
#Test
public void findCustomerByEmail_customerExists_returnCustomer() {
assertThat(stripeService.getCustomerId()).isEqualTo(2);
}
}
The error: java.lang.NullPointerException. I had checked and the stripeService is actually null.
Since you are autowiring you need an applicationcontext so that Spring can manage the bean and then can get injected in your class. Therefore you are missing an annotation to create the applicationcontext for your testclass.
I have updated your code and it works now(with junit 5 on your classpath). In the case dat you are using junit 4 it should be #RunWith(SpringRunner.class) instead of #ExtendWith(SpringExtension.class):
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = TestConfiguration.class)
public class StripeServiceTests {
#Autowired
StripeService stripeService;
#TestConfiguration
static class TestConfig {
#Bean
public StripeService employeeService() {
return new StripeServiceImpl();
}
}
#Test
public void findCustomerByEmail_customerExists_returnCustomer() {
assertThat(stripeService.getCustomerId()).isEqualTo(2);
}
}

Spring configuration - Autowired bean required?

I have the situation where a protoype bean contains a singleton bean. In order to achieve it, I had to create 2 configuration classes. Is it possible to merge my 2 confgiuration classes into a single one?
Singleton class:
public class MySingleton {
}
Prototype class:
public class MyPrototype {
private MySingleton b;
public MyPrototype(MySingleton b) {
this.b = b;
}
}
Configuration class 1:
#Configuration
public class ConfigClassA {
#Bean
public MySingleton myBean() {
return new MySingleton();
}
}
Configuration class 2:
#Configuration
public class ConfigClassB {
#Autowired
public MySingleton mb;
#Bean
#Scope("prototype")
public MyPrototype myPrototype() {
return new MyPrototype(mb);
}
}
Try this:
#Configuration
public class ConfigClass {
#Bean
public MySingleton myBean() {
return new MySingleton();
}
#Bean
#Scope("prototype")
public MyPrototype myPrototype(MySingleton myBean) {
return new MyPrototype(myBean);
}
}
The BeanFactory should search for a bean of type MySingleton when creating the prototype bean and inject it into the method myPrototype.

Spring - access #Autowired service from AbstractMessageHandler

I have a SpringBootApplication which subscribes to MQTT broker. MQTT messages need to be saved to Database, but I cannot access my #Autowired service.
Exception I get:
Field deviceService in com.example.MqttMessageHandler required a bean of type 'com.example.service.DeviceService' that could not be found.
MQTTApiApplication.java
#SpringBootApplication(scanBasePackages = "{com.example}")
public class MQTTApiApplication {
public static void main(String[] args) {
SpringApplicationBuilder(MQTTApiApplication.class)
.web(false).run(args);
}
#Bean
public IntegrationFlow mqttInFlow() {
return IntegrationFlows.from(mqttInbound())
.handle(new MqttMessageHandler())
.get();
}
}
MqttMessageHandler.java
public class MqttMessageHandler extends AbstractMessageHandler {
#Autowired
DeviceService deviceService;
#Override
protected void handleMessageInternal(Message<?> message) throws Exception {
deviceService.saveDevice(new Device());
}
}
Application.java
#SpringBootApplication
public class MQTTApiApplication {
public static void main(String[] args) {
SpringApplication.run(MQTTApiApplication.class, args);
}
#Bean
public IntegrationFlow mqttinFlow(MqttMessageHandler handler) {
return IntegrationFlows
.from(mqttInbound())
.handle(handler).get();
}
}
MqqtMessageHandler.java
#Component
public class MqttMessageHandler extends AbstractMessageHandler{
#Autowired
private DeviceService deviceService;
#Override
protected void handleMessageInternal(String message) {
//...
}
}
DeviceService.java
#Service
public class DeviceService {
#Autowired
private DeviceRepository repository;
//...
}
DeviceController.java
#RestController
#RequestMapping("/")
public class DeviceController {
#Autowired
private IntegrationFlow flow;
//...
}
DeviceRepository.java
#Repository
public class DeviceRepository {
public void save() {
//...
}
}

Mocking beans in spring context using Spring Boot

I'm using Spring Boot 1.3.2, and I notice problem, ComponentScan in my test class is not working. And I want to mock some of Spring Beans. Is spring boot blocking ComponentScan?
Test config class:
#Configuration
#ComponentScan(value = {"myapp.offer", "myapp.image"})
public class TestEdge2EdgeConfiguration {
#Bean
#Primary
public OfferRepository offerRepository() {
return mock(OfferRepository.class);
}
}
Test class:
#ContextConfiguration(classes=TestEdge2EdgeConfiguration.class, loader=AnnotationConfigContextLoader.class)
public class OfferActionsControllerTest extends AbstractTestNGSpringContextTests {
#Autowired
private OfferRepository offerRepository;
#Autowired
private OfferActionsController offerActionsController;
#BeforeMethod
public void setUp(){
MockitoAnnotations.initMocks(this);
}
#Test
public void saveOffer() {
//given
BDDMockito.given(offerRepository.save(any(Offer.class))).willReturn(new Offer());
//when
ResponseEntity<Offer> save = offerActionsController.save(new Offer());
//then
org.springframework.util.Assert.notNull(save);
}
}
Solution of this problem
Test config class, it's important to exclude SpringBootApplicationConfigutation and add #ComponentScan:
#ComponentScan(basePackages = "com.example", excludeFilters =
#ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
value = {SpringBootApplicationConfigutation.class, MyDao.class}
)
)
#Configuration
public class TestEdge2EdgeConfiguration {
#Bean
public OfferRepository offerRepository() {
return mock(OfferRepository.class);
}
}
And test:
#SpringApplicationConfiguration(classes=TestEdge2EdgeConfiguration.class)
public class OfferActionsControllerTest extends AbstractTestNGSpringContextTests {
#Autowired
private OfferRepository offerRepository;
#Autowired
private OfferActionsController offerActionsController;
#BeforeMethod
public void resetMock() {
Mockito.reset(offerRepository);
}
#Test
public void saveOffer() {
//given
BDDMockito.given(offerRepository.save(any(Offer.class))).willReturn(new Offer());
//when
ResponseEntity<Offer> save = offerActionsController.save(new Offer());
//then
org.springframework.util.Assert.notNull(save);
}
}

Issues with a Spring #Configurable class not getting its dependencies autowired

I am trying to configure Load Time Weaving for my Spring Boot app to properly autowire dependencies on a #Configurable java class.
Here is my configuration/main class:
package com.bignibou;
#Configuration
#EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class, ThymeleafAutoConfiguration.class, FlywayAutoConfiguration.class })
#EnableSpringConfigured
#EnableLoadTimeWeaving(aspectjWeaving = AspectJWeaving.ENABLED)
#ComponentScan
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
Here is how I start the application (my gradle build renamed the spring-instrument jar):
java -javaagent:build/lib/springinstrument.jar -jar myapp.jar
Here is the #Configurable class that does not get its dependencies autowired:
package com.bignibou.converter;
#Configurable
public class StringToDayToTimeSlotConverter implements Converter<String, DayToTimeSlot> {
#Autowired
private DayToTimeSlotRepository dayToTimeSlotRepository;//NOT AUTOWIRED!!
#Override
public DayToTimeSlot convert(String id) {
return dayToTimeSlotRepository.findOne(Long.parseLong(id));//NPE HERE!!
}
}
Here is where the class is instantiated (with new):
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "com.bignibou.controller" }, useDefaultFilters = false, includeFilters = { #Filter(type = FilterType.ANNOTATION, value = Controller.class),
#Filter(type = FilterType.ANNOTATION, value = ControllerAdvice.class) })
#Import(ApplicationControllerAdvice.class)
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
...
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new DayToTimeSlotToStringConverter());
registry.addConverter(new StringToDayToTimeSlotConverter());//INSTANTIATED HERE!
registry.addConverter(new LanguageToStringConverter());
registry.addConverter(new StringToLanguageConverter());
registry.addConverter(new AddressToStringConverter());
registry.addConverter(new StringToAddressConverter());
super.addFormatters(registry);
}
Can anyone please help figure out why StringToDayToTimeSlotConverter's dependencies are not autowired?
Very old question with at least a suggestion for a solution that I will turn into an answer so that the question can be "closed". Turn StringToDayToTimeSlotConverter into a Bean as follows:
#Bean
public class StringToDayToTimeSlotConverter implements Converter<String, DayToTimeSlot> {
#Autowired
private DayToTimeSlotRepository dayToTimeSlotRepository;
#Override
public DayToTimeSlot convert(String id) {
return dayToTimeSlotRepository.findOne(Long.parseLong(id));
}
}
Inject all available converters in WebMvcConfiguration as follows:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "com.bignibou.controller" }, useDefaultFilters = false, includeFilters = { #Filter(type = FilterType.ANNOTATION, value = Controller.class),
#Filter(type = FilterType.ANNOTATION, value = ControllerAdvice.class) })
#Import(ApplicationControllerAdvice.class)
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
#Autowired
List<Converter> converters;
#Override
public void addFormatters(FormatterRegistry registry) {
for (Converter converter : converter) {
registry.addConverter(converter);
}
super.addFormatters(registry);
}
}

Resources