INTERFACES proxy mode and #Qualifier doesn't work - java

Why I get an Exception when using #Qualifier and Interfaces proxy mode?
Error creating bean with name 'aopTest.TestBeanContainer': Unsatisfied
dependency expressed through field 'beanA'; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type 'pl.springui.components.HTMLRenderer'
available: expected at least 1 bean which qualifies as autowire
candidate. Dependency annotations:
{#org.springframework.beans.factory.annotation.Qualifier(value=a),
#org.springframework.beans.factory.annotation.Autowired(required=true)}
#EnableCaching
#Configuration
#ComponentScan(value = { "test.proxy" })
#EnableAspectJAutoProxy(proxyTargetClass = true)
public class AopTest {
#Test
public void testCache() {
ApplicationContext context = new AnnotationConfigApplicationContext(AopTest.class);
TestBeanContainer bean = context.getBean(TestBeanContainer.class);
bean.test();
bean.test();
}
#Component
#Scope(value = "prototype")
static class TestBeanContainer extends BaseBean {
#Qualifier("a")
#Autowired
HTMLRenderer beanA;
public void test() {
BaseBean.print(beanA);
}
public TestBeanContainer() {
super();
}
}
#Qualifier("a")
#Component
#EqualsAndHashCode
#Scope(value = "singleton", proxyMode = org.springframework.context.annotation.ScopedProxyMode.INTERFACES)
class BeanA extends BaseBean implements HTMLRenderer {
}
}
When I change #Qualifier to #Primary I don't get any exceptions but a new beanA is created when test() method is executed on the same object.
test executed:
NEW:BeanA [id=5]
BeanA [id=5] |$Proxy27
test executed:
NEW:BeanA [id=6]
BeanA [id=6] |$Proxy27

Related

SpringBoot - activiti - Injecting org.activiti.engine.TaskService

I've created this class:
public class ActivitiWorkflowService {
private final TaskService taskService;
..
}
but I have this problem when init the project:
No qualifying bean of
type 'org.activiti.engine.TaskService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
I expect that your class has a constructor such as:
public class ActivitiWorkflowService {
private final TaskService taskService;
public ActivitiWorkflowService(TaskService taskService) {
this.taskService = taskService;
}
}
The error you are getting is because Spring cannot autowire this class to the ActivitiWorkflowService - it probably was not defined in the Spring context.
Depending on the configuration you use you can either:
Define class with #Component or #Service annotation and let #ComponentScan do its work:
#Component //#Service
public TaskService {
...
}
or if you are using #Configuration class define the bean of type TaskService
#Configuration
public class AppConfig {
#Bean
public TaskService taskService() {
return new TaskService();
}
#Bean
public ActivitiWorkflowService activitiWorkflowService(TaskService taskService) {
return new ActivitiWorkflowService(taskService);
}
}

Spring Boot WebFluxTest test, failed to instantiate repository, specified class is an interface

I am writing the integration tests with #WebFluxTest for my #RestController.
Here are my classes:
#RestController
#RequestMapping("/usager")
public class UsagerController {
#Autowired
private UsagerService usagerService;
#GetMapping
public Usager getUsager() {
return usagerService.create();
}
}
#Service
public class UsagerService implements CrudService<Usager, Integer> {
#Autowired
private UsagerRepository usagerRepository;
#Override
public JpaRepository<Usager, Integer> getRepository() {
return usagerRepository;
}
#Override
public Usager create() {
return new Usager();
}
}
#Repository
public interface UsagerRepository extends JpaRepository<Usager, Integer>, JpaSpecificationExecutor<Usager> {
}
#ExtendWith(SpringExtension.class)
#WebFluxTest(UsagerController.class)
#Import({ UsagerService.class, UsagerRepository.class })
#Tag(TestCase.INTEGRATION)
public class UsagerControllerIT {
#Autowired
private WebTestClient wtc;
#Test
public void getUsager_returnUsager() {
ResponseSpec rs = wtc.get().uri("/usager").exchange();
rs.expectStatus().isOk();
rs.expectHeader().contentType(MediaType.APPLICATION_JSON);
rs.expectBody(Usager.class).isEqualTo(new Usager());
}
}
I get the following exception:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.dsi.bibliosys.biblioback.repository.UsagerRepository]: Specified class is an interface
I don't understand why Spring can't inject the repository.
Does somebody have an idea ?
I tried another approach using #SpringBootTest. Here is my new test class :
#ExtendWith(SpringExtension.class)
#SpringBootTest
#Tag(TestCase.INTEGRATION)
public class UsagerController02IT {
#Autowired
private UsagerController usagerController;
#Test
public void getUsager_returnUsager() {
WebTestClient wtc = WebTestClient.bindToController(usagerController).build();
ResponseSpec rs = wtc.get().uri("/usager").exchange();
rs.expectStatus().isOk();
rs.expectHeader().contentType(MediaType.APPLICATION_JSON);
rs.expectBody(Usager.class).isEqualTo(new Usager());
}
}
I get this exception:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.dsi.bibliosys.biblioback.controller.UsagerController': Unsatisfied dependency expressed through field 'usagerService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.dsi.bibliosys.biblioback.service.entity.UsagerService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I don't understand why UserService is not available in the application context.
Thanks for your help.
This looks very similar to this. I'd suggest investigating your test configuration and adding it if appropriate.
A quote from Spring on #WebFluxTest
Using this annotation will disable full auto-configuration and instead apply only configuration relevant to WebFlux tests (i.e. #Controller, #ControllerAdvice, #JsonComponent, Converter/GenericConverter, and WebFluxConfigurer beans but not #Component, #Service or #Repository beans).

run #Component after #Repository in Spring Framework

I'm using Redis in a spring project and I define a #Component class that uses Redis repository with #Autowire, but when debugging the application, #Component class constructor runs before bean to connect to Redis, therefore the application exits with this error :
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataManager' defined in file [/mnt/D/ms/projects/EventDetection/out/production/classes/ir/rahati/data/datamanager/DataManager.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'ir.rahati.data.messagegraph.redis.RedisMessageGraphRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
DataManager class
#Component
public class DataManager {
private final RedisMessageGraph messageGraph;
#Autowired
public DataManager( RedisMessageGraphRepository redisMessageGraphRepository) {
this.messageGraph=new RedisMessageGraph(redisMessageGraphRepository);
}
}
Redis repository interface
#Repository
public interface RedisMessageGraphRepository extends CrudRepository<MessageGraphModel, String> {
}
Configuration Class
#Configuration
#EnableRedisRepositories("ir.rahati.data.messagegraph")
public class RedisMessageGraphConfig {
#Bean
JedisConnectionFactory jedisConnectionFactory() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration("localhost", 6379);
redisStandaloneConfiguration.setDatabase(3);
return new JedisConnectionFactory(redisStandaloneConfiguration);
}
#Bean(name = "redis15")
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(jedisConnectionFactory());
return template;
}
}

Spring boot can not autowire repository bean for service test class

I am using a mock repository for my application.
Here is snippet how service looks:
#Service
public class WeatherStationService {
#Autowired
private WeatherStationRepositoryMock weatherRepository;
Here is repository code:
#Repository
public class WeatherStationRepositoryMock {
#Getter
private List<WeatherStation> stations = new ArrayList<>(
Arrays.asList(
new WeatherStation("huston", "Huston station", RandomGenerator.getRandomGeoInformation()),
new WeatherStation("colorado", "Colorado station", RandomGenerator.getRandomGeoInformation())
)
);
It works fine when I am executing main() with #SpringBootApplication.
However, when I want to run test class:
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = MockConfig.class)
#DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
public class WeatherStationServiceTest {
#Autowired
#Real
private WeatherStationService weatherService;
It fails with the following stacktrace:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'edu.lelyak.repository.WeatherStationRepositoryMock' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Here is MockConfig content:
#Configuration
public class MockConfig {
//**************************** REAL BEANS ******************************
#Bean
#Real
public WeatherStationService weatherServiceReal() {
return new WeatherStationService();
}
Real is marker annotation for real instances:
#Retention(RUNTIME)
#Qualifier
public #interface Real {
}
I can fix it with next initialization at service:
#Service
public class WeatherStationService {
private WeatherStationRepositoryMock weatherRepository = new WeatherStationRepositoryMock();
It works fine.
Why does this happen?
How to fix autowiring for my custom repository class?
#SpringBootApplication implicitly defines #ComponentScan, which scans all subpackages for beans.
When you run a test using MockConfig's, it doesn't scan for beans.
Solution - use #ComponentScan OR define beans in MockConfig
(1) Using #ComponentScan:
#Configuration
#ComponentScan //Make sure MockConfig is below all beans to discover
public class MockConfig {
#Bean
#Real
public WeatherStationService weatherServiceReal() {
return new WeatherStationService();
}
}
(2) or define required beans:
#Configuration
public class MockConfig {
#Bean
#Real
public WeatherStationService weatherServiceReal() {
return new WeatherStationService();
}
#Bean
public WeatherStationRepositoryMock weatherStationRepository() {
return new WeatherStationRepositoryMock()
}
}

Spring-Boot create bean with out name will cause "NoSuchBeanDefinitionException, No qualifying bean of type[]found for dependency "

I Create the bean by configuration with out name
#Configuration
#ConfigurationProperties(prefix = "mysql")
public class DbConfiguration extends BaseDbConfiguration {
#Bean//(name = "fix")
#Override
public DbClient createClient() {
return super.createClient();
}
}
usage:
#Autowired
private DbClient dbClient;
when I running application it can't start up
And throw NoSuchBeanDefinitionException:
No qualifying bean of type [DbClient] 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)}
But I fix it by add name, why??
#Bean(name = "fix")
I also add a test such like this:
public class TestCreate {
#NotNull
private int test;
public Test createTest() {
return new Test(this.test);
}
}
it configuration like this:
#Configuration
#ConfigurationProperties(prefix = "test")
public class TestConfiguration extends TestCreate {
#Override
#Bean
public Test createTest() {
return super.createTest();
}
}
And autowired like this:
#Autowired
private Test test;
However, this test may work well
It also create Bean without name and Autowired with out Qualifier
Please Tell me why....thanks
Sorry.
I have found the results:
Overriding bean definition for bean 'createClient': replacing ...
So Spring-Boot will create Bean by FunctionName rather than returning ObjectName.

Categories

Resources