0

I'm currently working on a project that is attempting to integrate use both shade and felix. The goal is to create a shaded jar that contains only the code we need, then use felix to create the manifest we need. The build part of my pom is as follows:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>1.3</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <shadedArtifactAttached>false</shadedArtifactAttached>
                        <artifactSet>
                            <includes>
                                <include>${project.groupId}:*</include>
                            </includes>
                        </artifactSet>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>

        <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <executions>
                <execution>
                    <id>bundle-manifest</id>
                    <phase>package</phase>
                    <goals>
                        <goal>manifest</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <manifestLocation>${project.build.directory}</manifestLocation>
                <niceManifest>true</niceManifest>
            </configuration>
        </plugin>

    </plugins>
</build>

Now the issue I'm running in to is something I've seen elsewhere, but all of those threads seem to die right at this point. So the shaded jar is correctly created, then Felix runs afterwards and puts the MANIFEST.MF file (which is correct as far as I can tell) in target/classes/META-INF/ but it doesn't put that same manifest in the shaded jar. The one inside the jar is the same manifest that existed before Felix ran.

It almost seems like I need Shade to run, then Felix, then re-run the jar creation. Am I missing something?

I'm trying to figure out how to, for lack of a better term, re-package the JAR with the new manifest.

Neal
  • 127
  • 1
  • 2
  • 9
  • Why do you need to create the manifest in that way? I only ask because I've used the Shade plugin before and managed to use the resulting application(s) just fine. – HomerPlata Feb 28 '17 at 15:59
  • This post runs into the same issue and goes unanswered. http://apache-felix.18485.x6.nabble.com/Using-maven-felix-plugin-with-maven-shade-plugin-td4997927.html – Neal Feb 28 '17 at 16:00
  • 1
    Not entirely sure, I'm flying by the seat of my pants here. We have an RCP app that needs this shaded jar, because the original jars rely on a custom OSGi configuration that the RCP app doesn't have access to. Something about the way it uses the other jars caused it to blow up. I'll generate the jar with the empty manifest and see how the RCP app behaves. Worth a shot. – Neal Feb 28 '17 at 16:03
  • Let me know if that works out :-) – HomerPlata Feb 28 '17 at 16:06
  • So because there's nothing in the manifest, the RCP app doesn't even attempt to add the shaded jar to the project (event when it's in the pom) so we get a noClassDefFound error once we hit code that needs something in the jar. – Neal Feb 28 '17 at 19:16
  • Ah, I see. When I used Shade, it was for a single standalone project, not something to be included as a dependency further down the line. I guess the Shade plugin might be pruning things it doesn't know you actually need, if the scope is limited to the project itself when really it's being used in a wider context. Can you apply Shade at the very end of your build process? – HomerPlata Mar 01 '17 at 07:13
  • 1
    Not really. The shaded jar has to be created first in order for felix to run on it. So the answer below ended up sorta-working, turns out you can create the jar, generate the manifest, and have the jar pull the manifest from a set location. It wasn't pretty but it got me further than before. The issue has been resolved (looks like we just didn't end up using shade and went another route) but this has been really informative. Thanks for all the info. – Neal Mar 07 '17 at 15:20

1 Answers1

1

Your main problem is that the manifest must be generated in the jar file, you can generate your Manifest file from the shade plugin (adapt with your needs):

 <configuration>
        <transformers>
            <!-- This bit sets the main class for the executable jar as you otherwise -->
            <!-- would with the assembly plugin -->
            <transformer
                implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                <manifestEntries>
                    <Import-Package>org.apache.common</Import-Package>
                    <Export-Package>org.test</Export-Package>
                    <Main-Class>com.br.iacit.tutorialdoJar.ImageLab</Main-Class>
                    <Specification-Title>Java Advanced Imaging Image I/O Tools</Specification-Title>
                    <Specification-Version>1.1</Specification-Version>
                    <Specification-Vendor>Sun Microsystems, Inc.</Specification-Vendor>
                    <Implementation-Title>com.sun.media.imageio</Implementation-Title>
                    <Implementation-Version>1.1</Implementation-Version>
                    <Implementation-Vendor>Sun Microsystems, Inc.</Implementation-Vendor>
                </manifestEntries>
            </transformer>
            <!-- This bit merges the various GeoTools META-INF/services files -->
            <transformer
                implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
        </transformers>
    </configuration>

Output Manifest:

Manifest-Version: 1.0
Toto: test
Export-Package: org.test
Archiver-Version: Plexus Archiver
Built-By: NG673AB
X-Compile-Target-JDK: 1.7
Import-Package: org.apache.common
X-Compile-Source-JDK: 1.7
Created-By: Apache Maven 3.3.3
Build-Jdk: 1.8.0_66
Main-Class: tt.tt.main

Edit: I managed to make it so that it compiles correctly, see below:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>1.3</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer">
                                <resource>META-INF/MANIFEST.MF</resource>
                            </transformer>
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
                                <resource>META-INF/MANIFEST.MF</resource>
                                <file>src/main/resources/MANIFEST.MF</file>
                            </transformer>
                        </transformers>
                        <shadedArtifactAttached>false</shadedArtifactAttached>
                        <artifactSet>
                            <includes>
                                <include>${project.groupId}:*</include>
                            </includes>
                        </artifactSet>

                    </configuration>
                </execution>
            </executions>
        </plugin>

        <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <executions>
                <execution>
                    <id>bundle-manifest</id>
                    <phase>package</phase>
                    <goals>
                        <goal>manifest</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <manifestLocation>src/main/resources/</manifestLocation>
                <niceManifest>true</niceManifest>
                <instructions>
                    <Export-Package>test</Export-Package>
                </instructions>
            </configuration>
        </plugin>

    </plugins>
</build>
Adonis
  • 4,670
  • 3
  • 37
  • 57
  • One of the things that seems to be missing from this is the export-package and import-package tags, and those values seem to be generated automatically by felix. Is there a way to do this with maven-shade? I've been wary of going too far down the rabbit hole of trying to do it all manually within shade. – Neal Feb 28 '17 at 16:09
  • Yes I edited the pom.xml. Actually you can put anything as XML tags Inside and it will be added to your MANIFEST.mf – Adonis Feb 28 '17 at 16:18
  • Worst case I'll see if I can give that a shot. Unfortunately There are about 60 things in the include, so that may be a last case resort. – Neal Feb 28 '17 at 16:23
  • Actually you could have Felix run at phase post compile so shade execute on it at package phase. Edited my post. – Adonis Feb 28 '17 at 16:26
  • So shade executes first, and it has to otherwise felix complains that the jar doesn't exist yet. So shade creates the jar and then felix executes, but the manifest that's created doesn't get put into the already generated shaded jar. I can't figure out if it's supposed to or if it even can. – Neal Feb 28 '17 at 16:38
  • Giving it a shot, will report back. – Neal Feb 28 '17 at 19:18
  • Ok, so I haven't given it to the person working on the RCP app yet, but the manifest in the jar is correct (YAY!!). There's also a -sources jar that wasn't there before and a second manifest inside the jar in the parent directory (so one in the parent, one in META-INF). Definitely a step in the right direction though, mind explaining why there's a -sources and a second manifest? – Neal Feb 28 '17 at 19:31
  • According to the doc: https://maven.apache.org/plugins/maven-shade-plugin/shade-mojo.html. Do you have a createSourceJar tag somewhere else possibly (otherwise set it explicitly to false)? The second manifest comes from the fact that my MANIFEST.MF is in src/main/resources and Maven copies it by default to the root of the jar – Adonis Feb 28 '17 at 19:52
  • Hmm. Added the and set it to false but it's still being created. Somehow this change has caused the maven-source-plugin to be added on an install. Interesting. – Neal Feb 28 '17 at 20:03
  • But the manifest is being created and is in the jar, so I'm marking this fixed. Think it's just tweaking it from here on out. Thanks for your help. – Neal Feb 28 '17 at 20:26
  • Very strange because I don't get any sources jar on my file... Good luck! – Adonis Feb 28 '17 at 20:29