No se pudo resolver el marcador de posición en el valor de la cadena

86

Estoy intentando usar las propiedades de un .propertiesarchivo, pero parece que no funciona.

Aquí está mi 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 clase usa @Valueanotaciones para obtener las propiedades. También se declara como un servicio Spring y está vinculado a mi infraContext.xmlarchivo:

<?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, vinculo este archivo a mi context-core.propertiesarchivo:

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

Esto tiene sentido, ¿verdad?

Pero cuando intento lanzar mi proyecto, Tomcat lanza esta excepción:

    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

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

EDITAR:

Aquí está mi 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>

Mi infraContext.xml se importa en otro archivo .xml llamado 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>

Obviamente me estoy perdiendo algo, pero no puedo averiguar qué.

Por favor, avíseme si necesita más detalles, ya que es mi primera pregunta aquí, intentaré responder lo antes posible :).

Hwen
fuente
1
¿Dónde está infraContext.xmlsiendo cargado? A juzgar por el stacktrace, no está incluido en la configuración cargada por ContextLoaderListener. Publique su archivo web.xml.
M. Deinum
2
El problema es que tiene varias instancias de una PropertySourcesPlaceholderConfigurerdefinida explícitamente (¿por qué?) Y una debido al espacio de nombres. El que está en tu applicationContext.xmlno hace nada ni agrega nada. Retirarlo.
M. Deinum

Respuestas:

73

En su configuración tiene 2 PropertySourcesPlaceholderConfigurer instancias.

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

De forma predeterminada, PlaceholderConfigurera fallará rápidamente, por lo que si un marcador de posición no se puede resolver, lanzará una excepción. La instancia delapplicationContext.xml archivo no tiene propiedades y, como tal, fallará en todos los marcadores de posición.

Solución: elimine el de applicationContext.xml ya que no agrega nada, solo rompe cosas.

M. Deinum
fuente
Impresionante, gracias, así que supongo que en primavera solo puede haber una instancia de un PlaceholderConfigurer?
Mushtaq Jameel
11
No, puede tener varios, sin embargo, de forma predeterminada, fallan rápidamente si no se encuentra un marcador de posición. Puede deshabilitar esto estableciendo ignore-unresolved-placeholdersen true.
M. Deinum
3
¿Cómo puedo manejarlo en el arranque de primavera con anotaciones?
rezKesh
5

Tuve el mismo problema, lo resolví agregando

<filtering>true</filtering> 

en pom.xml:

antes (no funcionó):

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

después (funcionó):

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

Después de eso, simplemente ejecute mvn clean install and deploy application.

usuario2910552
fuente
Gracias, esto resolvió mi problema. Sin embargo, tengo curiosidad, ¿por qué / cómo el complemento de recursos de maven afecta a los marcadores de posición de primavera?
Pim Hazebroek
3

Este problema ocurre si la aplicación no puede acceder al archivo some_file_name.properties. Asegúrese de que el archivo de propiedades esté ubicado en la carpeta de recursos en Spring.

Pasos para solucionar problemas

1: agregue el archivo de propiedades en la carpeta de recursos.

2: si no tiene una carpeta de recursos. Cree uno navegando por nuevo. Haga clic derecho en el proyecto nuevo> Carpeta de origen, asígnele el nombre de recurso y coloque su archivo de propiedades debajo.

Para implementación basada en anotaciones

Añadir @PropertySource(ignoreResourceNotFound = true, value = "classpath:some_file_name.properties") // Agregarlo antes de usar el marcador de posición

Ejemplo:

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;

        }  

}

asignación1.propiedades

app.title=Learning Spring
Gani
fuente
1
¿Esto se aplica a Spring4 y posteriores?
Malkocoglu
Sí @Malkocoglu
Gani
3

En mi caso, fui descuidado al fusionar el archivo application.yml, y he sangrado innecesariamente mis propiedades a la derecha.

Lo he sangrado así:

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

Si bien el código esperaba que fuera así:

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

También puede probar los valores predeterminados. anotación-valor-resorte

Se pueden proporcionar valores predeterminados para propiedades que pueden no estar definidas. En este ejemplo, se inyectará el valor "algunos predeterminados":

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

Si la misma propiedad está definida como propiedad del sistema y en el archivo de propiedades, entonces se aplicaría la propiedad del sistema.

Akasha
fuente
Está bien ... esto me ayudó. De hecho, mi aplicación tiene muchos archivos application- <profile> .yml, y recibía un error debido a una nueva propiedad definida en la configuración principal. archivo solamente. Honestamente, esperaba definir el valor solo una vez en la configuración principal y, en caso de que se anule el valor en una configuración específica de perfil. Parece que no funciona así, y siempre se debe proporcionar un valor predeterminado. ¡Ahora entiendo por qué fallaban mis configuraciones de Java, cuando no inicialicé las propiedades con un valor predeterminado! ¿Se puede cambiar este comportamiento? Gracias :-)
funder7
2

Recibí el mismo error en mi microservicio, siempre que declaras la anotación @Value en el programa, es decir, @Value ("$ {project.api.key}")

asegúrese de que su archivo application.properties con los mismos valores no debe estar en blanco project.api.key = agregar algunos valores

MostIMP : de lo contrario, arrojará el error "Error al crear un bean con el nombre 'ServiceFTP': Inyección de dependencias cableadas automáticamente"

Ankush Thakur
fuente
0

Con Spring Boot:

En el pom.xml

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

Ejemplo en clase 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;
    }
    [ ... ]

En los archivos de propiedades:

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

En los argumentos de la VM de Application.java

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

¡No olvide ejecutar el comando mvn después de modificar las propiedades!

mvn clean package -Dmaven.test.skip=true

En el archivo de registro de -Dspring.profiles.active = rec:

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

En el archivo de registro de -Dspring.profiles.active = prod:

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

En el archivo de registro de -Dspring.profiles.active = local:

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

Oups, me olvido de crear application-local.properties.

cdesmetz
fuente
0

Recibí el mismo error en mi proyecto de microservicio. La propiedad en sí faltaba en mi archivo yml. Así que agregué el nombre y el valor de la propiedad que resuelve mi problema

Dhivya
fuente
0

Este error aparece porque el proyecto Spring no lee las propiedades del archivo ( bootstrap.yml o application.yml ). Para resolver esto, debe agregar dependencia en su pom.xml

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

Eliminar o dañar el archivo pom.xml puede causar este error.

Renato Vasconcellos
fuente
-3

Mi solución fue agregar un espacio entre $ y {.

Por ejemplo:

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

se convierte en

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