2016-12-10 5 views
2

Ich habe Probleme mit der neuesten Iteration zu versuchen, eine Multi-Modul-Feder-Boot-Anwendung zu erhalten gehen, und ich es geschaffen, das Problem auf eine einfache Testanwendung unten (und auch an diesem Kern vorhanden eingefügt zu destillieren: https://gist.github.com/deinspanjer/d8416e91c1454bfe44efeee5b00fb805Wie konfiguriert man externe Konfigurations-Beans im Spring Boot?

Wenn ich versuche, dies zu laufen, es startet, gibt aber dann den folgenden Fehler. Bitte sagen sie mir, was offensichtlich, was ich falsch mache. :(

. ____   _   __ _ _ 
/\\/___'_ __ _ _(_)_ __ __ _ \ \ \ \ 
(()\___ | '_ | '_| | '_ \/ _` | \ \ \ \ 
\\/ ___)| |_)| | | | | || (_| | )))) 
    ' |____| .__|_| |_|_| |_\__, |//// 
=========|_|==============|___/=/_/_/_/ 
:: Spring Boot ::  (v1.4.2.RELEASE) 

2016-12-10 16:41:04.035 INFO 25026 --- [   main] com.example.DemoApplication    : Starting DemoApplication on den with PID 25026 (/Users/dre/src/demo/target/classes started by dre in /Users/dre/src/demo) 
2016-12-10 16:41:04.039 INFO 25026 --- [   main] com.example.DemoApplication    : No active profile set, falling back to default profiles: default 
2016-12-10 16:41:04.108 INFO 25026 --- [   main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.spring[email protected]21507a04: startup date [Sat Dec 10 16:41:04 EST 2016]; root of context hierarchy 
2016-12-10 16:41:04.923 WARN 25026 --- [   main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'demoApplication': Unsatisfied dependency expressed through field 'dc'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'demoConfig' defined in file [/Users/dre/src/demo/target/classes/com/example/config/DemoConfig.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} 
2016-12-10 16:41:04.932 INFO 25026 --- [   main] utoConfigurationReportLoggingInitializer : 

Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. 
2016-12-10 16:41:05.035 ERROR 25026 --- [   main] o.s.b.d.LoggingFailureAnalysisReporter : 

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

Description: 

Parameter 0 of constructor in com.example.config.DemoConfig required a bean of type 'java.lang.String' that could not be found. 


Action: 

Consider defining a bean of type 'java.lang.String' in your configuration. 


Process finished with exit code 1 

application.yml

demo: 
    foo: 
    str_val: Make it work! 
    objVal.objVal: This one too! 

DemoApplication.java

package com.example; 

import com.example.config.DemoConfig; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.ApplicationArguments; 
import org.springframework.boot.ApplicationRunner; 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 

@SpringBootApplication 
public class DemoApplication implements ApplicationRunner { 

    @Autowired 
    private DemoConfig dc; 

    public static void main(String[] args) { 
     SpringApplication.run(DemoApplication.class, args); 
    } 

    @Override 
    public void run(ApplicationArguments args) throws Exception { 
     System.out.printf("String val: %s\nObject val: %s", dc.getStrVal(), dc.getObjVal()); 
    } 
} 

DemoConfig.java

package com.example.config; 

import lombok.Data; 
import org.hibernate.validator.constraints.NotBlank; 
import org.springframework.boot.context.properties.ConfigurationProperties; 
import org.springframework.stereotype.Component; 

@Data 
@Component 
@ConfigurationProperties(prefix = "demo.foo") 
public class DemoConfig { 
    @NotBlank private final String strVal; 
    private final ObjVal objVal; 

    @Data 
    public static class ObjVal { 
     @NotBlank private final String objVal; 
    } 
} 

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.example</groupId> 
    <artifactId>demo</artifactId> 
    <version>0.0.1-SNAPSHOT</version> 
    <packaging>jar</packaging> 

    <name>demo</name> 
    <description>Demo project for Spring Boot</description> 

    <parent> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-parent</artifactId> 
     <version>1.4.2.RELEASE</version> 
     <relativePath/> <!-- lookup parent from repository --> 
    </parent> 

    <properties> 
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 
     <java.version>1.8</java.version> 
    </properties> 

    <dependencies> 
     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-validation</artifactId> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-configuration-processor</artifactId> 
      <optional>true</optional> 
     </dependency> 
     <dependency> 
      <groupId>org.projectlombok</groupId> 
      <artifactId>lombok</artifactId> 
      <optional>true</optional> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-test</artifactId> 
      <scope>test</scope> 
     </dependency> 
    </dependencies> 

    <build> 
     <plugins> 
      <plugin> 
       <groupId>org.springframework.boot</groupId> 
       <artifactId>spring-boot-maven-plugin</artifactId> 
      </plugin> 
     </plugins> 
    </build> 


</project> 
+0

Nicht sicher, ob es das Problem ist, aber die Eigenschaft in application.yml verwendet einen Unterstrich, während das Klassenattribut camel case verwendet. Können die Felder wirklich endgültig sein? – Quagaar

+0

Versuchen Sie, die '@ Komponente' zu ​​entfernen; Ich glaube, dass Sie möglicherweise redundante Kopien erhalten, von denen nur eine die Umwelt-Injektionsbehandlung erhält. – chrylis

+0

@Quagaar Spring Boot sollte den ersten Teil behandeln. Nicht sicher über die Sekunde, aber ich vermute, dass es funktionieren sollte (beachten Sie, dass Lombok einen Konstruktor einfügt). – chrylis

Antwort

0

Lesen der Dokumentation helfen sollte.

Ihre Felder sind endgültig, es werden keine Setter generiert. Aber, this is a requirement for @ConfigurationProperties properties. Die Bindung funktioniert über Standard-Java-Beans-Eigenschaftendeskriptoren. Der Binder hat die Konstruktorinjektion nie unterstützt.

Aber dieser Fehler ist anders. Abhängigkeiten injection unterscheidet sich hier nicht von anderen Komponenten. Sie erstellen im Grunde eine @Component, die eine String und eine ObjVal als Argumente dauert. Wenn der Anwendungskontext versucht, die Bean zu erstellen, muss er zwei Beans finden, die diesen Typen entsprechen. Dies hat nichts mit @ConfigurationProperties zu tun.

Lange Rede kurzer Sinn, Ihre Klasse wie folgt ändern:

package com.example.config; 

import org.hibernate.validator.constraints.NotBlank; 
import org.springframework.boot.context.properties.ConfigurationProperties; 
import org.springframework.stereotype.Component; 

@Component 
@ConfigurationProperties(prefix = "demo.foo") 
public class DemoConfig { 
    @NotBlank private String strVal; 
    private final ObjVal objVal = new ObjVal(); 

    // getter & setter for strVal 

    // getter for objVal (we already have an instance so we can "crawl to it") 

    public static class ObjVal { 
     @NotBlank private String objVal; 

     // getter & setter for objVal 
    } 
} 

ich Lombok entfernt haben, um es explizit zu machen, dass es keine besonderen Konstruktor jetzt. Wenn Sie einen haben, müssen Parameter im Kontext verfügbar sein.

+0

Vielen Dank für Ihre Antwort. Der letzte Modifikator war in der Tat das Problem. Ich werde erwähnen, dass ich die Dokumentation sicherlich mehrmals gelesen habe. Das Stück, mit dem Sie verlinkt haben, sagt nicht explizit, dass Sie das endgültige Schlüsselwort nicht verwenden können. Tatsächlich heißt es: "Geschachtelte POJO-Eigenschaften können auch erstellt werden (** also ist ein Setzer nicht obligatorisch **), wenn sie einen Standardkonstruktor haben oder ein Konstruktor einen einzelnen Wert akzeptiert, der von String erzwungen werden kann." Mein Fehler war, dass ich nicht erkannte, dass dies nur für verschachtelte POJOs funktionierte, nicht für POJO auf Root-Ebene. – deinspanjer

+0

Ich denke, dass die Dokumentation uns jedes Mal zurückbeißt, wenn ich es referenziere, also ist es an der Zeit, dass wir noch mehr Liebe geben. Es tut mir leid, dass Sie das Dokument mehrmals gelesen haben und keine gute Antwort auf Ihre Frage gefunden haben. Ich habe [# 7620] (https://github.com/spring-projects/spring-boot/issues/7620) erstellt, um dies zu beheben. Fühlen Sie sich frei, es zu abonnieren. Vielen Dank! –

Verwandte Themen