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-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to