dev@glassfish.java.net

Re: Maven-built deployment plans confuse DeploymentPlanArchive and break asadmin deploy --deploymentplan.

From: Hong Zhang <hong.hz.zhang_at_oracle.com>
Date: Thu, 02 Sep 2010 22:46:24 -0400

Hi, Owen
> I explored a couple of alternatives for addressing this, without reaching a satisfying solution. Attached are two patches to deployment/common (against the 3.0.1-b22 tag).
>
> deployment-plan-archive-ignores-meta-inf.patch is probably the better of the two alternatives: the patch causes DeploymentPlanArchive.entries() to skip the deployment plan JAR's META-INF dir entirely, which prevents any files there from being copied to the deployed application. This is a very simple solution, and it appears to work well with the simple cases, but I'd worry about people relying on deployment plans to place important runtime configuration in their application (SPI services/ entries, extra Spring XML files, config files, &c) having their use cases broken.
>
> deployment-plan-archive-includes-meta-inf.patch takes the opposite approach: it avoids path-mangling any entries that are already in META-INF, and tries to return entries without de-mangling them first. This has its own worrying side effects: in the case of signed JARs, the deployment plan's signing data will be copied into the app, potentially overwriting any signing data that went with the original application; similarly, with Maven metadata, both my application's own Maven metadata and the deployment plan's Maven metadata end up in the application.
>
Thanks for working on this and providing the patches! I also like the
first patch better, it's very simple and addressed the problem. As the
deployment plan is only intended to provide vendor specific deployment
descriptors and not other runtime configuration files, I think it's fine
to ignore the META-INF directory here.

If you agree, I will apply your first patch and check in after running
the necessary tests.
> While I was fiddling with this, I may have uncovered another bug... Is account.war.sun-web.xml in the deployment plan supposed to be copied into account_war/WEB-INF/sun-web.xml ?
Yes.
> Because it's not, and as far as I can tell my container adjustments are not being applied to any of my nested web applications inside my EAR - only to the EAR itself.
>
I just tried this from my side, and the sun-web.xml seems getting copied
as expected. I can look into it if you send me your test case...

Thanks,

- Hong
> ------------------------------------------------------------------------
>
>
> On 2010-09-02, at 10:01 AM, Hong Zhang wrote:
>
>
>> Hi, Owen
>> Thanks for sharing your experience with us on this (with detailed information on how to reproduce, and how to workaround etc)!
>> Yes, this code need to be more robust in dealing with unexpected files from META-INF. I have filed issue
>> https://glassfish.dev.java.net/issues/show_bug.cgi?id=13235
>> to track the problem. We will get it fixed!
>> Thanks,
>>
>> - Hong Owen Jacobson wrote:
>>
>>> (I mistakenly sent this to dev_at_glassfish.org <mailto:dev_at_glassfish.org> first -- apologies if this comes through twice.)
>>>
>>> Hi there,
>>>
>>> I just solved something that's been blocking me for a couple of days, and I thought you guys might appreciate knowing about it. First, a reproduction case:
>>>
>>> 1. Build a deployment plan archive (per http://docs.sun.com/app/docs/doc/820-7693/gijyb?l=en&a=view <http://docs.sun.com/app/docs/doc/820-7693/gijyb?l=en&a=view>) with Maven. The following POM will do:
>>>
>>> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>>> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
>>> <modelVersion>4.0.0</modelVersion>
>>>
>>> <groupId>com.example.glassfish</groupId>
>>> <artifactId>deployment-plan</artifactId>
>>> <version>1.0-SNAPSHOT</version>
>>> </project>
>>>
>>> 2. Note the contents of the deployment plan. In my case:
>>>
>>> $ jar tf test-environment-1.0-SNAPSHOT.jar META-INF/
>>> META-INF/MANIFEST.MF
>>> account.war.sun-web.xml
>>> root.war.sun-web.xml
>>> sun-application.xml
>>> META-INF/maven/
>>> META-INF/maven/ca.grimoire/
>>> META-INF/maven/ca.grimoire/test-environment/
>>> META-INF/maven/ca.grimoire/test-environment/pom.xml
>>> META-INF/maven/ca.grimoire/test-environment/pom.properties
>>>
>>> 3. Try to deploy an application with this deployment plan.
>>>
>>> Under Glassfish 3.0.1, the deploy command fails with
>>>
>>> $ bin/asadmin deploy \
>>> --deploymentplan test-environment-1.0-SNAPSHOT.jar \
>>> ~/Development/grimoire/grimoire/target/grimoire-1.0-SNAPSHOT.ear
>>> com.sun.enterprise.admin.cli.CommandException: remote failure: Exception while deploying the app : java.lang.NullPointerException
>>>
>>> and in the logs, the following stack trace:
>>>
>>> [#|2010-08-30T19:58:30.661-0400|SEVERE|glassfish3.0.1|javax.enterprise.system.core.com.sun.enterprise.v3.server|_ThreadID=21;_ThreadName=Thread-1;|Exception while deploying the app
>>> java.lang.NullPointerException
>>> at com.sun.enterprise.util.shared.ArchivistUtils.copyWithoutClose(ArchivistUtils.java:58)
>>> at com.sun.enterprise.deployment.archivist.Archivist.copyJarElements(Archivist.java:1469)
>>> at com.sun.enterprise.deployment.archivist.Archivist.copyInto(Archivist.java:1670)
>>>
>>> I've reproduced the Archivist.copyJarElements here, with annotations:
>>>
>>> protected void copyJarElements(ReadableArchive in, WritableArchive out, Vector ignoreList)
>>> throws IOException {
>>>
>>> /* entries is generated *by in* -oj */
>>> Enumeration entries = in.entries();
>>> /* ... */
>>> if (entries != null) {
>>> for (; entries.hasMoreElements();) {
>>> String anEntry = (String) entries.nextElement();
>>> if (ignoreList == null || !ignoreList.contains(anEntry)) {
>>> InputStream is = in.getEntry(anEntry);
>>> OutputStream os = out.putNextEntry(anEntry);
>>> /* Oops! 'is' is null here, so copyWithoutClose NPEs out. -oj */
>>> ArchivistUtils.copyWithoutClose(is, os);
>>> is.close();
>>> out.closeEntry();
>>> }
>>> }
>>> }
>>> }
>>>
>>> Digging around a bit lead me to com.sun.enterprise.deployment.deploy.shared.DeploymentPlanArchive, the ReadableArchive implementation that handles deployment plans. The entries() and getEntry() methods contain some medium-hairy code designed to munge paths like foo.jar.sun-ejb.xml, and designed specifically to ignore META-INF/MANIFEST.MF. However, Maven's extra archive metadata confuses it in such a way that entries() includes Entry objects for pom.xml and pom.properties, but getEntry() will return null for those entries.
>>>
>>> I think this is a bug, but I don't know what the right fix is. It's easy to work around, though: telling maven not to include Maven descriptors in the resulting JAR is simple:
>>>
>>> <plugin>
>>> <artifactId>maven-jar-plugin</artifactId>
>>>
>>> <configuration>
>>> <archive>
>>> <addMavenDescriptor>false</addMavenDescriptor>
>>> </archive>
>>> </configuration>
>>> </plugin>
>>>
>>> and, absent those two files (and their containing directories), asadmin deploy is quite happy.
>>>
>>> Maybe getEntries() should ignore unexpected files in META-INF? I suspect something like this will happen if you sign your deployment plan, too.
>>>
>>> -o
>>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe_at_glassfish.dev.java.net
>> For additional commands, e-mail: dev-help_at_glassfish.dev.java.net
>>
>>
>
>
>
> ------------------------------------------------------------------------
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_glassfish.dev.java.net
> For additional commands, e-mail: dev-help_at_glassfish.dev.java.net