Spring #Bean Inject Enum - java

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?

Related

Error creating Bean of Type Crudrepository; SpringBootTest

I am trying to test my spring Repository with JdbcTest; I am using JDBC's Crudrepository so i want to autowire it into my Test class:
#JdbcTest
#ActiveProfiles("test")
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = {CRUDStudent.class, CRUDKlausur.class})
#TestPropertySource(locations = {"classpath:testEnv"})
public class KlausurRepositoryImplTest {
#Autowired
CRUDKlausur db;
#Test
#Sql({"classpath:db/migration/V1__init.sql"})
#DisplayName("MyTest")
void test1() {
}
}
But on Execution i get this:
No qualifying bean of type 'de.propra.chicken.db.CRUDKlausur' available: expected at least 1 bean which qualifies as autowire candidate.
The interface is annotated with #Repository, so it should count as a valid Bean.
#Repository
public interface CRUDKlausur extends CrudRepository<KlausurDTO, Long> {

How to inject mocks with Springboot?

I want to inject a mock into my Springboot application. I get this error:
Error creating bean with name 'ca.company.TestA': Unsatisfied dependency expressed through field 'a'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'ca.company.hello.A' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I'm stuck and don't understand how to process. I Defined A to be autowired. What's the problem?
Here is my test file:
#RunWith(SpringJUnit4ClassRunner.class)
public class TestA {
#Autowired
private A a;
private B Bmock;
#Before
public void before() {
Bmock = Mockito.mock(B.class);
ReflectionTestUtils.setField(a, "b", Bmock);
}
#Test
public void testSpeak() {
when(Bmock.writeToScreen()).thenReturn("Everything will be alright");
assert(true);
}
}
here is the config file:
#Configuration
public class Config {
#Bean
public B b() {
return new B();
}
// The error persists whether I define this bean or not
#Bean
public A a() {
return new A();
}
}
And here is the class in question:
#Component
public class A {
#Autowired
private B b;
public void speak() {
System.out.println(b.writeToScreen());
}
}
And finally here is my file structure:
What am I doing wrong, I don't get it.
Your configuration class is not processed by Spring. The simplest way to achieve that is to put #ContextConfiguration(classes = Config.class) in your test class.

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})

NoSuchBeanDefinitionException when injecting javax.inject.Provider<T> to constructors using Spring

I'm using constructor-based dependency injection to inject a javax.inject.Provider<T> to a service. With Spring Framework (4.2.5), NoSuchBeanDefinitionException will be thrown saying "No qualifying bean of type [T] found for dependency. Why is T expected by Spring while injecting javax.inject.Provider<T>?
Here's the sample code:
Provider:
import javax.inject.Provider;
public class MessageProvider implements Provider<String> {
#Override
public String get() {
return "Hello!";
}
}
Service:
import javax.inject.Inject;
import javax.inject.Provider;
public class GreetingService {
private final String message;
#Inject
GreetingService(Provider<String> provider) {
// GreetingService(MessageProvider provider) { // this works!
this.message = provider.get();
}
public String greeting() {
return message;
}
}
Test:
import org.junit.Test;
import static org.junit.Assert.*;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class GreetingServiceTest {
#Test
public void testSomeMethod() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(MessageProvider.class);
ctx.register(GreetingService.class);
ctx.refresh();
GreetingService bean = ctx.getBean(GreetingService.class);
String message = bean.greeting();
assertNotNull(message);
}
}
And here's the error message:
Error creating bean with name 'greetingService': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [GreetingService]: Constructor threw exception; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
You're question is a bit ambiguous. Are you asking why Spring needs a bean that can create a T or are you asking why Spring isn't injecting an instance of your MessageProvider class?
If your question is the former then the problem you are facing is that Provider<T> is an interface, not a class. When you inject Provider<String> Spring says, "Hmm, I don't see any bean definition for the Provider interface, is there another way I can satisfy this dependency?" And Spring's answer is, "Yes, I can create an instance of org.springframework.beans.support.DefaultListableBeanFactory$DependencyProvider, but only if I know how to create T, i.e. there is a bean definition for T."
Your sample code should work if you added a configuration class to define a bean of type String:
#Configuration
public class MyConfiguration
{
#Bean
public String getMessage()
{
return "Hello!";
}
}
But if you are asking why Spring isn't injecting an instance of your MessageProvider class I suspect the problem is that it's not properly defined. You could add a qualifier to the MessageProvider definition and usage
#Component("MyMessageProvider")
public class MessageProvider implements Provider<String> {
...
and
#Inject
GreetingService(#Qualifier("MyMessageProvider") Provider<String> provider) {
...
to say exactly which Provider implementation you want injected.

Categories