I have a problem in deploying spring boot 2.3.2 WAR application version into Apache Tomcat/8.5.20, I build and deploy using Jenkins and deployment sometimes finishes successfully and sometimes fails due to the below exception :
+ tail -n 70 /b001/app/servers/tomcat/Node5/logs/catalina.out
[Pipeline] echo
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:173)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:153)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:95)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:172)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5196)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 10 more
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'alertDashboardServiceImpl': Unsatisfied dependency expressed through field 'alertDashBoardRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.se2.repository.AlertDashBoardRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1420)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1307)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1227)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
... 33 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.se2.repository.AlertDashBoardRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1717)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1273)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1227)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
... 46 more
19-Nov-2020 12:57:58.455 SEVERE [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR Error deploying web application archive [/b001/app/servers/tomcat/Node5/webapps/AlertServices.war]
java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/AlertServices]]
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:756)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:728)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:734)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:988)
at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1860)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
2- My repo
@Repository
@Transactional
public interface AlertDashBoardRepository
extends CrudRepository<AlertDashboardCommon, Long>, JpaSpecificationExecutor<AlertDashboardCommon> {
int countByIsSeenAndAlertSettingUserSiteId(boolean isSeen, int siteId);
int countByIsSeenAndIsArchiveAndAlertSettingUserSiteId(boolean isSeen, boolean isArchive, int siteId);
int countByAlertSettingUserSiteId(int siteId);
Page<AlertDashboardCommon> findByIsArchiveAndAlertSettingUserUserIdOrderByIdDesc(boolean isArchive, int userId, Pageable pageable);
List<AlertDashboardCommon> findByIsArchiveAndAlertSettingUserUserIdOrderByIdDesc(boolean isArchive, int userId);
List<AlertDashboardCommon> findByIsFlagFalseAndAlertEmailHistoryInsertDateLessThan(Date yearBefore);
Page<AlertDashboardCommon> findByIsArchiveAndAlertSettingUserSiteIdOrderByIdDesc(boolean isArchive, int siteId, Pageable pageable);
List<AlertDashboardCommon> findByIsArchiveAndAlertSettingUserSiteIdOrderByIdDesc(boolean isArchive, int siteId);
@Modifying(clearAutomatically = true)
@Query("update AlertDashboardCommon a set a.isFlag = :isFlag where a.id in (:dashboardIds)")
int updateFlagForDashboards(@Param("isFlag") boolean isFlag, @Param("dashboardIds") List<Long> dashboardIds);
@Modifying(clearAutomatically = true)
@Query("update AlertDashboardCommon a set a.isArchive = :isArchive where a.id in (:dashboardIds)")
int updateArchiveForDashboards(@Param("isArchive") boolean isArchive, @Param("dashboardIds") List<Long> dashboardIds);
@Query("select distinct new com.se2.dto.ManNameId(a.matchedManName, a.matchedManId) from AlertDashboardCommon a where a.alertSetting.user.siteId = :siteId and a.isArchive = :isArchive order by a.matchedManName ASC")
Set<ManNameId> getDistinctManufacturersForUser(@Param("siteId") int siteId, @Param("isArchive") boolean isArchive);
@Query("select distinct(a.alertFeatureCategory) from AlertDashboardCommon a where a.alertSetting.user.siteId = :siteId and a.isArchive = :isArchive order by a.alertFeatureCategory.feature_DISPLAY_ORDER ASC")
List<AlertFeatureCategory> getDistinctFeaturesForUser(@Param("siteId") int siteId, @Param("isArchive") boolean isArchive);
@Query("select distinct a.matchType from AlertDashboardCommon a where a.alertSetting.user.siteId = :siteId and a.isArchive = :isArchive order by a.matchType.isDisplayed ASC, a.matchType.matchId DESC")
Set<AlertMatchType> getMatchTypeForUserByIsArchive(@Param("siteId") int siteId, @Param("isArchive") boolean isArchive);
@Query("select distinct a.alertSetting.alertScope from AlertDashboardCommon a where a.alertSetting.user.siteId = :siteId and a.isArchive = :isArchive")
Set<AlertScope> getScopesForUser(@Param("siteId") int siteId, @Param("isArchive") boolean isArchive);
@Query("select count(a)>0 from AlertDashboardCommon a where a.alertSetting.user.siteId = :siteId and a.isArchive = :isArchive and a.isFlag = :isFlag")
boolean isFoundFlagForUser(@Param("siteId") int siteId, @Param("isArchive") boolean isArchive, @Param("isFlag") boolean isFlag);
}
3- My Service class
@Service
public class AlertDashboardServiceImpl implements ICommonService, IAlertDashboardService {
private final static Logger logger = LoggerFactory.getLogger(AlertDashboardServiceImpl.class);
@Autowired
private AlertDashBoardRepository alertDashBoardRepository;
@Autowired
private AlertFeatureCategoryRepository alertFeatureCategoryRepository;
@Autowired
private AlertMatchTypeRepository alertMatchTypeResultRepository;
3- my main Class Alert.class
package com.se2;
@SpringBootApplication
@EnableScheduling
public class Alert extends SpringBootServletInitializer {
private final static Logger springBootServletInitializerLogger = LoggerFactory.getLogger(Alert.class);
@Override
protected SpringApplicationBuilder configure(
SpringApplicationBuilder builder) {
return builder.sources(Alert.class);
}
public static void main(String[] args) {
SpringApplication.run(Alert.class, args);
System.out.println("Alert Application Started");
springBootServletInitializerLogger.info("Alert Application Started");
}
}
4- my pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.se2</groupId>
<artifactId>SE2-Alert-Service-BL</artifactId>
<version>0.0.3</version>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
<springfox-swagger.version>2.9.2</springfox-swagger.version>
<sonar.host.url>http://localhost:9000</sonar.host.url>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-swagger.version}</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- Use MySQL Connector-J -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- H2 Database -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox-swagger.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>com.excel.streaming</groupId>
<artifactId>excel-streaming</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.18.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>6.0.18.Final</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>8.4.1</version><!--$NO-MVN-MAN-VER$ -->
</dependency>
<dependency>
<groupId>com.se2.om</groupId>
<artifactId>Se2CacheLayer</artifactId>
<version>0.0.14</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>com.excel.streaming</groupId>
<artifactId>excel-streaming</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>de.dev-eth0.dummycreator</groupId>
<artifactId>dummy-creator</artifactId>
<version>1.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>AlertServices</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>3.0.0-M3</version>
</dependency>
</dependencies>
</plugin>
<!-- MapStruct -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.4.0.905</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.5.201505241946</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>default-report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>default-check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<!-- implementation is needed only for Maven 2 -->
<rule implementation="org.jacoco.maven.RuleConfiguration">
<element>BUNDLE</element>
<limits>
<!-- implementation is needed only for Maven 2 -->
<limit implementation="org.jacoco.report.check.Limit">
<counter>COMPLEXITY</counter>
<value>COVEREDRATIO</value>
<minimum>0.0</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Finally, I can't figure out the problem of why deployment succeeds sometimes and tomcat starts, and why sometimes it fails due to dependency injection fails.
Any suggestions?
i was using an embedded local spring boot project JAR that was using Spring Data Redis, and has different level of main package namespace it's was "com.ex1.ex2.main1" and my main application main package namespace was "com.ex1.main2", so spring and tomcat sometime loads that Jar before the main application and create it's repositories "Redis" which doesn't include Spring Data JPA that main application needs it, it's resolved by renaming my main application to "com.ex1.ex2.main2" that has the same namespace and package level as the jar, also adding @ComponentScan("com.ex1.ex2.*") so component scan loads them in standard and appropriate order.