Nie można rozpoznać symbolu zastępczego w wartości ciągu

86

Próbuję użyć właściwości z .propertiespliku, ale wydaje się, że nie działa.

Oto mój kod:

@Service("ServiceFTP")
@Transactional
public class ServiceFTPImpl implements ServiceFTP {

@Value("${project.ftp.adresse}")
private String adresse;

@Value("${project.ftp.login}")
private String compte;

@Value("${project.ftp.password}")
private String motDePasse;

@Value("${project.ftp.root}")
private String ROOT;

[...]

}

Ta klasa używa @Valueadnotacji do pobierania właściwości. Jest również zadeklarowany jako usługa Spring i jest powiązany z moim infraContext.xmlplikiem:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">

<context:property-placeholder location="classpath:context-core.properties"/>

[...]

</beans>

Używając context:property-placeholder, łączę ten plik z moim context-core.propertiesplikiem:

project.ftp.adresse = localhost
project.ftp.login = anonymous
project.ftp.password =
project.ftp.root = /anonymous/

To ma sens, prawda?

Ale kiedy próbuję uruchomić mój projekt, Tomcat rzuca ten wyjątek:

    ERROR [context.ContextLoader.initWebApplicationContext()] Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ServiceFTP': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.String project.sins.service.impl.ServiceFTPImpl.adresse; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'project.ftp.adresse' in string value "${project.ftp.adresse}"
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:925)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:472)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:388)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:293)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4887)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5381)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:633)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:657)
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1636)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:722)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.String project.sins.service.impl.ServiceFTPImpl.adresse; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'project.ftp.adresse' in string value "${project.ftp.adresse}"
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:513)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:92)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284)
    ... 27 more
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'project.ftp.adresse' in string value "${project.ftp.adresse}"
    at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:173)
    at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:125)
    at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:151)
    at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:142)
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:169)
    at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:748)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:740)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:730)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:485)
    ... 29 more

Lub w skrócie: java.lang.IllegalArgumentException: Could not resolve placeholder 'project.ftp.adresse' in string value "${project.ftp.adresse}"

EDYTOWAĆ :

Oto mój web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         id="sins" version="2.5">

    <display-name>Project</display-name>

    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>

    <context-param>
        <param-name>log4jExposeWebAppRoot</param-name>
        <param-value>false</param-value>
    </context-param>

    <filter>
        <filter-name>ExpiresFilter</filter-name>
        <filter-class>org.apache.catalina.filters.ExpiresFilter</filter-class>
        <init-param>
            <param-name>ExpiresByType text/html</param-name>
            <param-value>now plus 0 seconds</param-value>
        </init-param>
        <init-param>
            <param-name>ExpiresByType application/json</param-name>
            <param-value>now plus 0 seconds</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>ExpiresFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>

    <filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
        <filter-class>
            org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
        </filter-class>
    </filter>

    <filter-mapping>
        <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <listener>
        <listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class>
    </listener>

    <context-param>
        <param-name>
            org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG
        </param-name>
        <param-value>
            /WEB-INF/tiles/user.xml
        </param-value>
    </context-param>

    <resource-ref>
        <res-ref-name>jdbc/si_nsg</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>

    <session-config>
        <session-timeout>60</session-timeout>
    </session-config>

</web-app>

Mój plik infraContext.xml jest importowany do innego pliku .xml o nazwie applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd">

    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
        <property name="environment">
            <bean class="org.springframework.web.context.support.StandardServletEnvironment"/>
        </property>
    </bean>

    <import resource="classpath:securityContext.xml"/>

    [...]
    <import resource="classpath:project/sins/persistenceContext.xml"/>

    <import resource="classpath:project/sins/infraContext.xml"/>

</beans>

Oczywiście czegoś mi brakuje, ale nie wiem co.

Daj mi znać, jeśli potrzebujesz więcej informacji, ponieważ jest to moje pierwsze pytanie tutaj, postaram się odpowiedzieć jak najszybciej :).

Hwen
źródło
1
Gdzie infraContext.xmljesteś ładowany? Sądząc po stacktrace, nie jest on uwzględniony w konfiguracji załadowanej przez ContextLoaderListener. Proszę opublikować swój plik web.xml.
M. Deinum
2
Problem polega na tym, że masz wiele wystąpień PropertySourcesPlaceholderConfigurerjednego jawnie zdefiniowanego (dlaczego?) I jednego z powodu przestrzeni nazw. Ten w twoim applicationContext.xmlnie robi nic ani niczego nie dodaje. Usunąć to.
M. Deinum

Odpowiedzi:

73

W swojej konfiguracji masz 2 PropertySourcesPlaceholderConfigurerinstancje.

applicationContext.xml

<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
    <property name="environment">
        <bean class="org.springframework.web.context.support.StandardServletEnvironment"/>
    </property>
</bean>

infraContext.xml

<context:property-placeholder location="classpath:context-core.properties"/>

Domyślnie a PlaceholderConfigurerbędzie działać szybko, więc jeśli nie można rozwiązać symbolu zastępczego, zgłosi wyjątek. Instancja z applicationContext.xmlpliku nie ma właściwości i jako taka zakończy się niepowodzeniem dla wszystkich symboli zastępczych.

Rozwiązanie: Usuń ten z applicationContext.xml, ponieważ nie dodaje niczego, a jedynie psuje.

M. Deinum
źródło
Świetnie, dziękuję, więc rozumiem, że wiosną może być tylko jeden przypadek PlaceholderConfigurer?
Mushtaq Jameel
11
Nie, możesz mieć wiele, ale domyślnie szybko zawodzą, jeśli nie zostanie znaleziony symbol zastępczy. Możesz to wyłączyć, ustawiając ignore-unresolved-placeholdersna true.
M. Deinum,
3
jak sobie z tym poradzić w wiosennych butach z adnotacjami?
rezKesh
5

Miałem ten sam problem, rozwiązałem go dodając

<filtering>true</filtering> 

w pom.xml:

przed (nie działało):

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>               
        </resource>
    </resources>
</build>

po (zadziałało):

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

Następnie wystarczy uruchomić mvn clean install i wdrożyć aplikację.

user2910552
źródło
Dzięki, to rozwiązało mój problem. Jestem jednak ciekawy, dlaczego / w jaki sposób wtyczka zasobów Maven wpływa na elementy zastępcze wiosny ... Nigdy bym nie przypuszczał, że są powiązane!
Pim Hazebroek
3

Ten problem występuje, jeśli aplikacja nie może uzyskać dostępu do pliku nazwa_pliku.properties. Upewnij się, że plik właściwości zostanie umieszczony w folderze zasobów na wiosnę.

Rozwiązywanie problemów Kroki

1: Dodaj plik właściwości do folderu zasobów.

2: jeśli nie masz folderu zasobów. Utwórz go, przechodząc do nowego, klikając prawym przyciskiem myszy projekt nowy> Folder źródłowy, nazwij go jako zasób i umieść pod nim plik właściwości.

Do implementacji opartej na adnotacjach

Dodaj @PropertySource(ignoreResourceNotFound = true, value = "classpath:some_file_name.properties")// Dodaj przed użyciem elementu zastępczego

Przykład:

Assignment1Controller.Java

@PropertySource(ignoreResourceNotFound = true, value = "classpath:assignment1.properties")
@RestController  
public class Assignment1Controller {

//  @Autowired
//  Assignment1Services assignment1Services;
    @Value("${app.title}")
    private String appTitle;
     @RequestMapping(value = "/hello")  
        public String getValues() {

          return appTitle;

        }  

}

assignment1.properties

app.title=Learning Spring
Gani
źródło
1
Czy dotyczy to Spring4 i nowszych?
Malkocoglu
Tak @Malkocoglu
Gani
3

W moim przypadku byłem nieostrożny podczas scalania pliku application.yml i niepotrzebnie wciąłem moje właściwości w prawo.

Wcięłem to w ten sposób:

spring:
    application:
       name: applicationName
............................
    myProperties:
       property1: property1value

Chociaż kod spodziewał się, że będzie tak:

spring:
    application:
        name: applicationName
.............................
myProperties:
    property1: property1value
Semir Deljić
źródło
3

Możesz także wypróbować wartości domyślne. adnotacja-wartości-sprężyny

Można podać wartości domyślne dla właściwości, które mogą nie być zdefiniowane. W tym przykładzie zostanie wstawiona wartość „some default”:

@Value("${unknown.param:some default}")
private String someDefault;

Jeśli ta sama właściwość jest zdefiniowana jako właściwość systemowa i w pliku właściwości, wówczas zostanie zastosowana właściwość systemowa.

akasha
źródło
Dobra ... to mi pomogło. W rzeczywistości moja aplikacja ma wiele plików application- <profile> .yml i otrzymywałem błąd z powodu nowej właściwości zdefiniowanej w głównej konfiguracji. tylko plik. Szczerze mówiąc spodziewałem się zdefiniowania wartości tylko raz w głównej konfiguracji, aw przypadku nadpisania wartości w konfiguracji specyficznej dla profilu. Wygląda na to, że to nie działa i zawsze należy podać wartość domyślną. Teraz rozumiem, dlaczego moje konfiguracje Java zawiodły, kiedy nie zainicjowałem właściwości z wartością domyślną! Czy można zmienić to zachowanie? Dzięki :-)
funder7
2

Mam ten sam błąd w mojej mikroserwisie, za każdym razem, gdy deklarujesz adnotację @Value w programie, tj. @Value („$ {project.api.key}”)

upewnij się, że plik application.properties z tymi samymi wartościami nie powinien być pusty project.api.key = dodaj jakieś wartości

MostIMP : w przeciwnym razie wygeneruje błąd „Błąd podczas tworzenia komponentu bean o nazwie„ ServiceFTP ”: Wstrzyknięcie autowired zależności”

Ankush Thakur
źródło
0

Z butem wiosennym:

W pliku pom.xml

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

Przykład w klasie Java

@Configuration
@Slf4j
public class MyAppConfig {
    @Value("${foo}")
    private String foo;
    @Value("${bar}")
    private String bar;
    @Bean("foo")
    public String foo() {
        log.info("foo={}", foo);
        return foo;
    }
    @Bean("bar")
    public String bar() {
        log.info("bar={}", bar);
        return bar;
    }
    [ ... ]

W plikach właściwości:

src / main / resources / application.properties

foo=all-env-foo

src / main / resources / application-rec.properties

bar=rec-bar

src / main / resources / application-prod.properties

bar=prod-bar

W argumentach VM pliku Application.java

-Dspring.profiles.active=[rec|prod]

Nie zapomnij uruchomić komendy mvn po zmodyfikowaniu właściwości!

mvn clean package -Dmaven.test.skip=true

W pliku dziennika -Dspring.profiles.active = rec:

The following profiles are active: rec
foo=all-env-foo
bar=rec-bar

W pliku dziennika dla -Dspring.profiles.active = prod:

The following profiles are active: prod
foo=all-env-foo
bar=prod-bar

W pliku dziennika dla -Dspring.profiles.active = local:

Could not resolve placeholder 'bar' in value "${bar}"

Ups, zapomniałem stworzyć application-local.properties.

cdesmetz
źródło
0

Wystąpił ten sam błąd w moim projekcie mikrousługi. Brakuje samej właściwości w moim pliku yml, więc dodałem nazwę właściwości i wartość, która rozwiązuje mój problem

Dhivya
źródło
0

Ten błąd pojawia się, ponieważ projekt Spring nie odczytuje właściwości pliku ( bootstrap.yml lub application.yml ). Aby rozwiązać ten problem, musisz dodać zależność w swoim pom.xml

   <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-context</artifactId>
    </dependency>
YAO ALEX DIDIER AKOUA
źródło
-1

Usunięcie lub uszkodzenie pliku pom.xml może spowodować ten błąd.

Renato Vasconcellos
źródło
-3

Moim rozwiązaniem było dodanie spacji między znakami $ a {.

Na przykład:

@Value("${project.ftp.adresse}")

staje się

@Value("$ {project.ftp.adresse}")
Ben G.
źródło