-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Nick,

On 3/13/13 2:19 PM, Nicholas Williams wrote:
> On Wed, Mar 13, 2013 at 12:10 PM, Christopher Schultz 
> <ch...@christopherschultz.net> wrote:
>> You mean addWebapp methods? They seem fairly self-explanatory.
> 
> Yes. I meant addWebapp methods. That was a typo.
> 
> There are three of them. Only one is documented. Unfortunately,
> the other two are not "self explanatory." I have no idea what the
> "url," "path," and "name" parameters are (although "host" makes
> sense). The documentation for the lone method that IS documented
> only has "contextPath" and "baseDir" ... that doesn't line up with
> the other two methods.

Yup, it's ugly.

>> Tomcat.addWebapp(String,String) says that the first argument is
>> the context path. The context path for the ROOT webapp is "", not
>> "/".
> 
> I didn't know this. I will change it. By the way, I got this code
> from the tutorial at 
> https://devcenter.heroku.com/articles/create-a-java-web-application-using-embedded-tomcat.

They
> 
should probably update their HOWTO: "/" isn't a valid context
path, though it might actually work since "//" ~= "/" in the URL world.

>> The second argument is a "baseDir" which says (via 
>> Context.setDocBase) it can be an absolute pathname, a relative 
>> pathname (to the cwd I suppose, or maybe relative to the hosts's 
>> appbase), or a URL.
> 
> Well there's part of the problem with the documentation. The 
> documentation for the method says "Add a webapp using normal 
> WEB-INF/web.xml if found." and the documentation for the "baseDir" 
> parameter says nothing. There's no information here that would
> have led me to look at the Context#setDocBase() method. Nada. I
> will try out making it a URL.

I was reading the code, not the Javadoc: it makes it a lot easier.
Since the "baseDir" gets passed into Context.setDocBase, I read the
javadoc for that method to get the real story.

>> You are passing a relative path name which probably won't
>> resolve to a resource "inside" the JAR file you are using. Try
>> fetching a resource URL for the "web/" path from the ClassLoader
>> and pass that instead of just "web/".
> 
> I will give this a try.
> 
>> You didn't say what actually happens: just stated your
>> requirements and showed your code. Does Tomcat fail to start?
>> Does it fail to listen on your port? Does it fail to respond to
>> requests?
> 
> My bad. I'm always seeing y'all tell people to explain the
> problem, and here I go not explaining the problem just like all the
> rest of them. :-P ... When I ran the application using the batch
> file generated by the mojo plugin, almost everything was good
> (Tomcat started up, started listening on the right port, found all
> the classes it was supposed to find, etc.). However, I got a
> "severe" error that the web application directory
> (webAppDirLocation) did not exist and the application could not be
> deployed. Understandable, since I didn't know what to use for
> this.

The likely problem is that your appBase was just "web" and Tomcat was
trying to load that from the disk (directly) instead of looking inside
your JAR file. Using a JAR-URL (which the ClassLoader should give you)
should work. The URL should look something like /path/to/your.jar!/web
or something like that.

>>> tomcat.start();
>> 
>> You should probably call tomcat.init() first, though some of the 
>> Tomcat test cases don't do it so you're probably okay.
> 
> Yea, the tutorial I was using didn't say anything about that. 
> Interesting that "init" and "start" are separate. If "init" was 
> required and "start" didn't call "init" I would think that "start" 
> would throw an IllegalStateException. Since it doesn't, my guess
> is that calling "start" is sufficient, though I will certainly add 
> "init." I would love to now the semantic difference between "init"
> and "start." The documentation just says "Initialize the server"
> and "Start the server."

Take a look at the Javadoc for LifecycleListener, one of the
interfaces that the Tomcat class implements. The Javadoc for any
implemented yet not documented method from that interface gets
inherited in the javadoc for the implementation class, but the
interface-level documentation is, of course, ignored. Go look at the
javadoc for that interface and you'll see some nice ASCII art that
describes the full lifecycle.

>>> tomcat.getServer().await(); } }
>> 
>> I don't think you configured any logging. You might want to set
>> up something to at least dump to the console, and crank-up the
>> log level to DEBUG or something like that. Then you might be able
>> to see what Tomcat is actually doing.
> 
> It does seem to automatically dump to the console automatically. I
> got plenty of messages, most of them good (listening on 8973,
> etc.). I will look into logging more, of course. This was just a
> first pass at proof-of-concept.

Cool. Obviously, you're going to want to log to a log file eventually.
If you configure commons-logging at the top-level (that is, your own
code), I think everything will flow through that.

> Since sending this email, I've discovered the "Executable WAR" [2] 
> capability of the Tomcat Maven plugin. I'm kind of confused about
> the difference between Embedded Tomcat and Executable WAR. Which
> one do I need? Will they both do what I need, but one might be
> better than the other based on more exact requirements?

I dunno anything about the Tomcat Maven plugin, but I think that an
executable WAR file is exactly what you are trying to build.

> This may be premature (getting it working is my priority), but I 
> should mention that performance is important to what I'm doing
> here. I'd like to enable the native code. Some applications and
> libraries include native DLLs/SOs/JNILIBs in their JAR files, copy
> them to a temporary directory at runtime and load them from the
> temporary location (to avoid having to actually "install" the
> native libraries in the OS or JVM directory structure). Is there a
> way to do this with an embedded/executable Tomcat application so
> that the Tomcat classes can take advantage of the native library?

I'm almost sure Java won't load a shared library out of a JAR file, so
you'll have to use this same technique: extract some shared libraries
out of your JAR file and throw them into java.io.tmpdir/pid/shared/*
or whatever and then instruct the JVM to load them from there (or
modify the java.library.path system property to point to that and let
them load naturally).

Just be aware that if you want an executable JAR/WAR that will run
anywhere, you'll have to bundle all possible combinations of
architecture, OS, etc. in order to rely on APR (and it will be a
mess). If you provide a statically-linked tcnative (includes APR and
OpenSSL), you may be able to survive this process, but if you want to
support shared libraries, you're in for a world of hurt.

Also, if APR doesn't load for some reason, you'll have to configure
your SSL Connectors completely differently (using trustStore instead
of SSLCertificateKeyFile, etc.), which could be a real pain.

As for performance itself, you may not actually need APR: if you need
SSL, then APR is probably the way to go. If you don't need SSL, stick
to the NIO connector which provides comparable performance (from the
testing I've done). I dunno if APR provides a faster PRNG than
whatever the JVM provides, but I believe the AprLifecycleListener
configures Tomcat to use the OpenSSL PRNG which may have some
advantages -- I don't actually know.

If it were me, I'd forget about tcnative entirely.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
Comment: GPGTools - http://gpgtools.org
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iEYEAREIAAYFAlFDczcACgkQ9CaO5/Lv0PDJjgCfY86CMJ5gQTyM11IKu68X6J9v
J0YAn1eLVP/MjEE57Z4E15XoeAlqimP9
=3Xk5
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to