36

I'm pre-packaging a JSP web-app that relies on some file path settings found within web.xml. These settings are unknown at packaging time, because they reference a path the customer will set when deploying the entire application (of which the web-app is a management interface).

It seems that the easiest way to avoid tokens and file modifications in my installer script, is to ask the user for an install location, set this location as an environment variable (e.g JAVA_HOME), and have web.xml always reference that variable.

Is there a way to reference an environment variable value from within web.xml? Google searches lead to the J2EE method of SETTING environment variables from ejb xml files. This is not what I'm looking for.

John Saunders
  • 157,405
  • 24
  • 229
  • 388
Udi Bar-On
  • 761
  • 1
  • 7
  • 20
  • Take a look at the first option in the accepted answer [here](http://stackoverflow.com/questions/2161054/where-to-place-configuration-properties-files-in-a-jsp-servlet-web-application). By using resource loading from external file, which only need to be available on your classpath, I think you can achieve what you want. – gamliela Jul 18 '12 at 16:28
  • I know you can at least reference HOME env variable as follows ${user.home} --> Not sure this is helpful but maybe use this in a creative way. See [SSL HOWTO](http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html) there is a – nsof Feb 08 '11 at 21:38

7 Answers7

39

You can use Ant-style variable substitution in any of the tomcat xml config files, such as:

<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>${foo}</url-pattern>
</servlet-mapping>

Where foo is a Java System Property (sysprop).

You can't use OS Environment Variables (envvars) directly, I think...

To use envvars, you can put

set "CATALINA_OPTS=-DsomeJavaSysProp=%SOME_OS_ENVVAR%"

in bin/setenv.bat (or similarly in bin/setenv.sh for *nix). You may need to create that file. Tomcat will run this file when it starts.

As CATALINA_OPTS is an envvar (as opposed to a command line option), it should not be visible by other users on the system (save ancient Unixes), though I haven't tested this.

http://tomcat.apache.org/tomcat-7.0-doc/config/

If you are using Spring, you can create a <context:property-placeholder/> bean and then directly use envvars or sysprops in Spring XML config files (though not web.xml).

Neil McGuigan
  • 41,314
  • 10
  • 106
  • 137
  • I tested with Tomcat 7, it works for me. But is it portable? Or is it specific to Tomcat? – mcoolive Dec 16 '15 at 16:51
  • Could you expand on how to use property-placeholder to use envvars in web.xml? – Adam Feb 23 '16 at 22:03
  • @Adam I don't think you can use property-placeholder in web.xml, only in spring config xml files – Neil McGuigan Feb 23 '16 at 22:20
  • I see. In that case, if I go with your first solution and create a bash script to set a java system property, is there something I need to do to make sure that spring/tomcat runs that script? – Adam Feb 23 '16 at 23:02
  • @Adam if you use tomcat's setenv batch file it will get run automatically when tomcat is started – Neil McGuigan Feb 23 '16 at 23:34
12

i think you don't want to use environment variables (which i think are not accessible from web.xml), but environment entries [1, 2]. like so:

<env-entry>
    <env-entry-name>Bla/SomeFilePath</env-entry-name>
    <env-entry-type>java.lang.String</env-entry-type>
    <env-entry-value>/opt/bla</env-entry-value>
</env-entry>

you can use SomeFilePath like:

InitialContext ic = new InitialContext();
String s = (String) ic.lookup("java:comp/env/ejb/Bla/SomeFilePath");
ax.
  • 53,672
  • 7
  • 72
  • 66
  • 1
    Problem is, the web app is generated code, which I would rather not mess with, except changing the value of a particular variable within web.xml. So I'm looking for a way to set just the value in a way that would reference a pre-set environment variable. – Udi Bar-On Sep 12 '09 at 21:03
  • as i said: i think it's not possible to use environment variables in deployment descriptors. no way around changing some code, i'm afraid. – ax. Sep 13 '09 at 13:54
9

Basically, you don't do it that way. The web.xml should contain default values for things, yes, but you should override them when actually doing the deployment. If you're deploying to Tomcat, you do this by including appropriate entries in the context.xml that you use for the deployment. For example:

<Context path="/app">
    <!-- For things described by webapp parameters -->
    <Parameter name="foobar" value="grill" />

    <!-- For things described by environment entries -->
    <Environment name="Bla/SomeFilePath" type="java.lang.String"
            value="/opt/bla" />
</Context>

Other containers will have their own mechanisms for doing this so. You'll have to look up their documentation (or make your request for help more focussed).

Donal Fellows
  • 120,022
  • 18
  • 134
  • 199
4

Environment variables can be accessed in xml files like this:

${env.ENVIRONMENT_VARIABLE_NAME}

Obviously there may be issues with user account settings and access issues, but i have tried with system variables and it works!

hakamairi
  • 4,094
  • 4
  • 24
  • 45
1

I'm not totally clear on your limitations, but just maybe you can do this (I'm assuming that it's an init-param you're trying to configure):

1) Leave the variable unspecified in web.xml
2) Create a ServletContextListener and add that to your application
3) Listen for the initialization of your servlet
4) Set the init-param for the servlet at that point

I tried this with a similar problem, but it failed for me because it turned out that the 3rd party servlet (which I also didn't want to mess with) wasn't actually behaving as a servlet at all, so the context never got initialized. But maybe it has a chance here...

Toby Eggitt
  • 1,686
  • 15
  • 20
1

You have to put the env-entry in order :

<env-entry>
  <env-entry-name>maxAmount</env-entry-name>
  <env-entry-type>java.lang.String</env-entry-type>
  <env-entry-value>aString</env-entry-value>
</env-entry>

Else you will have validation error on web.xml

ref: https://community.oracle.com/thread/840452?tstart=0

Sayeed S. Alam
  • 417
  • 2
  • 6
0

If you're using Spring - you could pipe FilterConfig through ConfigurableBeanFactory.resolveEmbeddedValue to enable property placeholders interpolation support in web.xml.

Proxy class for make FilterConfig parameters resolvable.

public class ResolvableFilterConfig implements FilterConfig {

    private final FilterConfig source;
    private final ConfigurableBeanFactory resolver;

    public ResolvableFilterConfig(FilterConfig source, ConfigurableBeanFactory resolver) {
        this.source = source;
        this.resolver = resolver;
    }

    @Override
    public String getFilterName() {
        return source.getFilterName();
    }

    @Override
    public ServletContext getServletContext() {
        return source.getServletContext();
    }

    @Override
    public String getInitParameter(String name) {
        final String value = source.getInitParameter(name);
        return resolver.resolveEmbeddedValue(value);
    }

    @Override
    public Enumeration<String> getInitParameterNames() {
        return source.getInitParameterNames();
    }
}

Filter implementation sample code

    @Override
    public void init(FilterConfig config) throws ServletException {
        // configure
        final ServletContext servletContext = config.getServletContext();
        final AbstractApplicationContext aac = (AbstractApplicationContext) getRequiredWebApplicationContext(servletContext);
        final ConfigurableBeanFactory beanFactory = aac.getBeanFactory();
        config = new ResolvableFilterConfig(config, beanFactory);
        // ... do the rest
    }