Error autowiring an interface class in Spring - java

My code has this set up:
public class myResource() {
#Autowired
ImyHandler myHandler;
....
}
The next layer up contains my handler classes. I have two sets of classes, one is an interface class, and the other is the regular class, like:
public interface myHandler() {
public myObject modifyFunction();
}
and then my regular class looks like:
public class myHandler() {
....
}
However, when I build my project, I get this error:
Error creating bean with name 'myResource': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: ImyHandler
In my context-web.xml file, I declared:
<bean id="myHandler" class="myHandler" />
I'm not sure why I am getting this error, as I explicitly stated that the interface class is in my context. Does anyone understand why this is happening?

You also need to specify the package of the class in the bean that you want to create.

Related

XML bean definitions don't pick up #Component annotated beans in dependency packages

Not sure what i'm missing here but some assistance would be appreciated.
I have a class annotated with #Component as follows in a package com.company.package:
#Component
public class ClassAService {
#Autowired
public ClassAService(ClassB classB) {
....
}
}
Within the same package, I have a second class that utilizes ClassAService in its constructor argument as follows. Note that this class is not annotated with #Component
public class ClassBService {
String id;
#Autowired
public ClassBService(ClassAService classAService) {
....
}
}
Finally, in the main Application that utilizes the package described above, i have the following xml configuration that utilizes ClassBService to create a bean definition as follows:
....
<bean id="classBService" class="com.company.package.ClassBService">
<property name="id" value="abcde" />
</bean>
Finally, i have annotated my run application class with the following:
#SpringBootApplication({
scanBasePackages= {
"com.company.package.*"
})
Given everything above, I would expect the bean defined in the xml file to inject ClassAService correctly and construct the bean. However, I keep getting the following exception
Parameter 0 of constructor in com.company.package.ClassBService required a bean of type 'com.company.package.ClassAService' that could not be found.
However, I have no such issues when I use ClassAService directly in code using #Autowire:
#Service
public class MainService {
#Autowire
public ClassAService classAService
}
It shouldn't make a difference how the beans are declared as they are stored in the application context when the app fully boots up. So what the issue here?

Java Spring Dependency Injection creates two beans, when there should just be one

I want to enable our application to use Springs Dependency Injection. For some reason, some classes get instantiated twice, which leads to an org.springframework.beans.factory.NoUniqueBeanDefinitionException.
The ID of one Bean is just the simple class name, the other is the full name with a #0 at the end:
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'FDDConnectionFactory' defined in file [W:\Projekte\ocp-ospe\ServiceGruppe\osplus.ocp.service.impl\target\classes\osplus\dynssee\ie\ocp\bs\services\fdd\FDDConnectionFactory.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'osplus.dynssee.ie.ocp.bs.services.fdd.FDDParameterResolver' available: expected single matching bean but found 2: FDDDefaultParameterResolver,osplus.dynssee.ie.ocp.bs.services.fdd.FDDDefaultParameterResolver#0
#Component
public class FDDDefaultParameterResolver implements FDDParameterResolver {
private FremdsystemProviderProvider fremdsystemProviderProvider;
#Autowired
public FDDDefaultParameterResolver(FremdsystemProviderProvider fPP) {
this.fremdsystemProviderProvider = fPP;
}
// Some methods
}
#Component
public class FDDConnectionFactory {
#Autowired
public FDDConnectionFactory(FDDParameterResolver fddParams) {
this.fddParams = fddParams;
}
}
I cut down the class to it's bare minimum, as you can see above. But weirdly enough, I'm unable to recreate another minimal example that exhibits the same behaviour. Some injections just work, others don't.
Anybody got some ideas what might be causing this strange behaviour?
It seems the issues was bound to my company's framework, where they already perform some kind of component-scan on specific packages.

How can I use YAML properties with constructor injection in Spring Boot?

I know this should be a piece of cake but I'm just not getting anywhere.
In my Spring Boot app, in the application.yml file, I have an entry like so:
some:
constructor:
property: value
And I have a spring service (this is fake but demonstrates the problem):
package somepackage;
#Service
public class DummyService {
public DummyService(#Value("${some.constructor.property}") String path) {}
}
Startup fails, though:
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'dummyService' defined in file [...(the class
file)... ]: Instantiation of bean failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate [somepackage.DummyService]: No default constructor found;
nested exception is java.lang.NoSuchMethodException:
somepackage.DummyService.()
How can I convince Spring that it should use the non-empty constructor, and it should get that constructor parameter from the YAML file? Note: I'm not using any XML bean config files or anything, and would prefer not to.
Just put the #Autowired annotation on your constructor.
#Autowired
public DummyService(#Value("${some.constructor.property}") String path) {}
And just in case someone else is trying to do this in Scala -- which is what I was really trying to do, but wanted to get the answer in Java before trying it with Scala -- this works:
#Service
class DummyService #Autowired()(#Value("${some.constructor.property}") val path: String) {
}
This is covered in this SO case for scala constructor autowiring.

How to Autowired in ConversionService in springboot

Trying to access the ConversionControl in model in springboot, no luck.
#Component
public class CityHelperService {
#Autowired
ConversionService conversionService;// = ConversionServiceFactory.registerConverters();
public City toEntity(CityDTO dto){
City entity = conversionService.convert(dto, City.class);
return entity;
}
public CityDTO toDTO(City entity){
CityDTO dto = conversionService.convert(entity, CityDTO.class);
return dto;
}
}
It shows the following error:
Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.lumiin.mytalk.model.CityModel com.lumiin.mytalk.controllers.CityController.cityModel;
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'cityModel' defined in file : Unsatisfied dependency expressed through constructor argument with index 1 of type [com.lumiin.mytalk.dao.CityHelperService]: : Error creating bean with name 'cityHelperService': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.springframework.core.convert.ConversionService com.lumiin.mytalk.dao.CityHelperService.conversionService;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.core.convert.ConversionService] 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)};
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cityHelperService': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.springframework.core.convert.ConversionService com.lumiin.mytalk.dao.CityHelperService.conversionService;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.core.convert.ConversionService] 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)}
Apparently there is no ConversionService bean available, judging by the last nested exception:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.core.convert.ConversionService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
A look into the Spring documentation reveals, that you should declare a ConversionService bean. In the XML configuration it would look like this:
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="example.MyCustomConverter"/>
</set>
</property>
</bean>
And since you're using Spring Boot, I assume you are creating the context programatically, so you should create a method annotated with #Bean, which returns a ConverstionService, like this (explained here):
#Bean(name="conversionService")
public ConversionService getConversionService() {
ConversionServiceFactoryBean bean = new ConversionServiceFactoryBean();
bean.setConverters(...); //add converters
bean.afterPropertiesSet();
return bean.getObject();
}
Not totally agreed with the accepted answers, because there would be a default ConverstionService named mvcConversionService so you would get duplicate bean exception. Instead addConverter to FormatterRegistry, here is the link for the part answer:
Java Config equivalent for conversionService / FormattingConversionServiceFactoryBean
Also you would need (in some cases) to define to at least an empty Component for ConversionService, something like below:
#Component #Primary
public class MyConversionService extends DefaultConversionService implements ConversionService {
// an empty ConversionService to initiate call to register converters
}
This is to force spring container to initiate a call to:
class WebMvcConfigurerAdapter {
...
public void addFormatters(FormatterRegistry registry) {
//registry.addConverter(...);
}
}
Existing answers didn't work for me:
Customizing via WebMvcConfigurerAdapter.addFormatters (or simply annotating the converter with #Component) only works in the WebMvc context and I want my custom converter to be available everywhere, including #Value injections on any bean.
Defining a ConversionService bean (via ConversionServiceFactoryBean #Bean or #Component) causes Spring Boot to replace the default ApplicationConversionService on the SpringApplication bean factory with the custom bean you've defined, which will probably be based on DefaultConversionService (in AbstractApplicationContext.finishBeanFactoryInitialization). The problem is that Spring Boot adds some handy converters such as StringToDurationConverter to the standard set in DefaultConversionService, so by replacing it you lose those conversions. This may not be an issue for you if you don't use them, but it means that solution won't work for everyone.
I created the following #Configuration class which did the trick for me. It basically adds custom converters to the ConversionService instance used by Environment (which is then passed on to BeanFactory). This maintains as much backwards compatibility as possible while still adding your custom converter into the conversion services in use.
#Configuration
public class ConversionServiceConfiguration {
#Autowired
private ConfigurableEnvironment environment;
#PostConstruct
public void addCustomConverters() {
ConfigurableConversionService conversionService = environment.getConversionService();
conversionService.addConverter(new MyCustomConverter());
}
}
Obviously you can autowire a list of custom converters into this configuration class and loop over them to add them to the conversion service instead of the hard-coded way of doing it above, if you want the process to be more automatic.
To make sure this configuration class gets run before any beans are instantiated that might require the converter to have been added to the ConversionService, add it as a primary source in your spring application's run() call:
#SpringBootApplication
public class MySpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(new Class<?>[] { MySpringBootApplication.class, ConversionServiceConfiguration.class }, args);
}
}
If you don't do this, it might work, or not, depending on the order in which your classes end up in the Spring Boot JAR, which determines the order in which they are scanned. (I found this out the hard way: it worked when compiling locally with an Oracle JDK, but not on our CI server which was using a Azul Zulu JDK.)
Note that for this to work in #WebMvcTests, I had to also combine this configuration class along with my Spring Boot application class into a #ContextConfiguration:
#WebMvcTest(controllers = MyController.class)
#ContextConfiguration(classes = { MySpringBootApplication.class, ConversionServiceConfiguration.class })
#TestPropertySource(properties = { /* ... properties to inject into beans, possibly using your custom converter ... */ })
class MyControllerTest {
// ...
}

How to add inner classes to Spring application context for Unit Testing?

I have a bean whose business logic loads beans of a certain type from the ApplicationContext in order to process them.
For my jUnit tests, I would like to create some dummy beans within my unit test class and see if my bean under test properly processes them. However, I am not sure what the best way to accomplish this is.
If I just declare my inner class within my test class, Spring will not have it as part of its application context. I realize that I could inject my application context within my jUnit class, and then use appContext.registerPrototype() to add it, however, I thought there might be a cleaner way using annotations.
I've tried to annotate the internal class with #Component, but not surprisingly, it did not work.
public class PatchEngineTest extends TestBase {
#Component
protected class Patch1 extends PatchBaseImpl implements Patch{
public void applyPatch() throws Exception {
// does nothing
}
}
#Autowired PatchRepository patchRepository;
#Autowired Patch1 patch1;
#Test
public void test() {
fail("Not yet implemented");
}
}
Not surprisingly, I get the following error message:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.ia.patch.PatchEngineTest$Patch1] 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 any way of doing this?
You need to make your inner class static; Spring can't instantiate a non-static inner class as a bean. If there really is a valid reason why it needs to be non-static, you could create it manually in an #Bean method.
I also met this problem, and below is my solution :
#RunWith(SpringRunner.class)
#SpringBootTest
#ComponentScan
#ImportAutoConfiguration
public class FooTest {
#Component
public static class Bar {
}
}
I used spring boot 2.1.4.RELEASE

Categories

Resources