Spring changes finding beans from version 4.3 to 5 - java

I have a large spring applications using annotations that works fine in spring 4.3.13, and am looking to update to spring 5. I am getting all kinds of failures wiring beans, which look like the typical:
Unsatisfied dependency expressed through field 'pcoDAO'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.acme.dao.impl.contracts.PotentialChangeOrderDAO' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
turning on spring debug logging, only nets this additional line
Failed to meta-introspect annotation interface org.springframework.beans.factory.annotation.Autowired: java.lang.NullPointerException
It's not like all #Autowired fields fail, just this one (so far). The bean is specified by an interface, and the implementation is in a sub package of the interface, but again this worked before. The interface's package is specified directly in the
context:component-scan
base-package="com.acme.package.of.interface"
Again this works fine in 4.3.13, and the only change is spring being upgraded to 5.0.5-RELEASE.
Are they any known changes to how spring finds beans? or any documentation about this?

Seems a bug of Spring 5.0.5, and has been fixed in 5.0.6, see this Null check needed in AnnotationUtils.getAnnotation

Please checkout the implementations of respect interface, If it is not there provide implementation.
If implementation is there please check whether they have class level annotation as #Component or any specific annotations.
For info related auto wiring read this.

Related

Spring boot unable to autowire class in tests after disable JPA

hope you all are doing well
I'm facing some problems on testing my Spring Boot application. I created a simple API (currently has only one method, and it's working) and I created the domain tests disabling JPA configurations. When I test with JPA disabled, the tests provide the following error:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.mhrehbein.curriculum.register.infrastructure.mysql.ISpringDataAboutMeRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
When I enable JPA configuration it works fine, but I would like to disable once it is unit tests. You can check the code in the following PR: https://github.com/retatu/curriculum/pull/6/files (sorry for it)
In the code you can see that all tests are broke, the tests are basically the same and the example is here: https://github.com/retatu/curriculum/blob/dev/src/test/java/com/mhrehbein/curriculum/register/domain/entity/AboutMeTest.java
Appreciate any help
In your code you declared an interface that extends PagingAndSortingRepository:
public interface ISpringDataAboutMeRepository extends PagingAndSortingRepository<AboutMe, UUID> {
}
It means that spring boot must autoconfigure this repository bean for you, namely, it will be configured a proxy bean of SimpleJpaRepository.
But since you disabled DataSourceAutoConfiguration in application-test.properties, no DataSource bean is configured, therefore the automatic JpaRepositoriesAutoConfiguration is not activated and user-defined JPA-repositories, in your case ISpringDataAboutMeRepository, are not registered, which leads to the NoSuchBeanDefinitionException. More info about it here.
Also, if you disable HibernateJpaAutoConfiguration, EntityManagerFactory bean isn't configured, which is necessary to create your ISpringDataAboutMeRepository bean.
As a result, if you want to run #SpringBootTest, you need to remove your spring.autoconfigure.exclude property from application-test.properties and configure a database for tests, e.g. in-memory H2-database:
Add to your build.gradle:
testImplementation group: 'com.h2database', name: 'h2', version: '1.4.200'
Your application-test.properties:
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa
Otherwise, you can use #MockBean annotation on your test classes to mock your ISpringDataAboutMeRepository so:
#SpringBootTest
#ExtendWith(SpringExtension.class) // remove it since #SpringBootTest already contains it
#TestPropertySource(locations = "classpath:application-test.properties")
#MockBean(ISpringDataAboutMeRepository.class)
public class AboutMeTest {
...
}
Spring has it's spring application context which is working as a container of beans. The BeanFactory represents spring's inversion of control container. What it does is exposing beans to the application. When your application requires a bean which is not available then it throws NoSuchBeanDefinitionException.
I think your question and the root cause is best answered in the below question. Hope it will five you insights of the problem.
What is a NoSuchBeanDefinitionException and how do I fix it?

Programmatic run-time injection/auto-wiring in quarkus

I am looking for a a way to do runtime injection of a bean in Quarkus. I realize this might be a bit on an unorthodox approach for quarkus, and something on an anti-pattern, so no need to point that out, I am fully aware :)
What I am looking for is a way to construct a bean during runtime, and having any annotated properties injected from the Quarkus context.
In Spring Boot I would get the application context by having a bean initialized normally by spring boot, using the ApplicationContextAware interface to inject the application context. I would then use that as a factory by calling ApplicationContext.getAutowireCapableBeanFactory() to get the auto-wire factory and using the autowireBean method on the factory to autowire my beans during runtime. I am wondering if something similar is possible in Quarkus?
This is similar to this question.
How to programmatically inject a Java CDI managed bean into a local variable in a (static) method
javax.enterprise.inject.spi.CDI.current().getBeanManager().select(C.class).get()
To make sure that the bean class is manged use the io.quarkus.arc.Unremovable annotation.

Could not process Dynamic {} org.apache.camel.FailedToCreateRouteException: Failed to create route

I'm facing this issue. Anyone can help me with the resolution?
It says No bean could be found in the registry later it is throwing this error. But when I checked the bean, the bean is defined properly
At these two links 1 and 2 it's suggested to check for missing dependencies.
The BeanNotFound error is different. The bean could exist but not be visible. For example, I usually annotate my bean classes with the annotation #Component, which, if forgotten, leads to the same error.

Could not autowire field: private org.springframework.core.task.support.ExecutorServiceAdapter

I am really stuck and i need your help.
I am getting the following autowire error
Could not autowire field: private
org.springframework.core.task.support.ExecutorServiceAdapter
could not autowire because he cant find it.
but clearly it is there, I see it in maven dependencies.
what could possibly cause spring to not find his own beans?!
Thank you
Do you need to configure an instance of that class to be managed within the spring context? Normally spring will only look for managed beans to auto wire.

Classpath scanning of dependencies

I have a 3-tier application: web-service, service-layer and domain-layer. The web service is present in a web application (WAR). The service-layer and domain-layer are two JAR projects. The dependencies are:
web-service --> service-layer --> domain-layer
In the service layer, the services are annotated with #Service. In the domain-layer, the DAOs are annotated with #Repository. The web service implementation class uses the services of the service-layer JAR, so it keeps one instance of each service which is automatically injected (#Autowired).
The dependencies are well defined in my POMs. When I deploy my WAR on Tomcat, I get the following exception:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.mycompany.project.services.MyService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:952)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:821)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:735)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:551)
... 37 more
I quote from one relevant part in the Spring docs:
The scanning of classpath packages requires the presence of
corresponding directory entries in the classpath. When you build JARs
with Ant, make sure that you do not activate the files-only switch of
the JAR task.
I've checked and the service-layer JAR is present in the WEB-INF/lib directory.
Any idea?
Thanks
EDIT: I have only one context file which is located in the web-service layer project (WAR) under src/main/webapp/WEB-INF. In this context, I've enabled classpath scanning as follows:
<context:component-scan base-package="com.mycompany.project" />
The package com.mycompany.project is the base package of my project, under which there are the web-service (com.mycompany.project.server), service-layer (com.mycompany.project.services) and domain-layer (com.mycompany.project.domain) packages.
I've solved the issue. I don't understand why what I've done was causing such an issue. Each service implements an interface that defines its public methods. In my web service implementation class, the references to the services used the implementation classes and not the interfaces. I just changed them to use the interface, and I don't get the issue anymore. Could anyone explain me what's wrong with using the services implementation classes instead of the interfaces for the autowiring?
This is an answer for your EDIT:
The reason why referring to the interface worked but the concrete implementation failed is probably to do with the dynamic proxies that Spring creates for cases where you have your services annotated with #Transactional etc. What happens in such cases is that the type of your beans are not the implementation type anymore, but wrap around your impementation type. So when you have #Autowired by implementation type, it just cannot find it by type (which is the default).
Your fix is very appropriate, as a dynamic proxy continues to derive from the interfaces that you have defined for your implementation and so can inject by interface type - the reference that I have provided does a better job explaining this.
make sure you used <context:component-scan base-package="your.service.package"/>
check your autowired strategy is byName or byType; if byName, the Service annotation's name value should be right.
if problem still exist, check spring's log, it will print all found components' name, you could know the service is founded or not.
Can you show your component scanning configuration? If this is not set up correctly then Spring may not be discovering your service.
You want something like:
<context:component-scan base-package="your.service.package"/>
Edit:
I think the problem is that your #Service annotation is on the interface rather than implementation class.
If you annotate your service implementation then your web controller can use either:
#Autowired
private ExampleService service;
or
#Autowired
private ExampleServiceImpl service;

Categories