2015-02-12 16 views
9

Używam Wiosna Boot 1.2.1 i próbuje stworzyć @ConfigurationProperties Bean z walidacji tak:Wiosna Boot @ConfigurationProperties nie pobierania od właściwości środowiska

package com.sampleapp; 

import java.net.URL; 

import javax.validation.constraints.NotNull; 

import org.springframework.boot.context.properties.ConfigurationProperties; 
import org.springframework.stereotype.Component; 

@Component 
@ConfigurationProperties 
public class SampleAppProperties { 
    @NotNull 
    private URL url; 

    public URL getUrl() { 
     return url; 
    } 
} 

klasy bootstrap aplikacji jest:

package com.sampleapp; 

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.boot.context.properties.EnableConfigurationProperties; 
import org.springframework.context.EnvironmentAware; 
import org.springframework.core.env.Environment; 

@SpringBootApplication 
@EnableConfigurationProperties 
public class SampleApplication implements EnvironmentAware { 
    private static Logger LOGGER = LoggerFactory.getLogger(SampleApplication.class); 

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

    @Override 
    public void setEnvironment(Environment environment) { 
     LOGGER.info("URL = {}", environment.getRequiredProperty("url")); 
    } 
} 

Kiedy próbuję uruchomić tę aplikację i pojawia się następujący wyjątek: stos

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sampleAppProperties': Could not bind properties to [unknown] (target=, ignoreInvalidFields=false, ignoreUnknownFields=true, ignoreNestedProperties=false); nested exception is org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors 
Field error in object 'target' on field 'url': rejected value [null]; codes [NotNull.target.url,NotNull.url,NotNull.java.net.URL,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [target.url,url]; arguments []; default message [url]]; default message [may not be null] 
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:303) 
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:250) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:408) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1558) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:762) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480) 
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:321) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:961) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:950) 
    at com.sampleapp.SampleApplication.main(SampleApplication.java:17) 
Caused by: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors 
Field error in object 'target' on field 'url': rejected value [null]; codes [NotNull.target.url,NotNull.url,NotNull.java.net.URL,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [target.url,url]; arguments []; default message [url]]; default message [may not be null] 
    at org.springframework.boot.bind.PropertiesConfigurationFactory.validate(PropertiesConfigurationFactory.java:294) 
    at org.springframework.boot.bind.PropertiesConfigurationFactory.doBindPropertiesToTarget(PropertiesConfigurationFactory.java:253) 
    at org.springframework.boot.bind.PropertiesConfigurationFactory.bindPropertiesToTarget(PropertiesConfigurationFactory.java:225) 
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:296) 
    ... 17 common frames omitted 

Jak widać w sposobie setEnvironment powyżej mam zalogowaniu właściwość url aby potwierdzić, że jest to część Environment i jest on wyświetlany przed wyłączeniem:

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

2015-02-12 12:32:01.384 INFO 5608 --- [   main] c.s.SampleApplication     : Starting SampleApplication on VDDK03E-14FB6E5 with PID 5608 (D:\projects\onboarding-parser\target\classes started by ..... 
2015-02-12 12:32:01.509 INFO 5608 --- [   main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.spring[email protected]3252ac20: startup date [Thu Feb 12 12:32:01 EST 2015]; root of context hierarchy 
2015-02-12 12:32:03.040 INFO 5608 --- [   main] c.s.SampleApplication     : URL = http://www.joe.com 
2015-02-12 12:32:03.378 ERROR 5608 --- [   main] o.s.b.b.PropertiesConfigurationFactory : Properties configuration failed validation 
2015-02-12 12:32:03.378 ERROR 5608 --- [   main] o.s.b.b.PropertiesConfigurationFactory : Field error in object 'target' on field 'url': rejected value [null]; codes [NotNull.target.url,NotNull.url,NotNull.java.net.URL,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [target.url,url]; arguments []; default message [url]]; default message [may not be null] 
2015-02-12 12:32:03.394 WARN 5608 --- [   main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt 

Obiekt url są pobierane z pliku application.properties w src/main/resources. Zawartość pliku to:

url=http://www.joe.com 
+0

Czy 'DataBinder' obsługuje' URL' jako typ docelowy? Co się stanie, jeśli zmienisz typ pola na "String"? – chrylis

Odpowiedz

20

W twoim fasolku nie ma setera. Dodaj setera.

+0

To było to. Dziękuję Ci! – Centinul

+0

Czy tęskniłem w dokumentacji przypadkiem? Jeśli tak, czy możesz wskazać mi lokalizację? – Centinul

3

Jest wyraźnie napisane: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-typesafe-configuration-properties

pobierające i ustawiające są zazwyczaj obowiązkowe, ponieważ wiązanie jest poprzez standardowe deskryptory Java Beans własności, podobnie jak w Spring MVC. Zdarzają się sytuacje, w których seter może zostać pominięty: Mapy, dopóki są inicjowane, wymagają gettera, ale niekoniecznie są ustawione, ponieważ mogą być zmutowane przez segregator. Kolekcje i tablice mogą być dostępne przez indeks (zazwyczaj z YAML) lub za pomocą pojedynczej wartości oddzielonej przecinkami (właściwości). W tym drugim przypadku seter jest obowiązkowy. Zalecamy zawsze dodawać setera dla tego typu. Jeśli zainicjujesz kolekcję, upewnij się, że nie jest ona niezmienna (jak w powyższym przykładzie). Jeśli zagnieżdżone właściwości POJO są zainicjowane (jak w polu Zabezpieczenia w powyższym przykładzie), ustawiacz nie jest wymagany. Jeśli chcesz, aby spinacz tworzył instancję w locie przy użyciu jej domyślnego konstruktora, będziesz potrzebował ustawiacza. Niektóre osoby używają programu Project Lombok do automatycznego dodawania elementów pobierających i ustawiających. Upewnij się, że Lombok nie generuje żadnego konkretnego konstruktora dla tego typu, ponieważ będzie on używany automatycznie przez kontener, aby utworzyć instancję obiektu.

Powiązane problemy