bestsource

Build Properties 스프링 부트 2.1.5 및 이클립스 자동 배선 실패

bestsource 2023. 2. 17. 21:29
반응형

Build Properties 스프링 부트 2.1.5 및 이클립스 자동 배선 실패

몇 개의 REST API를 사용하여 매우 간단한 애플리케이션을 만들고 있으며, 현재 상태 점검 API에서 BuildProperties를 사용할 때까지 정상적으로 작동합니다.응용 프로그램 실행 중 다음 오류가 발생합니다.

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2019-06-17 09:54:29.210 ERROR 10796 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Field buildProperties in com.controller.HealthCheck required a bean of type 'org.springframework.boot.info.BuildProperties' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)

The following candidates were found but could not be injected:
    - Bean method 'buildProperties' in 'ProjectInfoAutoConfiguration' not loaded because @ConditionalOnResource did not find resource '${spring.info.build.location:classpath:META-INF/build-info.properties}'


Action:

Consider revisiting the entries above or defining a bean of type 'org.springframework.boot.info.BuildProperties' in your configuration.

빌드 파일로 이동하여 빌드에 의해 작성된 jar 파일도 확인했는데 build-info.properties가 실제로 있습니다.jar 파일에서 파일의 경로는 "BOOT-INF\classes\"입니다.META-INF\."또한 문제가 없는 다른 "자동" 요소도 있습니다.

코드가 실패한 경우:

@RestController
public class HealthCheck {

    @Autowired
    Environment environment;

    @Autowired 
    BuildProperties buildProperties;


    @GetMapping("/health")
    public HealthCheckResponse healthCheck() {
        return getHealthCheckResponse();
    }

    private HealthCheckResponse getHealthCheckResponse(){
        HealthCheckResponse healthResponse = new HealthCheckResponse();
        String[] profiles = environment.getActiveProfiles();

        healthResponse.setServerTime(new Date());
        healthResponse.setVersion(buildProperties.getVersion());
        healthResponse.setEnvironment(profiles[0]);

        return healthResponse;
    }

내 그래들 빌드 파일:

plugins {
    id 'org.asciidoctor.convert' version '1.5.3'
    id 'org.springframework.boot' version '2.1.5.RELEASE'
    id 'java'
}

apply plugin: 'io.spring.dependency-management'
apply plugin: 'eclipse'
apply plugin: 'java'

group = 'com'
version = '0.0.1'
sourceCompatibility = '12'

repositories {
    mavenCentral()
}

ext {
    set('snippetsDir', file("build/generated-snippets"))
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-jersey'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'com.github.ulisesbocchio:jasypt-spring-boot-starter:2.1.1'
    runtimeOnly 'mysql:mysql-connector-java'
    annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.restdocs:spring-restdocs-webtestclient'
    testImplementation 'org.springframework.security:spring-security-test'
}

test {
    outputs.dir snippetsDir
}

asciidoctor {
    inputs.dir snippetsDir
    dependsOn test
}

springBoot {
    buildInfo()
}

build-info.properties:

#Properties
#Mon Jun 17 10:52:04 EDT 2019
build.version=0.0.1
build.group=com
build.name=app
build.artifact=app
build.time=2019-06-17T14\:52\:04.829909200Z

.mvn clean package그런 다음 이클립스/인텔리J에서 스프링 부트 애플리케이션을 재시작합니다.

pom.xml 끝에 추가/수정:

<build>
        <finalName>{NAME_YOUR_PROJECT}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>build-info</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

요컨대:이 문제는 IDE와 관련된 문제(Eclipse 및 Idea에서 확인됨)로, 그래들 빌드 시스템을 통한 시작 스크립트의 스프링 부트 응용 프로그램 실행/디버깅에는 영향을 주지 않습니다.

또한 이클립스용 부트플러그인과 JDK가 이 문제를 일으킨다는 전제가 완전히 올바른 것은 아닙니다.

이 문제의 근원:컴파일러가 다르며 누락된 빌드 아티팩트의 위치가 다릅니다.build-info.properties.

설명:

gradle은 빌드를 실행할 때 JDK 컴파일러를 사용하여 Java 아티팩트를 생성하고 출력을 빌드 디렉토리에 배치합니다.

반면, Eclipse는 빌드를 수행할 때 Eclipse JDT를 사용하여 ARIFACT를 생성하고 출력을 bin 디렉토리에 배치합니다.

이 두 가지를 혼합하면 예상치 못한 행동이 발생할 수 있습니다.이 '특징'은 이미 일식 팀에 의해 분석되었으며 거부되었습니다(비활성화됨).자세한 내용은 이쪽.

task에 gradle task에 따르면buildInfo은 그래들이 운영한다는 있습니다.그것은 그 사실이 설명되고 있습니다.build-info.properties기본 출력 으로 gradle은 gradle에).build/resources/main/META-INF/를 참조해 주세요.

@ROOTKILL의 질문에서 볼 수 있는 것은 그가 BuildProperties 클래스에서 정보를 얻으려고 시도하고 있다는 것입니다.spring은 클래스 경로에 build-info.properties 파일이 있음을 검출하면 명시적으로 선언되지 않는 한 BuildProperties bean을 만듭니다.유용한 정보가 여기 있습니다.

이 방법을 확인해 주십시오.

@ConditionalOnResource(resources = "${spring.info.build.location:classpath:META-INF/build-info.properties}")
@ConditionalOnMissingBean
@Bean
public BuildProperties buildProperties() throws Exception {
    return new BuildProperties(
            loadFrom(this.properties.getBuild().getLocation(), "build"));
}

가 다른 dir를 하고 있는 하지 않으며 로 인해 오류(IDE > 、 dir 、 build - info . properties )가 합니다.Bean method 'buildProperties' in 'ProjectInfoAutoConfiguration' not loaded because @ConditionalOnResource did not find resource '${spring.info.build.location:classpath:META-INF/build-info.properties}' 모든 할 수 있는 의 반대편에서는, 모든 것을 그래들로 실행할 수 있는 이유를 설명합니다.

솔루션:

이러한 사실에 따르면 솔루션은 명확합니다.Eclipse와 IntelliJ Idea IDE 모두 실행/디버깅을 위해 gradle의 태스크가 아닌 gradle의 태스크를 사용해야 합니다.

  • Eclipse IDE의 경우: 그래들 태스크에서 응용 프로그램을 시작할 수 있습니다(그래들 태스크 보기에서 bootRun).
  • Idea IDE의 경우: IDE 빌드/실행 액션을 gradle로 위임하는 설정을 추가할 수 있습니다.이 설정은 이미 @user666이 지적하고 있습니다.

하므로 gradle은 gradle을 사용합니다.build-info.properties되었습니다.build/resources/main/META-INF/졸업하다【콩 빌드 속성】【콩 빌드 속성】

@André Schonrock가 정확하게 언급했듯이, 문제의 원인은 다음과 같습니다.

Maven 플러그인과 Gradle 플러그인은 모두 프로젝트의 좌표, 이름 및 버전을 포함하는 빌드 정보를 생성할 수 있습니다.구성을 통해 속성을 추가하도록 플러그인을 구성할 수도 있습니다.이러한 파일이 있는 경우 Spring Boot은 BuildProperties bean을 자동으로 설정합니다.

이 두 가지 중 .spring-boot-maven-pluginPOM:

<executions>
    <execution>
        <goals>
            <goal>build-info</goal>
        </goals>
    </execution>
</executions> 

build.gradle:

springBoot {
    buildInfo()
}

으로 추가할 수 .Bean@djangofan에 표시된 것보다 짧은 형식으로 표시됩니다.

@Bean @ConditionalOnMissingBean(BuildProperties.class)
BuildProperties buildProperties() {
    return new BuildProperties(new Properties());
}

컨피규레이션파일로 지정합니다.

주의: 갱신한 경우POM ★★★★★★★★★★★★★★★★★」build.gradle가 아직 을 사용해 보겠습니다(예:Maven 사이클명령어) " " " "clean 다음에 또 한 번.install츠키다

@Borislav Markov의 제안대로 명령줄로 실행해 봤는데 JDK 12를 사용하든 JDK 8을 사용하든 문제없이 동작하는 것 같습니다만, 이클립스 플러그인은 IDE를 통해 애플리케이션을 실행할 때 사용하는 이클립스 플러그인과 관련이 있다고 생각합니다.

Intelli와 maven을 사용하는 경우, 여기 주자를 변경하고 maven runner를 사용하는 방법에 대한 스크린샷이 있습니다.이상적으로는 이 방법이 가장 좋습니다.Ide에서도 maven이 정확히 어떻게 동작하는지를 실행할 수 있기 때문입니다.

여기에 이미지 설명 입력

에 maven-spring-boot Maven이 됩니다.BuildProperties cannot be found.jar 아카이브가 아닌 경우 서비스를 실행하려고 하면 됩니다.따라서 서비스를 일반 Spring Boot 실행 Configuration으로 실행하기 위해서는 다음 조건을 추가해야 합니다.bean은 모두 .jar 릴리즈로 동작하며 debug non-release로 동작합니다.

@ConditionalOnMissingBean
@Bean
public BuildProperties buildProperties() {
    Properties properties = new Properties();
    properties.put("group", "com.example");
    properties.put("artifact", "demo");
    properties.put("version", "not-jarred");
    return new BuildProperties(properties);
}

lombok을 사용하는 경우 spring-boot-maven-plugin 설정을 제외하십시오.

    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <excludes>
                <exclude>
                    <groupId>org.projectlombok</groupId>
                    <artifactId>lombok</artifactId>
                </exclude>
            </excludes>
        </configuration>
        <executions>
            <execution>
                <id>build-info</id>
                <goals>
                    <goal>build-info</goal>
                </goals>
            </execution>
        </executions>
    </plugin>

다른 답변에서도 알 수 있듯이 이는 IDE가 파일을 생성하지 않기 때문입니다.vscode의 경우, 빌드가 예상하는 위치에 맞게 Gradle의 빌드/리소스/메인/META-INF 디렉토리에서 vscode의 bin/main/META-INF로 build-info.properties 파일을 복사하는 작업을 정의하여 문제를 해결했습니다.

보통 최근에 Gradle 빌드를 실행했는데, vscoode에서 디버깅을 실행하려면 약간 오래된 버전의 build-info.properties로 충분합니다.

다음과 같은 .vscode/tasks.json을 만듭니다.

{
    "version": "2.0.0",
    "tasks": [
        {
            // This task keeps vscode from failing when using BuildProperties
            "label": "Copy build-info from Gradle",
            "type": "shell",
            "command": "mkdir -p ./bin/main/META-INF/ && cp ./build/resources/main/META-INF/build-info.properties ./bin/main/META-INF/build-info.properties"
        }
    ]
}

그런 다음 작업을 .vscode/launch.json시작 전 태스크로 추가합니다.

{
    "configurations": [
        {
            "type": "java",
            "name": "Spring Boot-Application<example>",
            "request": "launch",
            "cwd": "${workspaceFolder}",
            "console": "internalConsole",
            "mainClass": "com.example.Application",
            "projectName": "example",
            "args": "",
            "preLaunchTask": "Copy build-info from Gradle"
        }
    ]
}

JDK 8에서 실행해 보고 명령줄에서 실행해 보는 것이 좋습니다.java -jar <your jar name>빌드 속성을 올바르게 파악했는지 확인합니다.

Jdk 12는 아직 스프링 부트에 적합하지 않을 수 있습니다.다른 문제도 있을 것 같아요.많은 Java 프레임워크가 JDK 12에서 동작하는 것을 100% 인정받지 못하고 있습니다.

Spring Boot 2.2에서 Java 12를 공식적으로 지원할 예정입니다.

당신의 IDE는 "뚱뚱한 병"이 일반 병을 덮어쓴다는 사실에 혼란스러워하는 것 같습니다.IDE는 'build-info.properties'의 일반 jar + 생성된 리소스의 클래스 경로를 인식합니다.

저는 항상 다른 이름으로 항아리를 만들고 있기 때문에 부분 빌드에서는 이러한 문제를 피할 수 있습니다.

https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/html/ #예약 가능 및 표준

실행 가능한 아카이브와 일반 아카이브가 동일한 위치에 기록되지 않도록 하려면 둘 중 하나를 다른 위치를 사용하도록 구성해야 합니다.이를 위한 한 가지 방법은 분류자를 설정하는 것입니다.

bootJar {
    classifier = 'boot'
}

ProjectInfoAutoConfiguration 솔루션을 사용해 봤는데@ConditionalOnMissingBean (BuildProperties.class)대신@ConditionalOnResource (resources = "$ {spring.info.build.location: classpath: META-INF / build-info.properties}").

내가 길을 통제할 수 있기 때문이다.BuildProperties성됩니니다다

    @ConditionalOnMissingBean(BuildProperties.class)
    @Bean
    public BuildProperties buildProperties() throws IOException {
            Resource r = this.properties.getBuild().getLocation();
            if (r.exists())
                // build-info.properties exists in my jar
                return new BuildProperties(
                    loadFrom(r, "build")); // see ProjectInfoAutoConfiguration code
            else {
                // No, we running via IDE. So let's build a stub:
                Properties properties = new Properties();
                properties.put("group", "com.example");
                properties.put("artifact", "demo");
                properties.put("version", "not-jarred");
                return new BuildProperties(properties);
            }
    }

Gradle 프로젝트의 경우: build.gradle 파일에 추가합니다.

    springBoot {
        buildInfo {
            properties {
                name = PROJECT_NAME
                additional = [
                        'yourCustomInfo': 'someInfo'
                ]
            }
        }
    }

이 문제는 STS와 Intellij가 응용 프로그램을 Spring Boot Application으로 실행하는 동안 buildinfo 태스크를 실행하지 않는다는 것입니다.대부분의 개발자는 gradle/maven build를 사용하는 것이 아니라 이 메커니즘을 통해 앱을 실행하므로 두 가지 모두에 적합한 솔루션이 필요합니다.세르게이 K의 답변을 따라가 보니 IDE 기반의 Spring Boot Run에서 동작했습니다.그러나 gradle의 경우 생성된 build-info.properties 파일이 아닌 Configuration파일에서 BuildProperties가 자동배선되어 실행이 실패했습니다.

다음 컴포넌트를 사용하여 자동 접속함으로써 이 문제를 극복할 수 있었습니다.

@Component
public BuildValues{
   @Autowired(required = false)
   private buildProperties;
   
   public getBuildProperties(){
       if(buildProperties==null) {
          ResourceLoader resourceLoader = new DefaultResourceLoader();
          Resource r = resourceLoader.getResource("classpath:META-INF/build- 
        info.properties");
    if (r.exists()) {
        // build-info.properties exists in my jar
        Properties prop = PropertiesLoaderUtils.loadProperties(r);
        buildProperties =  new BuildProperties(prop);
    }else {
    // No, we running via IDE. So let's build a stub:
        Properties properties = new Properties();
        properties.put("buildTime", "2022-01-13T14:38:06.567Z");
        buildProperties = new BuildProperties(properties);
    }
    }
    return buildProperties;
   }

} 

언급URL : https://stackoverflow.com/questions/56634081/failed-autowired-of-buildproperties-spring-boot-2-1-5-eclipse

반응형