Skip to content
This repository has been archived by the owner on Jan 3, 2021. It is now read-only.

Distribute Pubby as a pre-packaged .war #11

Open
cygri opened this issue Feb 25, 2013 · 0 comments
Open

Distribute Pubby as a pre-packaged .war #11

cygri opened this issue Feb 25, 2013 · 0 comments

Comments

@cygri
Copy link
Owner

cygri commented Feb 25, 2013

Currently, Pubby is distributed as a “disassembled” web application directory. To install and run it, one has to copy that directory into the webapps directory of a pre-installed servlet container. To configure Pubby, one has to change files inside the web application. In particular, one has to set the location of the configuration file in /WEB-INF/web.xml (or modify the configuration file in the default location, /WEB-INF/config.ttl). This is bad because one cannot upgrade Pubby by simply replacing the Pubby directory, as this would overwrite the configuration changes. One needs to apply the configuration change in the new version, either by manually editing web.xml again, or by copy-pasting the file around.

It would be better if we could simply ship a pubby.war archive that one drops into the servlet container, where the configuration is made somewhere outside of the web application.

Unfortunately there is no particularly good way of doing this. This issue here captures the result of some research into different ways of achieving this goal.

Hardcoded configuration file location

One option would be to hardcode the location of the configuration file. It could be an absolute path (/etc/pubby-config.ttl), a path relative to the user home (~/.pubby-config.ttl), or a path relative to the current directory (./conf/pubby-config.ttl).

A number of problems with this approach:

  • Conventions for this kind of file differ between operating systems
  • Doesn't easily facilitate multiple instances of Pubby with different configurations (e.g., for multiple virtual hosts)
  • Whichever approach is chosen, it's likely to work poorly in some scenarios

This seems bad.

System-wide configuration

So if the location of the configuration file cannot be hardcoded, then it needs to be passed into the web application. This could be done through a system-wide setting. Options include:

  • Setting a system variable on servlet container startup, and reading it in the webapp
  • Adding a directory to the classpath, and putting a pubby.properties file there (or directly pubby-config.ttl) and reading it from within the webapp

Again there are a number of problems:

  • Doesn't easily facilitate multiple instances of Pubby with different configurations (e.g., for multiple virtual hosts)
  • Procedures differ between servlet containers
  • The classpath option involves fun with system classpath vs. app classpath on Tomcat, which is usually not fun
  • This is the right way of configuring a servlet container, but not really a webapp

Per-webapp configuration

So the right way of doing this should be based on per-webapp settings, because this allows running multiple instances of Pubby with different configurations. So this will involve making some settings in the servlet container configuration that are passed to the individual webapp. There seem to be two options here: JNDI and overriding context-param.

JNDI

This is a J2EE thing that seems rather complicated. It supports “environment parameters” that are simple strings that can be set in various ways, and then read from an application. But its real purpose is to provide factories for things to enable looser coupling of apps. So we'd be using a very complex system to achieve a rather simple task. Also, JNDI support is optional for servlet containers. Tomcat seems to have it out of the box, but Jetty requires extra jars and extra configuration. Altogether, this approach seems to be dragging in a whole lot of unpleasant complexities.

Setting context-param from outside of the webapp

Webapp configuration can be done using the context-param element inside the web.xml. Servlet containers generally provide a way of setting or overriding context parameters from outside of the web application. Architecturally, this seems to be the right approach. Downsides:

  • It works differently for each servlet container
  • It generally means that one doesn't deploy by simply dropping a war file into webapps, but by messing with XML files that sit in different locations; this it's likely to be unfamiliar to many users
  • It seems to be overly complicated in Jetty, requiring two small XML files

Nevertheless, this may be the way to go. So let's assume we want to set the config-file parameter that Pubby already uses to find the config file from outside of the web application, so that we can ship the web application as a simple pubby.war.

Setting context-params on Tomcat

Put a pubby.xml in $CATALINA_BASE/conf/[engine_name]/[host_name] (e.g., conf/Catalina/localhost). It should look somewhat like this (not actually tested):

<Context docBase="/Path/to/pubby.war">
  <Parameter name="config-file" value="/Path/to/config.ttl" override="false"/>
</Context>

Setting @override to false prevents the value from web.xml (if any) from overriding the value provided here. If the @docBase is omitted, then webapps/pubby.war in the Tomcat directory is assumed.

More information:

Setting context-params in Jetty

Put a pubby.xml into Jetty's /contexts directory. It should look something like this (not tested; the paths don't make sense in this example):

<Configure class="org.mortbay.jetty.webapp.WebAppContext">
  <Set name="contextPath">/pubby</set>
  <Set name="war"><systemproperty name="jetty.home" default="."/>/webapps/pubby.war</set>
  <Set name="overrideDescriptor"><SystemProperty name="jetty.home" default="."/>/my/path/to/override-web.xml</Set>
</Configure>

The override-web.xml looks like a normal web.xml, but is applied after the one in the web application, and can thus override stuff:

<web-app>
  <context-param>
    <param-name>config-file</param-name>
    <param-value>/Path/to/config.ttl</param-value>
  </context-param>
</web-app>

One deployment option here would be to have pubby.war and override-web.xml both located in some user directory outside of the servlet container. The general downside here is that one has to provide redundant absolute paths everywhere—twice in the context XML and once in the override-web.xml.

More information:

Setting context-params in the Jetty Maven plugin

This would use the same approach as for Jetty above, but instead of the context XML file, one only needs to point to the override-web.xml in the plugin configuration:

<project>
    ...
    <plugins>
        <plugin>
            ...
            <artifactId>jetty-maven-plugin</artifactId>
            <configuration>
                <webAppConfig>
                  ...
                  <overrideDescriptor>src/main/resources/override-web.xml</overrideDescriptor>
                </webAppConfig>
            </configuration>
        </plugin>
        ...
    </plugins>
    ...
</project>

Since the build should be location-independent, the actual location of the config file cannot be specified as an absolute path, which means that probably the config file has to be put onto the classpath.

More information:

Setting context-param for a command-line app with embedded Jetty

In case we want to also provide a command-line app that starts up an embedded Jetty to run Pubby. That should be straightforward. Use WebAppContext.setInitParams() to set the context param, or WebAppContext.setOverrideDescriptors() with a temporary file.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant