1

I have Spring Boot API that I run on Liberty or OpenLiberty server.

In Liberty server.env file I have settings for logging like:

log_dir=C:\mydir

log_level=INFO

Then in my application.properties file, I have setting like:

logging.file.name=${log_dir}

logging.level.org.springframework=${log_level}

I would expect that when the application starts, the log_dir and log_level will be resolved successfully.

However, instead I get error IllegalArgumentException: Could not resolve placeholder 'log_dir' in '${log_dir}'.

Interestingly, it only happens on log_dir but not on log_level.

The only way to resolve it I found is to hardcode the setting for log_dir so in my application.properties I hardcode it like logging.file.name=C:\mydir instead of logging.file.name=${log_dir}.

Note that I do not have to hardcode value for log_level and it gets resolved just fine.

But that of course is not the good solution.

ADDITIONAL INFO

I am setting log_dir... in server.env since this is our requirement and the app is deployed to different environments where each may log files at different level and locations. Beside, some of the information, we dont want to share in code repository but keep safe on server side.

I do not use liberty-maven-plugin.

I do use spring-boot-maven-plugin and it is set as:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <!-- to expose build info in actuator/info -->
        <execution>
            <goals>
                <goal>build-info</goal>
            </goals>
        </execution>
    </executions>
</plugin>

I am packaging the app as a war file, so in my pom.xml, I have:

<packaging>war</packaging>

My Liberty server.xml uses following features:

  <featureManager>
    <feature>javaee-8.0</feature>
    <feature>microProfile-3.3</feature>
    <feature>jndi-1.0</feature>
    <feature>localConnector-1.0</feature>
    <feature>jca-1.7</feature>
    <feature>jdbc-4.2</feature>
    <feature>springBoot-2.0</feature>
    <feature>servlet-4.0</feature>
    <feature>adminCenter-1.0</feature>
  </featureManager>

UPDATE

More interesting finding. Depending on how do I call the "log_dir" variable in server.env, I get following results:

  • log_dir=C:/me/myapi.log - I get problem described above

    log.dir=C:/me/myapi.log - It works as expected

    logDir=C:/me/myapi.log - It works as expected

I am not sure why is Spring Boot deployed on Liberty having issues resolving log_dir but no issues resolving log_level?

Or why is Spring Boot deployed on Liberty having issues resolving log_dir but no issue resolving log.dir or logDir?

Scott Kurz
  • 4,985
  • 1
  • 18
  • 40
pixel
  • 9,653
  • 16
  • 82
  • 149
  • Are you using server.env because you need 'log_dir' and 'log_level' to specifically be set as environment variables ? Or are you more just trying to take an existing application.properties file and provide the Liberty config somewhere Liberty-specific (like server.env)? Is it correct to assume you're building a runnable JAR using a combination of the spring-boot-maven-plugin and the liberty-maven-plugin to package the JAR, and the 'springBoot-2.0' feature in server.xml? (Like in the guide: https://openliberty.io/guides/spring-boot.html#packaging-the-application-embedded-with-open-liberty) – Scott Kurz Mar 01 '23 at 21:29
  • @ScottKurz I have provided answers in the question under **ADDITIONAL INFO** section. Much appreciated – pixel Mar 01 '23 at 22:06
  • @ScottKurz I added more interesting detail re variable naming in server.env like `log_dir` vs `log.dir` vs `logDir` – pixel Mar 01 '23 at 23:47
  • 1
    Is using the different one like LOGDIR not an option for you? I guess that LOG_DIR is already used internally in OpenLiberty. – Mar-Z Mar 02 '23 at 15:31
  • 1
    So yes, LOG_DIR is a special environment variable used by Liberty. But it's not just an internal, it's a documented env var for controlling the location of the logs, so it seems legitimate to try to reference this value from other places, e.g. other app config. And, on Windows (as this appears to be from the path name), 'log_dir' == 'LOG_DIR'. It seems this value is used by Liberty in setting up the logging framework but not set or propogated as an actual env variable in the actual server process. Will try to find some documentation and alternative. – Scott Kurz Mar 02 '23 at 17:34
  • 1
    @pixel can you please explain how exactly you are starting the Liberty server? You said you weren't using liberty-maven-plugin. Are you using the `bin/server` shell script? Some other Maven (or Ant even??) approach? – Scott Kurz Mar 02 '23 at 18:37
  • @ScottKurz I have Liberty installed on my system (v.22.0.0.8), so what we do, we set its server.env, server.xml as we need. Then in IntelliJ (or Eclipse, but we prefer intelliJ), I go to Menu > Run Configurations > + (to add new configuration) > Select "liberty server" > select "Local" > and then I provide name, server, .... in the box. Once that is set, I can r-c on that server in IntelliJ Services tab > choose Run/Debug. If you need more details, I could provide screenshots – pixel Mar 02 '23 at 18:49
  • @Mar-Z only because I have to coordianate with other team. Which is what I did so I am going to call the variable `MYAPI_logdir` instead of `log_dir`. However, and interestingly, I think there is more issue here since if I call the variable `MYAPI_log_dir`, it still fails to resolve. It is almost like Liberty is not looking `equalTo("log_dir")` but rather `contains("log_dir")` which is very strange. Because of this, we I will call it `MYAPI_logdir` – pixel Mar 02 '23 at 18:52
  • @ScottKurz Please also see my reply to Mar-Z re `MYAPI_log_dir` issue. – pixel Mar 02 '23 at 19:17

2 Answers2

1

Workaround Liberty's unsetting of LOG_DIR by enabling server.env variable expansion

The LOG_DIR environment variable is special to Liberty. The Liberty 'server' script, after reading the value and storing it in yet another variable, unsets the environment variable as it launches the Liberty server JVM process.

In order to not repeat yourself, and specify the location in a single place, so this value can both:

  • be used as the LOG_DIR value, to configure the location of Liberty logs, AND
  • be used as a normal environment variable, e.g. referenced in Liberty server.xml config, or in this case referenced within Spring Boot application.properties

You can simply write your server env like:

server.env (Windows)

LOG_DIR=C:\mydir
liberty_log_dir=!LOG_DIR!

server.env (Unix)

# enable_variable_expansion
LOG_DIR=/c/mydir
liberty_log_dir=${LOG_DIR}

and in both cases you can reference from, e.g. SpringBoot application.properties via:

logging.file.name=${liberty_log_dir}

NOTES

  1. The Unix-style support was added to Open Liberty version 22.0.0.1
  2. I switched 'log_dir' from the original question to 'LOG_DIR', the env var Liberty is looking for. I'd recommend against the use of 'log_dir' on Windows. In most contexts this will be one and the same as 'LOG_DIR' since Windows env variables are case-insensitive, but even so can still be confusing, e.g. in Unix environments on Windows, and even just generally confusing.
Scott Kurz
  • 4,985
  • 1
  • 18
  • 40
  • Much appreciated @ScottKurz. I made change on my side as explained in my answer but I definitely think it is good to have your explanation here as well. Much appreciated. It would be good to have this clear in Liberty documentation. The "closest" to it I could find is this URL talking about LOG_DIR but it is very "shy" explanation and easy to miss as it is not clear https://openliberty.io/docs/latest/log-trace-configuration.html – pixel Mar 03 '23 at 15:56
  • 1
    Agree. I opened doc issue: https://github.com/OpenLiberty/docs/issues/6391 to follow-up on that front. Thanks for all the detail to make it easier to answer this question. – Scott Kurz Mar 03 '23 at 16:25
0

As strange as it sounds I found that if I call the variable:

  • logdir=C:/logs/myapi.log >>>> WORKS FINE
  • log.dir=C:/logs/myapi.log >>>> WORKS FINE
  • log_dir=C:/logs/myapi.log >>>> FAILS with IllegalArgumentException: Could not resolve placeholder 'log_dir' in value "${log_dir}
  • MYAPI_log_dir=C:/logs/myapi.log >>>> FAILS with IllegalArgumentException: Could not resolve placeholder 'MYAPI_log_dir' in value "${MYAPI_log_dir}

As we have discovered previously issuew with Liberty and use of "." in variable names such as log.dir, I decided to use logdir instead of log_dir or log.dir which is working as expected.

Thanks to everyone on your comments.

pixel
  • 9,653
  • 16
  • 82
  • 149
  • 1
    If you are fine using another environment variable besides 'LOG_DIR' which has a special behavior in Liberty, then yes, you could simply call it anything more or less. My answer below allows you to use LOG_DIR but also use an env var with the same value for other purposes, eg. providing a SpringBoot config value. I don't see why 'MYAPI_log_dir' should be an issue and couldn't recreate a problem with that name. – Scott Kurz Mar 03 '23 at 01:16