[JAVA] With Tomcat you can use placeholders ($ {...}) in web.xml

I've been using Tomcat for many years and (for the first time) I've learned that placeholders ($ {...}) can be used in web.xml. (I knew that it could be used in Tomcat-specific configuration files (server.xml and context.xml) ...)

Important:

** Just in case ... Placeholders are not a Servlet API specification, so don't get me wrong! !! ** **

Try using placeholders for the time being

Here, let's put the session timeout time as a placeholder and get the actual value from the system property.

web.xml


<session-config>
    <session-timeout>${session.timeout}</session-timeout>
    <!-- ... -->
</session-config>

If " -Dsession.timeout = 1 "is specified as the VM argument when starting Tomcat, the session timeout time will be 1 minute.

But ... you can't specify the default value

In the default implementation provided by Tomcat, the default value (the value to be applied when the property is undefined cannot be specified in the placeholder. (For example, in the placeholder function provided by Spring Framework, "$ {property name ". : Default value}" can be expressed) Therefore, when using the placeholder function provided by Tomcat, do not define the corresponding property in " $ CATALINA_BASE / conf / catalina.properties "or" system property ( -D property name = property value) ". It does not work as expected.

In such a case ... Customize the default implementation of Tomcat?

If you specify " -Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE = org.apache.tomcat.util.IntrospectionUtils.PropertySource interface implementation class "as the VM argument when starting Tomcat, the specified class is the default for Tomcat. It is used in preference to the implementation.

Trial ... Create a class that enables the expression "$ {property name: default value}" supported by the placeholder function provided by Spring Framework and apply it to Tomcat. I will. (** The implementation is pretty rough so don't copy it w **)

pom.xml


<!--Org for development projects.apache.tomcat.util.IntrospectionUtils.Add an artifact that contains a PropertySource-->
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-core</artifactId>
    <version>8.5.20</version>
    <scope>provided</scope>
</dependency>

IntrospectionUtils.PropertySource implementation class


package com.example.tomcat.propertysource;

import org.apache.tomcat.util.IntrospectionUtils;

public class CustomTomcatPropertySource implements IntrospectionUtils.PropertySource {
    @Override
    public String getProperty(String key) {
        String[] keyElements = key.split(":");
        if (keyElements.length == 2) {
            return System.getProperty(keyElements[0].trim(), keyElements[1].trim());
        }
        return null; //If null is returned, Tomcat's default implementation will be used
    }

}

ʻOrg.apache.tomcat.util.IntrospectionUtils.PropertySource Store the jar file containing the interface implementation class in the " $ CATALINA_BASE / lib"directory, and set the VM argument when starting Tomcat to"-Dorg.apache. Specify "tomcat.util.digester.PROPERTY_SOURCE = com.example.tomcat.propertysource.CustomTomcatPropertySource`".

web.xml


<session-config>
    <session-timeout>${session.timeout:1}</session-timeout>
    <!-- ... -->
</session-config>

This will allow you to specify default values for placeholders on Tomcat.

It's a schema violation for web.xml w

I've introduced it so far, but ... <session-timeout> is an Integer type on the XSD of web.xml, so a schema violation error will occur on the IDE, so it's quite subtle. Right.

Summary

(After all w) Basically, it seems good not to handle placeholders (environment-dependent values) on web.xml. Even if it is used (temporarily), it is not good to use it in a way that violates the schema, so I think it is better to use it only with the parameter values of the ʻinit-param` system.

Reference site

Recommended Posts

With Tomcat you can use placeholders ($ {...}) in web.xml
In Ruby you can define a method with any name
In Redmine you can get the project with Project.find (<identifier>)
Use constructor with arguments in cucumber-picocontainer
Do you use Stream in Java?
Until you can use the H2 database in server mode with Dropwizard using Eclipse and connect with DB Viewer.
When is it said that you can use try with a Swift error?
Be careful about upgrade if you use | etc. in the URL of Tomcat
Notify the build result with slack with CircleCI. You can do it in 5 minutes.
Use JDBC Manager with the settings in jdbc.dicon.
[Good news] You can still go with Java 8 !!
You use context to use MDC with Spring WebFlux
[Swift] Use nonzeroBitCount when you want popcnt in Swift
[JAVA] [Spring] [MyBatis] Use IN () with SQL Builder
You can eliminate @Param with Kotlin 1.1 and MyBatis 3.4.1+! !!
Code to use when you want to process Json with only standard library in Java
How to switch Tomcat context.xml with WTP in Eclipse
How to use Z3 library in Scala with Eclipse
You can do it with copy! Aspect-oriented programming (Android)
Play with Java function nodes that can use Java with Node-RED
If you want to use Mockito with Kotlin, use mockito-kotlin
Until you start development with Spring Boot in eclipse 1
How to use JDD library in Scala with Eclipse
Until you start development with Spring Boot in eclipse 2
Use Coveralls with GitHub Actions in a Ruby repository