On Fri, Nov 14, 2014 at 7:08 PM, Konstantin Kolinko
<knst.koli...@gmail.com> wrote:
> 2014-11-15 0:57 GMT+03:00 Matt Newell <dycs...@gmail.com>:
>> On Fri, Nov 14, 2014 at 3:28 PM, Christopher Schultz
>> <ch...@christopherschultz.net> wrote:
>>> On 11/14/14 1:14 PM, Matt Newell wrote:
>>>> Greetings,
>>>>
>>>> I have a need to get version information for classes that I have
>>>> been packaged in a war, and loaded into Tomcat 7.0.trunk on Windows
>>>> 7. For example:
>>>>
>>>>
>>>> System.out.println(this.getClass().getPackage().getImplementationVersion());
>>>>
>>>>  Assuming my.war/META-INF/MANIFEST.MF: Manifest-Version: 1.0
>>>> Implementation-Version: 1.0
>>>>
>>>> getImplementationVersion() always returns null.
>>>>
>>>> If I review the code for WebappClassLoader the reason for this is
>>>> clear. All roads lead to findResourceInternal(File, String), line
>>>> 2983 in 7.x/trunk. This method makes no attempt to load the
>>>> manifest from the war.
>>>>
>>>> My first instinct was that this is a bug. However, I did a quick
>>>> check using the same scenario using Wildfly 8 and the behavior is
>>>> the same. Given the clarity of the Tomcat code, and that two
>>>> robust, well-tested platforms behave the same, I have to assume
>>>> this is intentional.
>>>>
>>>> My question is this: why? Is META-INF/MANIFEST.MF not part of the
>>>> war standard? I've googled, but am not enough of a java standards
>>>> wonk to know what docs are authoritative on this topic. I've
>>>> certainly seen examples that use it.
>>>
>>> If Tomcat can't/won't do this, you can always load the manifest
>>> manually (context.getResource*) and grab the Implementation-Version
>>> from it.
>>
>> Chris,
>>
>> Agreed. Ultimately I am likely to leverage some approach along these
>> lines. Just thought it was odd that tomcat didn't populate the data
>> structures I expected.
>>
>> In my particular case, however, this approach is limiting. My use case
>> is to get version information from *all* loaded wars. Specifically
>> pulling resources from ServletContext or the available ClassLoader is
>> limited to resources within the current war.
>>
>> java.lang.Package.getPackages() doesn't have this limitation, it seems
>> to pull packages loaded via all ClassLoaders. But it only works if the
>> ClassLoader populated the metadata from META-INF/MANIFEST.MF when
>> loading a class.
>>
>> Otherwise, I've got to build a startup hook into each war that reads
>> its manifest, and writes version info to some global space.
>> Properties, maybe? Ugly. But, ya do what ya gotta.
>
> 1. What if the web application does not have a war file, but is
> deployed as an expanded directory?

Personally, I don't see how our expectations would change in this
scenario. As comparison, we load classes from the same relative
location whether exploded or not. However, see below.

> 2. Please find some specification references.

> 3. If there were a manifest for the WEB-INF/classes/ I would wonder
> whether it is META-INF/MANIFEST.MF or
> WEB-INF/classes/META-INF/MANIFEST.MF.  Why prefer the former rather
> than the latter?  I think that none of them is applicable.

I assume the Servlet Spec (JSR-000340) is authoritative.
Unfortunately, I find it vague. Section 10.5 speaks to the directory
structure, but makes no mention of META-INF, except in the context of
an included jar. Section 10.6 describes a packaged war, and describes
META-INF, but isn't specific to it's location. From the spec:
"When packaged into such a form, a META-INF directory will be present
which contains information useful to Java archive tools."

You could read these two sections to conclude that META-INF only
applies to a packaged war, not an expanded directory. That seems an
odd conclusion, however, since more times than not, we arrive at an
expanded directory by unzipping a war, and therefore whatever was
present in the war, would be in the directory. Either way, the spec
makes no specific reference to MANIFEST.MF or the metadata within.

I'd be glad to do more reading, but I'm not sure what other docs would apply.

> 4. Are there any precedents? Discussions?

Not sure what passes for a valid precedent around here. I had a look
at jetty, which strikes me as interesting and relevant as the simplest
implementation of the servlet spec. Its WebAppClassLoader is extremely
basic. In this case it ends up delegating to
java.net.URLClassLoader.defineClass(String, Resource). This method
also defines the Package with all null metadata fields, consistent to
the behavior of Tomcat.

Given that a core java class also has the same behavior, it
strengthens the argument that this is expected. Yet, it still strikes
me as odd. java.lang.Package is significantly less useful if it isn't
populated with metadata from MANIFEST.MF.

I don't find any discussions that are particularly compelling. There
are a few here and there:
http://stackoverflow.com/questions/11139643/what-is-use-of-manifest-mf-in-war-jar-ear
http://stackoverflow.com/questions/4239368/how-to-read-manifest-mf-inside-war-application
http://blog.frankel.ch/get-the-handle-on-the-manifest-mf-in-a-webapp

Most lead towards the solution that Chris originally proposed, rather
than a discussion of the standard.

It is interesting that maven provides a plugin for creating
META-INF/MANIFEST.MF in wars:
http://maven.apache.org/plugins/maven-war-plugin/examples/war-manifest-guide.html

Given the existence of this plugin, I would assume that other users
are creating META-INF/MANIFEST.MF for wars, but I have to assume
everyone is reading it back manually as a resource, rather than
relying on the various ClassLoaders populating the metadata to
Package. Which, truthfully, given this analysis, will end up being
more robust across platforms, if not the only option.


If anyone thinks there is useful investigation beyond what I've done,
I'm open to it. Otherwise, I'm inclined to let this die.

Thanks,
  -- m.


> Best regards,
> Konstantin Kolinko
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
> For additional commands, e-mail: users-h...@tomcat.apache.org
>

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

Reply via email to