I have been in the process of upgrading an Apache Tomcat 9.0.83 application to 10.1.6-1.
I have sorted out most of the Jakarta namespace changes but noticed that Beans injected with the @Service annotation are not available.
Our application is old, so the majority of classes are registered via XML and work. However the handful that use annotations are not available.
Resources using @AutoWire are null and trying to explicitly get the bean via aplicationContext.getBean("Foo")
gives the following error.
[ERROR] [Mon Apr 08 11:10:35.258 2024] [ajp-nio-127.0.0.1-8009-exec-2|BackupServiceImpl] Error: checking if chosen file name Backup-20244811:10 already exists for the host 127.0.0.1
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'FOO' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:893) ~[spring-beans-6.0.11.jar:6.0.11]
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1318) ~[spring-beans-6.0.11.jar:6.0.11]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300) ~[spring-beans-6.0.11.jar:6.0.11]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.0.11.jar:6.0.11]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1155) ~[spring-context-6.0.11.jar:6.0.11]
at com.myCompany.AppContextUtil.getFoo(AppContextUtil.java:48) ~[myCompany-services-impl.jar:?]
Other annotations such as as PostConstruct work.
Foo.class:
import org.springframework.stereotype.Service;
@Service("Foo")
public class FooImpl extends FooIAbstract {
public FooImpl() {
}
}
As per the top answer to this question, checking for duplicate instances of jakarta.annotation.Resource, I did find the following two jars containing the jakarta.annotation.Resource class and excluded he jakarta.annotation-api-2.0.0.jar without any luck.
~/eclipse-workspace09/DEVELOP_5_1_8_8_BRANCH/base/dist/usr/local/tomcat (DEVELOP_5_1_8_8_BRANCH)
$ find ./ -type f -iname '*.jar' | xargs grep --text --ignore-case --files-with-matches '.*jakarta.annotation.Resource.*'
./lib/jakarta.annotation-api-2.0.0.jar
./lib/tomcat-annotations-api-10.1.6.jar
There was not any ComponentScan annotation in our prior code so I tried adding one without any effect.
@ComponentScan("com.Company")
public class AppContextListener implements ServletContextListener, HttpSessionListener {
If I add an xml definition to our existing applicationContent.xml there are no errors trying to pull the bean by name from the context.
<bean id="Foo" class="com.Company.FooImpl" lazy-init="true">
</bean>
Relevant dependencies from main pom.xml:
<org.springframework.version>6.0.11</org.springframework.version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${org.springframework.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-instrument</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!--
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>6.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${org.springframework.version}</version>
</dependency>
</dependencies>
As M Deinum noted in the comments above, adding @Configuratio
resolved this issue.
@Configuratio
@ComponentScan("com.Company")
public class AppContextListener implements ServletContextListener, HttpSessionListener {
However adding <context:component-scan base-package="com.mycompany"/>
broke my application.
I am not at all certain how this worked in Tomcat 9.
Further reading for anyone that finds this in the future.