Java Spring Boot — Error starting Tomcat context

huangapple go评论120阅读模式
英文:

Java Spring Boot -- Error starting Tomcat context

问题

错误信息指出了Spring应用程序在启动Tomcat时遇到了依赖问题。主要的错误信息是:

  1. org.springframework.beans.factory.UnsatisfiedDependencyException 异常,它表明应用程序无法满足某个bean的依赖。

  2. jwtRequestFilter 类无法创建,因为它的构造函数参数中存在依赖问题。

  3. jwtTokenService 类也无法创建,因为它的构造函数参数中存在依赖问题。

  4. tokenRepository 无法解析对 jpaSharedEM_entityManagerFactory bean 的引用。

要解决这个错误,你可以尝试以下步骤:

  1. 检查你的 Spring Boot 版本是否与其他依赖项版本兼容。在你的项目的 pom.xml 文件中,确保所有的 Spring 相关依赖项版本一致。

  2. 检查 application.properties 文件,确保数据库连接配置正确。你需要确保数据库服务器地址、端口、用户名和密码都正确。

  3. 检查 Token 类和 TokenRepository 接口是否正确配置。确保实体类和存储库接口的注解正确,并且与数据库表的结构匹配。

  4. 检查 JwtTokenService 类的构造函数,确保它正确注入了 JwtTokenUtilTokenRepository。确保这两个依赖项在应用程序上下文中正确配置。

  5. 最后,检查你的数据库是否正在运行,并且数据库中的表结构与应用程序配置匹配。

根据上述信息,你可以逐步排查并修复依赖问题,以解决这个错误。如果你仍然遇到问题,可以提供更多关于你的项目配置和错误堆栈的信息,以便更详细地帮助你解决问题。

英文:

Edit: added pom.xml info

 Error: *o.s.b.web.embedded.tomcat.TomcatStarter: 
    
    Error starting Tomcat context. Exception: org.springframework.beans.factory.UnsatisfiedDependencyException. 
    
    Message: Error creating bean with name 'jwtRequestFilter' defined in file [C:...\target\classes\com\...\Semen\security\JwtRequestFilter.class]: 
    
    Unsatisfied dependency expressed through constructor parameter 1: 
    
    Error creating bean with name 'jwtTokenService' defined in file [C:...\target\classes\com\...\Semen\security\JwtTokenService.class]: 
    
    Unsatisfied dependency expressed through constructor parameter 1: 
    
    Error creating bean with name 'tokenRepository' defined in com.psuti.Semen.security.token.TokenRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: 
    
    Cannot resolve reference to bean 'jpaSharedEM_entityManagerFactory' while setting bean property 'entityManager'

application.properties

spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/testdb
spring.datasource.username=testuser
spring.datasource.password=testpassword
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=validate
spring.profiles.active=development
jwt.secret=simple

Info from pom.xml:

org.springframework.boot:spring-boot-starter-parentL3.0.4
java.version 18
spring 6.0.5
spring-security.version 6.0.2
org.springframework.boot:spring-boot-starter-web
org.springframework.boot:spring-boot-devtools:runtime:true
org.springframework.boot:spring-boot-starter-test:test
org.springframework.boot:spring-boot-starter-data-jpa
org.flywaydb:flyway-core
org.postgresql:postgresql:runtime
org.projectlombok:lombok:true
org.springframework.boot:spring-boot-starter-security
io.jsonwebtoken:jjwt-api:0.11.5
io.jsonwebtoken:jjwt-impl:0.11.5:runtime
io.jsonwebtoken:jjwt-jackson:0.11.5:runtime
org.springframework.boot:spring-boot-maven-plugin

Token

import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.UUID;

@Getter
@Setter
@Entity(name = "token")
@Table(name = "tokens", schema = "public")
public class Token implements Serializable {
    @Column(nullable = false, unique = true)
    private String value;
    @JsonIgnore
    private boolean killed;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "user_id")
    private UUID userId;
}

TokenRepository

import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;
import java.util.UUID;

public interface TokenRepository extends JpaRepository<Token, UUID> {
    Optional<Token> findByValue(String value);
    Optional<Token> findTokenByUserId(UUID id);
}

JwtTokenService

package com.psuti.Semen.security;

import com.psuti.Semen.security.token.JwtTokenUtil;
import com.psuti.Semen.security.token.Token;
import com.psuti.Semen.security.token.TokenRepository;
import jakarta.persistence.EntityExistsException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;

@Service
public class JwtTokenService {
    private final JwtTokenUtil<UUID> jwtUserIdTokenUtil;
    private final TokenRepository tokenRepository;
    @Autowired
    public JwtTokenService(JwtTokenUtil<UUID> jwtUserIdTokenUtil,
                           TokenRepository tokenRepository) {
        this.jwtUserIdTokenUtil = jwtUserIdTokenUtil;
        this.tokenRepository = tokenRepository;
    }
    public Token createToken(UUID userId){
        String token = jwtUserIdTokenUtil.generateToken(userId);
        Token tokenEntity = new Token();
        tokenEntity.setUserId(userId);
        tokenEntity.setValue(token);
        tokenEntity.setKilled(false);
        return tokenRepository.save(tokenEntity);
    }
    public void kill(String tokenValue){
        Token token = tokenByValue(tokenValue);
        token.setKilled(true);
        tokenRepository.save(token);
    }
    public void kill(Token token){
        token.setKilled(true);
        tokenRepository.save(token);
    }
    public boolean tokenIsKilled(String tokenValue){
        return tokenByValue(tokenValue).isKilled();
    }
    public boolean tokenExists(String tokenValue){
        AtomicBoolean exists = new AtomicBoolean(false);
        tokenRepository.findByValue(tokenValue).ifPresent(
                (t)-> exists.set(!t.isKilled())
        );
        return exists.get();
    }
    private Token tokenByValue(String val){
        Token token = tokenRepository.findByValue(val).orElseThrow(()->{
            throw new EntityExistsException("token with value: '" + val + "' doesn't exists");
        });
        return token;
    }
    public Optional<Token> findOptionalByUserId(UUID id){
        return tokenRepository.findTokenByUserId(id);
    }
    public Token findByUserId(UUID id){
        return tokenRepository.findTokenByUserId(id).orElseThrow(()->{
            throw new EntityExistsException("token by user id: " + id + " doesn't exists");
        });
    }
    public boolean validateToken(String token, UUID id){
        if(!jwtUserIdTokenUtil.validateToken(token,id)){
            if(new Date().before(jwtUserIdTokenUtil.getExpirationDateFromToken(token))){
                kill(token);
            }
            return false;
        }
        return true;
    }
    public UUID getIdFromToken(String token){
        return jwtUserIdTokenUtil.getSubjectFromToken(token);
    }
    public Token refreshToken(String tokenValue){
        Token token = tokenByValue(tokenValue);
        token.setValue(jwtUserIdTokenUtil.generateToken(token.getUserId()));
        return tokenRepository.save(token);
    }
}

I tried search info about this but nothing helped me

What means this error? How I can fix it?

答案1

得分: 0

这个错误是什么意思?

前两个错误涉及到构造函数参数的依赖未满足。从代码中我们可以看到,这个参数是'tokenRepository'。在Spring中,依赖未满足的错误意味着无法注入对对象(bean)的引用。然而,这两个错误只是第三个错误的后续错误。

第三个错误显示了为什么无法创建(实例化)'tokenRepository':在JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration类中存在对bean 'jpaSharedEM_entityManagerFactory'的未知引用。这看起来像是Spring Data配置类中的一个错误,我们无法修复任何东西。搜索网络显示,在Spring 6的早期版本中,或者Hibernate中曾出现与此引用相关的问题。

如何修复它?

等待bug修复,或尝试使用Spring的较早版本。从评论中可以看到,将spring-boot-starter-parent切换到3.0.1(而不是3.0.4)是有帮助的。

英文:

> What means this error?

The first two errors are about unsatisfied dependencies to the constructor parameters. From the code we can see that this parameter is 'tokenRepository'. Unsatisfied dependency error in Spring means that the injection of a reference to an object (bean) is not possible. However both errors a just subsequent errors of the third one.

The third error shows the reason why the 'tokenRepository' can't be created (instantiated): there is an unknown reference to bean 'jpaSharedEM_entityManagerFactory' in JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration class. This looks like a bug in a configuration class of Spring Data where we can't fix anything. Searching the web shows that there were some issue with this reference in the early versions of Spring 6, respectively Hibernate.

> How I can fix it?

Wait until the bug is fixed or try to use an earlier version of Spring. From the comment I can see that switching spring-boot-starter-parent to 3.0.1 (instead of 3.0.4) was helpful.

huangapple
  • 本文由 发表于 2023年3月9日 21:32:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/75685306.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定