0

I am having difficult in deploying a spring-webmvc application to cloud foundry. Error is related to application.properties placeholders are not resolved by CF environment. Error is below

22:14:41.152: [APP/PROC/WEB.0] [CONTAINER] org.apache.jasper.servlet.TldScanner               INFO    At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
22:14:41.215: [APP/PROC/WEB.0] [CONTAINER] lina.core.ContainerBase.[Catalina].[localhost].[/] INFO    No Spring WebApplicationInitializer types detected on classpath
22:14:41.544: [APP/PROC/WEB.0] [CONTAINER] lina.core.ContainerBase.[Catalina].[localhost].[/] INFO    Initializing Spring root WebApplicationContext
22:14:41.947: [APP/PROC/WEB.0] [CONTAINER] org.cloudfoundry.reconfiguration.ProfileUtils      INFO    'cloud' profile activated
22:14:42.088: [APP/PROC/WEB.0] [CONTAINER] n.CloudPropertySourceApplicationContextInitializer INFO    'cloud' property source added
22:14:42.090: [APP/PROC/WEB.0] [CONTAINER] erviceReconfigurationApplicationContextInitializer INFO    Reconfiguration enabled
22:14:42.633: [APP/PROC/WEB.0] 03:14:42.622 [main] ERROR org.springframework.web.context.ContextLoader - Context initialization failed
22:14:42.639: [APP/PROC/WEB.0]  at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:831)
22:14:42.633: [APP/PROC/WEB.0] org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'dataSource' defined in ServletContext resource [/WEB-INF/test-servlet.xml]: Could not resolve placeholder 'datasource.url' in string value "${datasource.url}"; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'datasource.url' in string value "${datasource.url}"
22:14:42.633: [APP/PROC/WEB.0]  at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:211) ~[spring-beans-4.0.3.RELEASE.jar:4.0.3.RELEASE]

I am deploying application using concourse to CF. below is my pipeline code:

jobs:
- name: maven-build-and-deploy
  serial: true
  public: true
  plan: 
  - get: mygit
  - task: mvn-package
    privileged: true
    config:
      platform: linux
      image_resource:
        type: docker-image
        source:
          repository: test/alpine-jdk8-maven
          tag: latest
      inputs:
      - name: test11
      outputs:
      - name: maven-package-output
      run:
        path: sh
        args:
        -  -exc
        -   |
              set -xe
              cd test
              mvn package
              cp target/test.war ../maven-package-output
  - put: cf-push
    resource: cf-env
    params:
      path: maven-package-output/test.war
      manifest: test/manifest.yml
      environment_variables:
        datasource.url: ((datasource.url))
        datasource.username: ((datasource.username))
        datasource.password: ((datasource.password))

Above environment variables are configured in Cloud Foundry. These environment variables are read by application.properties file and this is causing issue.

I have configured the same application in local tomcat. created a setenv.sh file with properties and copied to tomcat/bin folder. when deployed working succcessfully.

When deployed to CF, causing issue.

Below is my pom.xml, including only depenedencies

 <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${springframework.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${springframework.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${springframework.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${springframework.version}</version>
        </dependency>
<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${springframework.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>${spring.jpa.data.version}</version>
        </dependency>

application.properties

database.url = ${datasource.url}
database.username = ${datasource.username}
database.password = ${datasource.password}

test-servlet.xml (context loader)

<?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"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:task="http://www.springframework.org/schema/task"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
                  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
                  http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
                  http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
                  http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd">

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

    <tx:annotation-driven transaction-manager="transactionManager"/>

  <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${database.driverClassName}" />
    <property name="url" value="${database.url}" />
    <property name="username" value="${database.username}" />
    <property name="password" value="${database.password}" />
  </bean>

How will application.properties read environment variables from CF environment. Please help in resolving this issue.

Vipul
  • 545
  • 1
  • 8
  • 30
  • Anyone please let me know how to proceed on this issue? – Vipul Mar 02 '21 at 13:33
  • After enabling auto re-configuration, I could get data source connection. But still I want to read user-defined properties. I tried reading them using VCAP. still not reading – Vipul Mar 03 '21 at 14:15

1 Answers1

0

In your pipeline, you are setting these env variables:

        datasource.url: ((datasource.url))
        datasource.username: ((datasource.username))
        datasource.password: ((datasource.password))

A problem I see, there may be others, is that datasource.url is the actual env variable name that will be used, however, that's not technically a valid env variable name. The . is not allowed (neither is a -). These variables will end up not being set because the shell will filter them out, due to the invalid characters.

Allowed characters in Linux environment variable names

The recommendation from the Spring Boot documentation is to name environment variables:

  1. In all CAPS
  2. Change spaces and . (dot or period) to _ (underscore)
  3. Remove -.

So if you want to set the datasource.url property, you need to set DATASOURCE_URL. Similary, if you want to set the property foo.bar-prop, you'd want to set an env variable of FOO_BARPROP.

See the docs on relaxed bindings for more info: https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-relaxed-binding

Daniel Mikusa
  • 13,716
  • 1
  • 22
  • 28