Não foi possível resolver o marcador de posição no valor da string

86

Estou tentando usar as propriedades de um .propertiesarquivo, mas não parece funcionar.

Aqui está o meu código:

@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;

[...]

}

Esta classe usa @Valueanotações para obter as propriedades. Ele também é declarado como um serviço Spring e está vinculado ao meu infraContext.xmlarquivo:

<?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>

Usando context:property-placeholder, eu vinculo este arquivo ao meu context-core.propertiesarquivo:

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

Isso faz sentido, certo?

Mas quando tento lançar meu projeto, o Tomcat lança esta exceção:

    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

Ou, resumindo: java.lang.IllegalArgumentException: Could not resolve placeholder 'project.ftp.adresse' in string value "${project.ftp.adresse}"

EDITAR:

Aqui está meu 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>

Meu infraContext.xml é importado em outro arquivo .xml chamado 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>

Estou obviamente perdendo alguma coisa, mas não consigo descobrir o quê.

Avise-me se precisar de mais detalhes, pois é minha primeira pergunta aqui, tentarei responder assim que puder :).

Hwen
fonte
1
Onde você está infraContext.xmlsendo carregado? A julgar pelo rastreamento de pilha, ele não está incluído na configuração carregada pelo ContextLoaderListener. Por favor, poste seu web.xml.
M. Deinum
2
O problema é que você tem várias instâncias de uma PropertySourcesPlaceholderConfigurerdefinida explicitamente (por quê?) E outra devido ao namespace. Aquele no seu applicationContext.xmlnão está fazendo nada nem adicionando nada. Remova.
M. Deinum

Respostas:

73

Em sua configuração, você tem 2 PropertySourcesPlaceholderConfigurerinstâncias.

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"/>

Por padrão, PlaceholderConfigurera falhará rapidamente, portanto, se um marcador não puder ser resolvido, ele lançará uma exceção. A instância do applicationContext.xmlarquivo não tem propriedades e, como tal, falhará em todos os marcadores de posição.

Solução: Remova o de applicationContext.xml , pois não adiciona nada, apenas quebra as coisas.

M. Deinum
fonte
Incrível, obrigado, então presumo que na primavera só pode haver uma instância de PlaceholderConfigurer?
Mushtaq Jameel
11
Não, você pode ter vários, no entanto, por padrão, eles falham rapidamente se um espaço reservado não for encontrado. Você pode desativar isso configurando ignore-unresolved-placeholderspara true.
M. Deinum
3
como posso lidar com isso na bota de primavera com anotações?
rezKesh
5

Eu tive o mesmo problema, resolvi adicionando

<filtering>true</filtering> 

em pom.xml:

antes (não funcionou):

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

depois (funcionou):

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

Depois disso, basta executar o aplicativo mvn clean install e deploy.

user2910552
fonte
Obrigado, isso resolveu meu problema. Estou curioso, porém, por que / como o plug-in de recursos do maven está afetando os marcadores de posição da primavera ... Eu nunca teria imaginado que eles estavam relacionados!
Pim Hazebroek 01 de
3

Este problema ocorre se o aplicativo não puder acessar o arquivo some_file_name.properties. Certifique-se de que o arquivo de propriedades seja colocado na pasta de recursos na primavera.

Etapas de solução de problemas

1: Adicione o arquivo de propriedades na pasta de recursos.

2: Se você não tiver uma pasta de recursos. Crie um navegando em new clicando com o botão direito no projeto new> Source Folder, nomeie-o como recurso e coloque seu arquivo de propriedades sob ele.

Para implementação baseada em anotação

Adicionar @PropertySource(ignoreResourceNotFound = true, value = "classpath:some_file_name.properties")// Adicione antes de usar o marcador de posição

Exemplo:

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;

        }  

}

atribuição1.properties

app.title=Learning Spring
Gani
fonte
1
Isso se aplica ao Spring4 e posterior?
Malkocoglu
Sim @Malkocoglu
Gani
3

No meu caso, fui descuidado ao mesclar o arquivo application.yml e indentei desnecessariamente minhas propriedades para a direita.

Eu indentei assim:

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

Embora o código esperasse que fosse assim:

spring:
    application:
        name: applicationName
.............................
myProperties:
    property1: property1value
Semir Deljić
fonte
3

Você também pode tentar os valores padrão. spring-value-annotation

Os valores padrão podem ser fornecidos para propriedades que podem não ser definidas. Neste exemplo, o valor "algum padrão" será injetado:

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

Se a mesma propriedade for definida como uma propriedade do sistema e no arquivo de propriedades, a propriedade do sistema será aplicada.

Akasha
fonte
Ok ... isso me ajudou. Na verdade, meu aplicativo tem muitos arquivos application- <profile> .yml, e eu estava recebendo um erro devido a uma nova propriedade definida na configuração principal. arquivo apenas. Honestamente, eu esperava definir o valor apenas uma vez na configuração principal e, no caso, substituir o valor em uma configuração específica do perfil. Parece que não funciona assim e um valor padrão deve ser sempre fornecido. Agora eu entendo porque minhas configurações java estavam falhando, quando eu não inicializei propriedades com um valor padrão! Esse comportamento pode ser alterado? Obrigado :-)
funder7
2

Eu tenho o mesmo erro no meu micro-serviço, sempre que você declara a anotação @Value no programa, ou seja, @Value ("$ {project.api.key}")

certifique-se de que seu arquivo application.properties com os mesmos valores não deve estar em branco project.api.key = add some values

MostIMP : caso contrário, ele lançará o erro "Erro ao criar bean com o nome 'ServiceFTP': Injeção de dependências autowired"

Ankush Thakur
fonte
0

Com Spring Boot:

No pom.xml

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

Exemplo na classe 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;
    }
    [ ... ]

Nos arquivos de propriedades:

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

Nos argumentos VM de Application.java

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

Não se esqueça de executar o comando mvn após modificar as propriedades!

mvn clean package -Dmaven.test.skip=true

No arquivo de log para -Dspring.profiles.active = rec:

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

No arquivo de log para -Dspring.profiles.active = prod:

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

No arquivo de log para -Dspring.profiles.active = local:

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

Oups, esqueci de criar application-local.properties.

cdesmetz
fonte
0

Recebi o mesmo erro em meu projeto de microsserviço. A propriedade em si faltou no meu arquivo yml. Portanto, adicionei o nome da propriedade e o valor que resolve meu problema

Dhivya
fonte
0

Este erro aparece porque o projeto spring não lê as propriedades do arquivo ( bootstrap.yml ou application.yml ). Para resolver isso, você deve adicionar dependência no seu pom.xml

   <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-context</artifactId>
    </dependency>
YAO ALEX DIDIER AKOUA
fonte
-1

Excluir ou corromper o arquivo pom.xml pode causar esse erro.

Renato Vasconcellos
fonte
-3

Minha solução foi adicionar um espaço entre $ e {.

Por exemplo:

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

torna-se

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