users@glassfish.java.net

Re: GF 3.1.1 yet another classloading issue - JEE6 EAR packaging and MANIFEST.FM

From: Tim Quinn <tim.quinn_at_oracle.com>
Date: Tue, 29 Nov 2011 14:34:54 -0600

On Nov 29, 2011, at 2:11 PM, Bernhard Thalmayr wrote:

>
>
> On Tue, Nov 29, 2011 at 6:49 PM, Tim Quinn <tim.quinn_at_oracle.com>
> wrote:
> Ah, this is such fun!
>
> If you look at the JavaDoc for URLClassLoader, you find this little
> morsel:
>
> "This class loader is used to load classes and resources from a
> search path of URLs referring to both JAR files and directories. Any
> URL that ends with a '/' is assumed to refer to a directory.
> Otherwise, the URL is assumed to refer to a JAR file which will be
> opened as needed. "
>
> Just about every useful class loader you'll come across extends
> URLClassLoader, either directly or indirectly, so while the trailing
> slash is NOT required by the manifest or JAR spec, it IS required by
> the URLClassLoader contract.
>
> Well ..... does this mandate that a directory mentioned in the
> 'Class-Path' header of MANIFEST.MF has a trailing slash?
>
> If the URLClassLoader needs this it could also be the responsibility
> of the container to add that slash .. isn't it?

It is risky for the code to try to read the mind of the person who
prepared the manifest, especially if that introduces differences in
how an app server behaves with the same inputs compared to Java SE.

Although it is true that a container could conceivably assume that the
user intended any Class-Path entries that do not end in .jar to be
directories, that would (1) contradict how Java SE treats such Class-
Path entries, and (2) require the container to guess what the user
intended.

But let's go back to the 3rd party library which contains the slash-
less directory entries in the Class-Path. Is there a runtime
environment in which this library and its Class-Path entries are
handled so that the slash-less directory IS added to the class path as
a directory?

- Tim


> -Bernhard
>
>
>
> - Tim
>
>
> On Nov 29, 2011, at 10:23 AM, Bernhard Thalmayr wrote:
>
>>
>>
>> On Tue, Nov 29, 2011 at 5:08 PM, Cheng Fang <cheng.fang_at_oracle.com>
>> wrote:
>> If you write a java app with the same structure, you will also get
>> the same behavior. So not a Java EE or GlassFish bug.
>>
>> Yes, both jar files and directories can be members of Class-Path.
>> This part is governed by Java Jar Specification.
>>
>> If I read
>>
>> http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html
>>
>> I don't see where it's sepcified that 'directories' need to thave a
>> trailing slash .... is this a litle inaccuracy?
>>
>> IIRC I can do 'new File("dir").mkdir()' ....
>>
>> -Bernhard
>>
>> -cheng
>>
>>
>> On 11/29/11 10:35 AM, Bernhard Thalmayr wrote:
>>>
>>> Thanks for the pointer Cheng.
>>>
>>> I removed the 'lib' prefixes (actually I know about lib-
>>> directory .. but this is a 3rd party app and I don't want to
>>> change to much at the beginnin) and put 'classes/' into 'Class-
>>> Path' header.
>>>
>>> BTW should I consider it as a bug that I the directory must have a
>>> trainling '/'?
>>>
>>> Unfortuantely I can not deploy the app anymore to an instance
>>> directly (using --target <instance>).
>>>
>>> Deploying for target 'domain' works, but when I try to create the
>>> application-reference I always get the following error .... I
>>> don't see any reason how this could be related to the change
>>>
>>> [#|2011-11-29T16:25:11.814+0100|SEVERE|glassfish3.1.1|
>>> com.sun.grizzly.config.GrizzlyServiceListener|
>>> _ThreadID=157;_ThreadName=Thread-2;|GRIZZLY0039: Request URI is
>>> too large.
>>> java.nio.BufferOverflowException
>>> at
>>> com
>>> .sun
>>> .grizzly
>>> .tcp.http11.InternalInputBuffer.fill(InternalInputBuffer.java:765)
>>> at
>>> com
>>> .sun
>>> .grizzly
>>> .tcp
>>> .http11
>>> .InternalInputBuffer.parseRequestLine(InternalInputBuffer.java:467)
>>> at
>>> com.sun.grizzly.http.ProcessorTask.parseRequest(ProcessorTask.java:
>>> 861)
>>> at
>>> com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:692)
>>> at
>>> com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019)
>>> at
>>> com
>>> .sun
>>> .grizzly
>>> .http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
>>> at
>>> com
>>> .sun
>>> .grizzly
>>> .DefaultProtocolChain
>>> .executeProtocolFilter(DefaultProtocolChain.java:137)
>>> at
>>> com
>>> .sun
>>> .grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
>>> at
>>> com
>>> .sun
>>> .grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
>>> at
>>> com
>>> .sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:
>>> 79)
>>> at
>>> com
>>> .sun
>>> .grizzly
>>> .ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
>>> at
>>> com
>>> .sun
>>> .grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:
>>> 59)
>>> at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
>>> at com.sun.grizzly.util.AbstractThreadPool
>>> $Worker.doWork(AbstractThreadPool.java:532)
>>> at com.sun.grizzly.util.AbstractThreadPool
>>> $Worker.run(AbstractThreadPool.java:513)
>>> at java.lang.Thread.run(Thread.java:722)
>>> |#]
>>>
>>> [#|2011-11-29T16:25:11.817+0100|SEVERE|glassfish3.1.1|
>>> com.sun.grizzly.config.GrizzlyServiceListener|
>>> _ThreadID=157;_ThreadName=Thread-2;|GRIZZLY0051: ProcessorTask
>>> exception.
>>> java.lang.NullPointerException
>>> at java.nio.CharBuffer.put(CharBuffer.java:915)
>>> at com.sun.enterprise.web.accesslog.DefaultAccessLogFormatterImpl.appendRequestInfo
>>> (DefaultAccessLogFormatterImpl.java:494)
>>> at com.sun.enterprise.web.accesslog.DefaultAccessLogFormatterImpl.appendLogEntry
>>> (DefaultAccessLogFormatterImpl.java:264)
>>> at
>>> com
>>> .sun
>>> .enterprise.web.PEAccessLogValve.postInvoke(PEAccessLogValve.java:
>>> 592)
>>> at com.sun.enterprise.web.VirtualServer
>>> $2.onParsingError(VirtualServer.java:1698)
>>> at
>>> com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:709)
>>> at
>>> com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019)
>>> at
>>> com
>>> .sun
>>> .grizzly
>>> .http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
>>> at
>>> com
>>> .sun
>>> .grizzly
>>> .DefaultProtocolChain
>>> .executeProtocolFilter(DefaultProtocolChain.java:137)
>>> at
>>> com
>>> .sun
>>> .grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
>>> at
>>> com
>>> .sun
>>> .grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
>>> at
>>> com
>>> .sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:
>>> 79)
>>> at
>>> com
>>> .sun
>>> .grizzly
>>> .ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
>>> at
>>> com
>>> .sun
>>> .grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:
>>> 59)
>>> at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
>>> at com.sun.grizzly.util.AbstractThreadPool
>>> $Worker.doWork(AbstractThreadPool.java:532)
>>> at com.sun.grizzly.util.AbstractThreadPool
>>> $Worker.run(AbstractThreadPool.java:513)
>>> at java.lang.Thread.run(Thread.java:722)
>>> |#]
>>>
>>> Thanks and regards,
>>> Bernhard
>>>
>>> On Tue, Nov 29, 2011 at 1:51 PM, Cheng Fang
>>> <cheng.fang_at_oracle.com> wrote:
>>> Hi Bernhard,
>>>
>>> Change Class-Path: lib/lib1.jar lib/lib2.jar classes to Class-
>>> Path: lib/lib1.jar lib/lib2.jar classes/
>>>
>>> Another point is, in Java EE 6, EAR/lib/ is the default EAR
>>> library-directory and all jars in that directory are automatically
>>> made available to your application. Having them also in Class-
>>> Path results in duplicates but that should affect functioning.
>>>
>>> -cheng
>>>
>>>
>>> On 11/29/11 5:13 AM, Bernhard Thalmayr wrote:
>>>>
>>>> Hi experts,
>>>>
>>>> classloading and 'portable JEE application' seems to be very
>>>> challenging in GF 3.1.1
>>>>
>>>> I have a (3rd party) enterprise app with layout
>>>>
>>>> META-INF/application.xml
>>>> ejb1.jar
>>>> |_ META-INF/MANIFEST.FM (Class-Path: lib/lib1.jar lib/lib2.jar
>>>> classes)
>>>>
>>>> ejb2.jar
>>>> |_META-INF/MANIFEST.FM (Class-Path: lib/lib1.jar lib/lib3.jar
>>>> classes)
>>>>
>>>> lib/lib1.jar
>>>> lib/lib2.jar
>>>> lib/lib3.jar
>>>> classes/<package-structure>
>>>>
>>>> A 'NoClassDefFoundError' is raised
>>>>
>>>> java.lang.NoClassDefFoundError: <class-from-classes-directory>
>>>> at java.lang.ClassLoader.defineClass1(Native Method)
>>>> at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
>>>> at
>>>> com
>>>> .sun.enterprise.loader.ASURLClassLoader.findClass(ASURLClassLoader
>>>> .java:756)
>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:410)
>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:410)
>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
>>>> at java.lang.Class.forName0(Native Method)
>>>> at java.lang.Class.forName(Class.java:186)
>>>> at <method-of-class-from-ejb1.jar>
>>>>
>>>>
>>>> As far as I interpret chapter 'EE.8' of JEE 6 specification I
>>>> packaged the appliation correctly.
>>>>
>>>> Could it be that GF 3.1.1 does not honour directories mentioned
>>>> in MANIFEST.FM ?
>>>>
>>>> Section 8.2.1 states ...
>>>>
>>>> "The Java EE deployment tools must process all such referenced
>>>> files and directories when processing a Java EE module."
>>>>
>>>> Thanks for any pointers.
>>>>
>>>> -Bernhard
>>>> --
>>>> IT-Consulting Bernhard Thalmayr
>>>> - Painstaking Minds -
>>>> 83620 Vagen (Munich area)
>>>> Germany
>>>
>>>
>>>
>>> --
>>> IT-Consulting Bernhard Thalmayr
>>> - Painstaking Minds -
>>> 83620 Vagen (Munich area)
>>> Germany
>>
>>
>>
>> --
>> IT-Consulting Bernhard Thalmayr
>> - Painstaking Minds -
>> 83620 Vagen (Munich area)
>> Germany
>
>
>
>
> --
> IT-Consulting Bernhard Thalmayr
> - Painstaking Minds -
> 83620 Vagen (Munich area)
> Germany