This is my approach so far to run multiple hot-deployable instances of
a shared Persevere application (each with its own datasource) inside
Jetty. This is still not optimal for what I'm after but perhaps this
might help someone.
I used Persevere v1.0 beta 6 and Jetty v6.1.14 and modified jetty as
follows:
- comment out the webapp deployer in etc\jetty.xml (I only wanted hot-
deployable contexts, leave this in if you want standard webapps).
- copy and add the files from persevere\lib to jetty\lib
- copy and add the files from persevere\WEB-INF\lib to jetty\lib
EXCEPT persevere.jar, js.jar, and jline-0.9.94.jar
- for each app to be deployed to the jetty\contexts directory:
- create the application directory (we'll call the instance foo for
this example):
jetty
+ contexts
+ foo
+ static resource directories (css, images, js, etc.)
+ WEB-INF
+ config
+ data
+ jslib
+ lib
js.jar (from persevere\WEB-INF\lib)
persevere.jar (from persevere\WEB-INF\lib)
web.xml (from persevere\WEB-INF)
- create the deployment file contexts\foo.xml:
<?xml version='1.0' encoding='ISO-8859-1'?>
<!DOCTYPE Configure PUBLIC '-//Mort Bay Consulting//DTD Configure//
EN' '
http://jetty.mortbay.org/configure.dtd'>
<Configure class='org.mortbay.jetty.webapp.WebAppContext'>
<Set name='contextPath'>/</Set>
<Set name='resourceBase'><SystemProperty name='jetty.home'
default='.'/>/contexts/foo</Set>
<Set name='extractWAR'>false</Set>
<Set name='copyWebDir'>false</Set>
<Set name='descriptor'><SystemProperty name='jetty.home'
default='.'/>/contexts/foo/WEB-INF/web.xml</Set>
<Set name='defaultsDescriptor'><SystemProperty name='jetty.home'
default='.'/>/etc/webdefault.xml</Set>
<Set name='tempDirectory'><SystemProperty name='jetty.home'
default='.'/>/contexts/foo/WEB-INF/data</Set>
<Set name='virtualHosts'>
<Array type='String'>
<Item>
foo.mydomain.com</Item>
</Array>
</Set>
</Configure>
Start jetty: java -Xmx128m -jar start.jar
Notes:
- I intentionally left out jline-0.9.94.jar because you can't have
multiple command lines for each app in the same shell. If you leave
it in, you'll get a js> prompt, but I don't know how to assign it to a
particular webapp. Leaving it out results in harmless warnings. Use
ctrl-c to exit Jetty if running from a command line.
- The deployment file in this case uses a virtual host subdomain to
map contexts. I tried doing this using context paths (<Set
name='contextPath'>/foo/</Set>) but I was getting odd behavior with
Dojo on the client. This could probably work with a little more time
and care than what I was willing to spend. Using the virtual hosts in
this manner also allows me to specify a *.
mydomain.com that presents a
login form that always returns an authentication failure. I wanted
this so that a group of users could not detect the presence or absence
of another group by guessing subdomains.
- The tempDirectory setting was the only way I found to trick Jetty/
Persevere into using the correct location for the data\jsdb location.
As a result, Jetty uses this as the working directory and will also
create an empty jsp directory. It can be ignored. I think it would
be really useful to be able to specify this as a context-param inside
the instance web.xml file similar to the way one specifies the
database path from a single instance command line.
- I really wanted a way of having a single copy of the webapp where
each group of users would have their own database based on the
subdomain but everything else was the same. Since I am developing on
Windows, I used the junction utility (
http://technet.microsoft.com/en-
us/sysinternals/bb896768.aspx) to create symbolic links to the common
files. This is built into Linux from what I understand. This
requires some care when adding directories so I created a batch file
to create the new context directories, setup the junctions and create
the deployment xml files based on a command line param.
- I tested this with 30 instances of Persevere running. After two or
three instances, I had to supply the -Xmx128m to avoid heap memory
errors. Each test context had its own unique Persevere native
datastore weighing in at 6.6MB for the index.psv + transactions.psv
files. I did not do any load testing, but I did find that each
additional context added an additional ~3MB of memory usage to the
java process...fairly reasonable IMO. The problems start at about 30
instances where I started getting "OutOfMemoryError: PermGen space"
errors. Increasing the -Xmx parameter has no effect on this error,
and Jetty does not accept the -XX:MaxPermSize=???m parameter for some
reason.
I am not crazy about this approach for a shared application because it
consumes system resources unnecessarily. Ideally, a single instance
of Persevere would be able to attach to any datasource on the fly
based on the request object and then continue on with the normal
Persevere processing magic. I may open a new thread on that topic.
However, I think this approach works well for cases where multiple
Persevere apps with distinct code bases need to be deployed on the
same server (probably the case for everyone else except me).