You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Nick Williams <ni...@nicholaswilliams.net> on 2013/03/13 04:47:42 UTC

Embedded Tomcat JavaDoc Not Complete

The JavaDoc for o.a.c.startup.Tomcat [1] is not complete. Importantly, it is lacking complete information about all three addWebapp classes. Ultimately, I want to create one giant JAR file with my classes, Tomcat classes, servlet classes, etc., with a com.mycompany.Bootstrap specified as the Main class in MANIFEST.MF. Here's (roughly) what I expect it to look like (though, if it should be different to make something work correctly, please correct me):

- MyEmbeddedWebApp.jar
    - com
        - mycompany
            - ...
    - javax
        - ...
    - META-INF
        - MANIFEST.MF
    - org
        - apache
            - ...
    - web
        - index.html
        - WEB-INF
            - web.xml

How do I correctly start up Tomcat so that my (lone) web app (MyEmbeddedWebApp.jar!/web/WEB-INF/web.xml) is correctly deployed to the root context (/) with index.html and etc. resources available?

[1] http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/startup/Tomcat.html
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Embedded Tomcat JavaDoc Not Complete

Posted by Nick Williams <ni...@nicholaswilliams.net>.
On Mar 15, 2013, at 3:15 PM, Christopher Schultz wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA256
> 
> Nick,
> 
> On 3/15/13 3:56 PM, Nick Williams wrote:
>> I tried using a JAR URL. (If I remember correctly, it ended up 
>> looking something like 
>> jar:url://C:/Users/Nicholas/Desktop/Project/target/Test.jar!/Test.war.
> 
> That
>> 
> doesn't look right.

That's what Class#getResource() returned.

> 
>> I tried it as both a directory and a WAR file. Tomcat did not like
>> it. It said "Could not deploy web application to [temporary webapps
>> directory location]" or something like that. I ended up, at
>> runtime, extracting the war file from the JAR file to a temporary
>> directory and deploying from there. That worked great, and it's how
>> the Tomcat Maven plugin executable war works, too.
> 
> Don't build your own URL. Instead, do this in your driver that calls
> Tomcat:
> 
> String docBase = getClass().getResource("/web);
> String ROOT = "";
> tomcat.addWebapp(ROOT, docBase);

I was using Class#getResource() just like this. However, Class#getResource() does not return a String. It returns a java.net.URL. I can't just pass that to addWebapp(), I had to toString() it. Just to be accurate, I ran it again and dumped the URL again (I was doing this before for debugging, but I had removed it). It's "jar:file:/C:/Users/Nicholas/Desktop/PeripheralProxy/TomcatRunner/target/Peripher
alProxy-1.0.0.SNAPSHOT.jar!/PeripheralProxy.war". So my memory was close, but not exact.

> 
> It's probably worth dumping-out the URL just to see what it looks
> like. Note that your CLASSPATH can affect what getResource() will
> return, so make sure you don't have too much classpath pollution.
> 
>>> I dunno anything about the Tomcat Maven plugin, but I think that
>>> an executable WAR file is exactly what you are trying to build.
>> 
>> It is. There are some issues (not bugs) with the Tomcat Maven
>> plugin executable war, the first one being that it's not very easy
>> to customize without using command-line arguments (makes it kind of
>> hard to "double-click" and run the executable war effectively).
>> Also, while there are snapshots for the Tomcat 8.0 embedded
>> artifacts, there is no Tomcat 8.0 version of the Tomcat Maven
>> plugin yet, so I literally can't use it. I ended up using a few
>> maven modules and the embedded Tomcat artifacts to create my own
>> executable WAR. Working great now.
> 
> Cool.
> 
>>>> 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).
>> 
>> Yea. I got that working. Embedded the DLLs in the JAR file and
>> then extracted at runtime. Learned a lot about how Tomcat loads the
>> native library and filed and created a patch for improvement
>> request #54700 as a result.
> 
> That bug report offers a silly suggestion: use a system property to
> configure where tcnative can be found because setting system
> properties at startup is inconvenient? I suppose that system property
> would be writable at runtime and so marginally more useful.

That was exactly the point. For my purposes, I have to sniff out the architecture at runtime (really not as hard as you suggest below, only took me about 10 minutes to write) and THEN determine which library to use. System#setProperty() makes it easy to then tell Tomcat where the library is. But you can't change the java.library.path at runtime with setProperty() (you can, it has just already been cached, so you have to use reflection on a JVM class to clear the cache, which isn't pretty). Even specifying this property on the command line at JVM startup is STILL easier than changing the java.library.path property at startup, because java.library.path isn't always constructed the same way across platforms, and changing it has some inherent risk.

> What about
> a setting where the native library wasn't loaded *at all* so an
> embedded driver can load it however it wants?

I'm not sure what you're suggesting here.

> 
>> This is a prototype for now, but if we use it for real we'll 
>> probably compile and include statically-linked Linux .so and Mac
>> .jnilib files as well, and let the other platforms just run without
>> APR.
> 
> This won't work without a whole lot of work like sniffing the
> architecture at runtime and then extracting only the right libraries
> (or just giving them all different names).

Like I said above, it was easy. Had it working in a few minutes. Several libraries and applications use a similar approach for loading the right native library for the running platform. First one that comes to mind is NRJavaSerial [1], a fork of RXTX, a fork of Java Communications API.

> 
>>> 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.
>> 
>> Not using SSL, so not concerned here.
>> 
>>> 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.
>> 
>> Interesting. My reading on the Tomcat site seemed to indicate APR 
>> was better in ALL cases, not just OpenSSL. I will keep this in
>> mind.
> 
> Nope: from my testing, NIO was a better bet given the additional setup
> and configuration required by APR. Plus there's a bit of overhead
> managing the same resources twice (once on the Java side, once on the
> native side) when using APR. Also a bug in APR can bring-down the
> whole JVM instead of maybe just throwing an exception for a single
> request.
> 
> Basically, if you aren't using SSL, you can abandon tcnative.

That is indeed useful information. I had no idea. I will keep that under advisement. I still think my improvement suggestion is an improvement, though. :-)

[1] http://code.google.com/p/nrjavaserial/


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


Re: Embedded Tomcat JavaDoc Not Complete

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Nick,

On 3/15/13 3:56 PM, Nick Williams wrote:
> I tried using a JAR URL. (If I remember correctly, it ended up 
> looking something like 
> jar:url://C:/Users/Nicholas/Desktop/Project/target/Test.jar!/Test.war.

That
> 
doesn't look right.

> I tried it as both a directory and a WAR file. Tomcat did not like
> it. It said "Could not deploy web application to [temporary webapps
>  directory location]" or something like that. I ended up, at
> runtime, extracting the war file from the JAR file to a temporary
> directory and deploying from there. That worked great, and it's how
> the Tomcat Maven plugin executable war works, too.

Don't build your own URL. Instead, do this in your driver that calls
Tomcat:

String docBase = getClass().getResource("/web);
String ROOT = "";
tomcat.addWebapp(ROOT, docBase);

It's probably worth dumping-out the URL just to see what it looks
like. Note that your CLASSPATH can affect what getResource() will
return, so make sure you don't have too much classpath pollution.

>> I dunno anything about the Tomcat Maven plugin, but I think that
>> an executable WAR file is exactly what you are trying to build.
> 
> It is. There are some issues (not bugs) with the Tomcat Maven
> plugin executable war, the first one being that it's not very easy
> to customize without using command-line arguments (makes it kind of
> hard to "double-click" and run the executable war effectively).
> Also, while there are snapshots for the Tomcat 8.0 embedded
> artifacts, there is no Tomcat 8.0 version of the Tomcat Maven
> plugin yet, so I literally can't use it. I ended up using a few
> maven modules and the embedded Tomcat artifacts to create my own
> executable WAR. Working great now.

Cool.

>>> 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).
> 
> Yea. I got that working. Embedded the DLLs in the JAR file and
> then extracted at runtime. Learned a lot about how Tomcat loads the
> native library and filed and created a patch for improvement
> request #54700 as a result.

That bug report offers a silly suggestion: use a system property to
configure where tcnative can be found because setting system
properties at startup is inconvenient? I suppose that system property
would be writable at runtime and so marginally more useful. What about
a setting where the native library wasn't loaded *at all* so an
embedded driver can load it however it wants?

> This is a prototype for now, but if we use it for real we'll 
> probably compile and include statically-linked Linux .so and Mac
> .jnilib files as well, and let the other platforms just run without
> APR.

This won't work without a whole lot of work like sniffing the
architecture at runtime and then extracting only the right libraries
(or just giving them all different names).

>> 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.
> 
> Not using SSL, so not concerned here.
> 
>> 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.
> 
> Interesting. My reading on the Tomcat site seemed to indicate APR 
> was better in ALL cases, not just OpenSSL. I will keep this in
> mind.

Nope: from my testing, NIO was a better bet given the additional setup
and configuration required by APR. Plus there's a bit of overhead
managing the same resources twice (once on the Java side, once on the
native side) when using APR. Also a bug in APR can bring-down the
whole JVM instead of maybe just throwing an exception for a single
request.

Basically, if you aren't using SSL, you can abandon tcnative.

- -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/

iEYEAREIAAYFAlFDgUcACgkQ9CaO5/Lv0PD3sgCgnEEo8iBKOUZu4nFLbPoIEhTl
5W4AoLlKo0Gi9kFzvfcaU/OAnIWo6IA+
=IjbF
-----END PGP SIGNATURE-----

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


Re: Embedded Tomcat JavaDoc Not Complete

Posted by Nick Williams <ni...@nicholaswilliams.net>.
On Mar 15, 2013, at 2:15 PM, Christopher Schultz wrote:

> -----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.

Yep.

> 
>>> 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.

That's how I ended up getting it running: I starting reading code instead of documentation.

> 
>>> 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.

I tried using a JAR URL. (If I remember correctly, it ended up looking something like jar:url://C:/Users/Nicholas/Desktop/Project/target/Test.jar!/Test.war.) I tried it as both a directory and a WAR file. Tomcat did not like it. It said "Could not deploy web application to [temporary webapps directory location]" or something like that. I ended up, at runtime, extracting the war file from the JAR file to a temporary directory and deploying from there. That worked great, and it's how the Tomcat Maven plugin executable war works, too.

> 
>>>> 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.

Yep. Found that. Last time I saw ASCII art was the late 1990s or something. ;-)

> 
>>>> 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.

Yep. I used the standard logging.properties that ships with Tomcat and got Tomcat logging to a temporary directory I set up. Works great now.

> 
>> 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.

It is. There are some issues (not bugs) with the Tomcat Maven plugin executable war, the first one being that it's not very easy to customize without using command-line arguments (makes it kind of hard to "double-click" and run the executable war effectively). Also, while there are snapshots for the Tomcat 8.0 embedded artifacts, there is no Tomcat 8.0 version of the Tomcat Maven plugin yet, so I literally can't use it. I ended up using a few maven modules and the embedded Tomcat artifacts to create my own executable WAR. Working great now.

> 
>> 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).

Yea. I got that working. Embedded the DLLs in the JAR file and then extracted at runtime. Learned a lot about how Tomcat loads the native library and filed and created a patch for improvement request #54700 as a result. This is a prototype for now, but if we use it for real we'll probably compile and include statically-linked Linux .so and Mac .jnilib files as well, and let the other platforms just run without APR.

> 
> 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.

Understood.

> 
> 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.

Not using SSL, so not concerned here.

> 
> 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.

Interesting. My reading on the Tomcat site seemed to indicate APR was better in ALL cases, not just OpenSSL. I will keep this in mind.

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

Thanks. Consider me advised.
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Embedded Tomcat JavaDoc Not Complete

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Embedded Tomcat JavaDoc Not Complete

Posted by Nicholas Williams <ni...@nicholaswilliams.net>.
On Wed, Mar 13, 2013 at 12:10 PM, Christopher Schultz
<ch...@christopherschultz.net> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA256
>
> Nick,
>
> On 3/12/13 11:50 PM, Nick Williams wrote:
>>
>> On Mar 12, 2013, at 10:47 PM, Nick Williams wrote:
>>
>>> The JavaDoc for o.a.c.startup.Tomcat [1] is not complete.
>>> Importantly, it is lacking complete information about all three
>>> addWebapp classes.
>
> 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.

>
>>> Ultimately, I want to create one giant JAR file with my classes,
>>> Tomcat classes, servlet classes, etc., with a
>>> com.mycompany.Bootstrap specified as the Main class in
>>> MANIFEST.MF.
>
> I think is called OSGi, right? I think this has been done before...

I don't know. Unfortunately, OSGi is kind of a new thing to me.

>
>>> Here's (roughly) what I expect it to look like (though, if it
>>> should be different to make something work correctly, please
>>> correct me):
>>>
>>> - MyEmbeddedWebApp.jar - com - mycompany - ... - javax - ... -
>>> META-INF - MANIFEST.MF - org - apache - ... - web - index.html -
>>> WEB-INF - web.xml
>>>
>>> How do I correctly start up Tomcat so that my (lone) web app
>>> (MyEmbeddedWebApp.jar!/web/WEB-INF/web.xml) is correctly deployed
>>> to the root context (/) with index.html and etc. resources
>>> available?
>>>
>>> [1]
>>> http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/startup/Tomcat.html
>>
>>>
>> By the way, com.mycompany.Bootstrap currently looks like the code
>> below. It's the webAppDirLocation variable and addWebapp method
>> call that I'm struggling with.
>>
>> public class Bootstrap { public static void main(String...
>> arguments) throws Exception { String webAppDirLocation = "web/";
>> Tomcat tomcat = new Tomcat(); tomcat.setPort(8973);
>> tomcat.addWebapp("/", new
>> File(webAppDirLocation).getAbsolutePath());
>
> 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.

> 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.

> 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.

>
>> 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."

>
>> 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.

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?

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?

[2] http://tomcat.apache.org/maven-plugin-2.1/executable-war-jar.html

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


Re: Embedded Tomcat JavaDoc Not Complete

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Nick,

On 3/12/13 11:50 PM, Nick Williams wrote:
> 
> On Mar 12, 2013, at 10:47 PM, Nick Williams wrote:
> 
>> The JavaDoc for o.a.c.startup.Tomcat [1] is not complete. 
>> Importantly, it is lacking complete information about all three 
>> addWebapp classes.

You mean addWebapp methods? They seem fairly self-explanatory.

>> Ultimately, I want to create one giant JAR file with my classes,
>> Tomcat classes, servlet classes, etc., with a 
>> com.mycompany.Bootstrap specified as the Main class in
>> MANIFEST.MF.

I think is called OSGi, right? I think this has been done before...

>> Here's (roughly) what I expect it to look like (though, if it
>> should be different to make something work correctly, please
>> correct me):
>> 
>> - MyEmbeddedWebApp.jar - com - mycompany - ... - javax - ... -
>> META-INF - MANIFEST.MF - org - apache - ... - web - index.html -
>> WEB-INF - web.xml
>> 
>> How do I correctly start up Tomcat so that my (lone) web app 
>> (MyEmbeddedWebApp.jar!/web/WEB-INF/web.xml) is correctly deployed
>> to the root context (/) with index.html and etc. resources
>> available?
>> 
>> [1]
>> http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/startup/Tomcat.html
>
>> 
> By the way, com.mycompany.Bootstrap currently looks like the code 
> below. It's the webAppDirLocation variable and addWebapp method
> call that I'm struggling with.
> 
> public class Bootstrap { public static void main(String...
> arguments) throws Exception { String webAppDirLocation = "web/"; 
> Tomcat tomcat = new Tomcat(); tomcat.setPort(8973); 
> tomcat.addWebapp("/", new
> File(webAppDirLocation).getAbsolutePath());

Tomcat.addWebapp(String,String) says that the first argument is the
context path. The context path for the ROOT webapp is "", not "/". 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. 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/".

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?

> 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.

> 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.

- -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/

iEYEAREIAAYFAlFAsxUACgkQ9CaO5/Lv0PBWTgCgol+RqJweJQ9VOiyAVcpJsxDg
UoUAoI0AlgMh8IcJ2zm2lwDmzEDbovku
=Prjq
-----END PGP SIGNATURE-----

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


Re: Embedded Tomcat JavaDoc Not Complete

Posted by Nick Williams <ni...@nicholaswilliams.net>.
On Mar 12, 2013, at 10:47 PM, Nick Williams wrote:

> The JavaDoc for o.a.c.startup.Tomcat [1] is not complete. Importantly, it is lacking complete information about all three addWebapp classes. Ultimately, I want to create one giant JAR file with my classes, Tomcat classes, servlet classes, etc., with a com.mycompany.Bootstrap specified as the Main class in MANIFEST.MF. Here's (roughly) what I expect it to look like (though, if it should be different to make something work correctly, please correct me):
> 
> - MyEmbeddedWebApp.jar
>    - com
>        - mycompany
>            - ...
>    - javax
>        - ...
>    - META-INF
>        - MANIFEST.MF
>    - org
>        - apache
>            - ...
>    - web
>        - index.html
>        - WEB-INF
>            - web.xml
> 
> How do I correctly start up Tomcat so that my (lone) web app (MyEmbeddedWebApp.jar!/web/WEB-INF/web.xml) is correctly deployed to the root context (/) with index.html and etc. resources available?
> 
> [1] http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/startup/Tomcat.html

By the way, com.mycompany.Bootstrap currently looks like the code below. It's the webAppDirLocation variable and addWebapp method call that I'm struggling with.

public class Bootstrap
{
    public static void main(String... arguments) throws Exception
    {
        String webAppDirLocation = "web/";
        Tomcat tomcat = new Tomcat();
        tomcat.setPort(8973);
        tomcat.addWebapp("/", new File(webAppDirLocation).getAbsolutePath());

        tomcat.start();
        tomcat.getServer().await();
    }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org