How to install shaded fat/uber JAR with dependency-reduced POM

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

How to install shaded fat/uber JAR with dependency-reduced POM

Alexander Kriegisch-2
Situation (sorry for maybe explaining too much):

  -- I have a multi-module project with an aggregator POM which is also
     the parent for all dependent modules.
  -- The modules implement different byte code transformation features.
  -- In some modules I use Maven Shade in order build fat JARs which can
     be used as Java agents.
  -- Those Java agents add themselves to the bootstrap class path during
     start-up, utilising the "Boot-Class-Path" manifest entry. For that
     purpose, it is imperative that the Java agents are fat JARs because
     their dependencies also need to be on the bootstrap class path,
     because the byte code transformations can also target other
     bootstrap classes. This works very well, I have no issues with
     that.
  -- Besides, I also build compound source JARs for the shaded JARs,
     which also works nicely.
  -- For each JAR I also build a variant with third-party classes
     relocated to my own package name space, in case the user happens to
     use the same dependencies and has problems due to API changes which
     cannot be reconciled by dependency version management. Also here, I
     build compound source files with relocated source packages. This
     also works nicely.

Problems description:

I want users to be able to depend on the shaded agent JARs without
pulling other dependencies into their projects because the agent JARs
already contain all classes necessary to run them.

But if I declare the dependencies as optional in the module using Maven
Shade, dependent modules in my own project (e.g. integration test
modules) no longer compile in IntelliJ IDEA. This is not a Maven
problem, but still something I need to avoid for the sake of being able
to use my IDE.

As an alternative, I can urge the user to use something like this:

  <dependency>
    <groupId>xxx</groupId>
    <artifactId>yyy</artifactId>
    <excludes>
      <excludes>
        <groupId>*</groupId>
        <artifactId>*</artifactId>
      </exclude>
    </exclude>
  </dependency>

This is not nice and I do not wish to burden my users with that.

What I am currently doing is to use something like this in each module
building shaded JARs:

  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>flatten-maven-plugin</artifactId>
    <version>1.2.2</version>
    <executions>
      <!-- Remove shaded dependencies from uber JAR -->
      <execution>
        <id>flatten</id>
        <phase>process-resources</phase>
        <goals>
          <goal>flatten</goal>
        </goals>
        <configuration>
          <flattenMode>oss</flattenMode>
          <pomElements>
            <dependencies>remove</dependencies>
          </pomElements>
          <outputDirectory>${project.build.directory}</outputDirectory>
          <flattenedPomFilename>flattened-pom.xml</flattenedPomFilename>
        </configuration>
      </execution>
    </executions>
  </plugin>

This has the effect of creating a POM similar to the dependency-reduced
POM created by Maven Shade and installing it together with the uber JAR
artifact. Now the dependency graph looks "clean" to users of my
libraries. I know it is not the Maven way of managin dependencies, but
uber JARs with shaded dependencies exist in the real world and I
explained at the beginning how/why they are useful in my case.

BTW, IntelliJ IDEA still adds all dependencies to the classpath and
excludes the uber JAR, trying to be smarter than Maven itself but
getting it wrong. But that is not your problem, I can deal with that and
provide the path to the uber JAR in another way to my integration tests.
The most important thing is that Maven and IDEA do not see the
dependencies when using the uber JARs from other project outside of my
own multi-module project.

Questions:

  1. Is there any more canonical way of doing what I did, i.e. directly
     using the dependency-reduced POM generated by Maven Shade in order
     to replace the original JAR when installing my artifact? Then I
     could get rid of the Flatten plugin (which also removes other stuff
     and even empty lines from my POMs, making them look horrible) and
     just use Shade.

  2. Can I achieve a similar result in a better way altogether?

  3. Does anyone even happen to know a way to make this work within my
     multi-module project in connection with building and running tests
     with IntelliJ IDEA? BTW, I also experimented with attaching the
     shaded JARs to the original artifact with special classifiers. This
     again works with Maven, but not in IDEA.

Sorry for the lengthy post, thanks for bearing with me. I really wonder
if I am the only one having this kind of problem because I found nothing
useful on StackOverflow or doing a global web search. Maybe I did not
use the right search terms.

--
Alexander Kriegisch
https://scrum-master.de

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: How to install shaded fat/uber JAR with dependency-reduced POM

Alexander Kriegisch-2
Sorry, I hope it is not against this group's etiquette to ping on a
question after several days of waiting for a reaction. Otherwise please
tell me and I will apologise and promise not to do it again.

--
Alexander Kriegisch
https://scrum-master.de


Alexander Kriegisch schrieb am 01.07.2020 13:07 (GMT +07:00):

> Situation (sorry for maybe explaining too much):
>
>   -- I have a multi-module project with an aggregator POM which is
>      also the parent for all dependent modules.
>   -- The modules implement different byte code transformation
>      features.
>   -- In some modules I use Maven Shade in order build fat JARs which
>      can be used as Java agents.
>   -- Those Java agents add themselves to the bootstrap class path
>      during start-up, utilising the "Boot-Class-Path" manifest entry.
>      For that purpose, it is imperative that the Java agents are fat
>      JARs because their dependencies also need to be on the bootstrap
>      class path, because the byte code transformations can also target
>      other bootstrap classes. This works very well, I have no issues
>      with that.
>   -- Besides, I also build compound source JARs for the shaded JARs,
>      which also works nicely.
>   -- For each JAR I also build a variant with third-party classes
>      relocated to my own package name space, in case the user happens
>      to use the same dependencies and has problems due to API changes
>      which cannot be reconciled by dependency version management. Also
>      here, I build compound source files with relocated source
>      packages. This also works nicely.
>
> Problem description:
>
> I want users to be able to depend on the shaded agent JARs without
> pulling other dependencies into their projects because the agent JARs
> already contain all classes necessary to run them.
>
> But if I declare the dependencies as optional in the module using
> Maven Shade, dependent modules in my own project (e.g. integration
> test modules) no longer compile in IntelliJ IDEA. This is not a Maven
> problem, but still something I need to avoid for the sake of being
> able to use my IDE.
>
> As an alternative, I can urge the user to use something like this:
>
>   <dependency>
>     <groupId>xxx</groupId>
>     <artifactId>yyy</artifactId>
>     <excludes>
>       <excludes>
>         <groupId>*</groupId>
>         <artifactId>*</artifactId>
>       </exclude>
>     </exclude>
>   </dependency>
>
> This is not nice and I do not wish to burden my users with that.
>
> What I am currently doing is to use something like this in each module
> building shaded JARs:
>
>   <plugin>
>     <groupId>org.codehaus.mojo</groupId>
>     <artifactId>flatten-maven-plugin</artifactId>
>     <version>1.2.2</version>
>     <executions>
>       <!-- Remove shaded dependencies from uber JAR -->
>       <execution>
>         <id>flatten</id>
>         <phase>process-resources</phase>
>         <goals>
>           <goal>flatten</goal>
>         </goals>
>         <configuration>
>           <flattenMode>oss</flattenMode>
>           <pomElements>
>             <dependencies>remove</dependencies>
>           </pomElements>
>           <outputDirectory>${project.build.directory}</outputDirectory>
>           <flattenedPomFilename>flattened-pom.xml</flattenedPomFilename>
>         </configuration>
>       </execution>
>     </executions>
>   </plugin>
>
> This has the effect of creating a POM similar to the
> dependency-reduced POM created by Maven Shade and installing it
> together with the uber JAR artifact. Now the dependency graph looks
> "clean" to users of my libraries. I know it is not the Maven way of
> managin dependencies, but uber JARs with shaded dependencies exist in
> the real world and I explained at the beginning how/why they are
> useful in my case.
>
> BTW, IntelliJ IDEA still adds all dependencies to the classpath and
> excludes the uber JAR, trying to be smarter than Maven itself but
> getting it wrong. But that is not your problem, I can deal with that
> and provide the path to the uber JAR in another way to my integration
> tests. The most important thing is that Maven and IDEA do not see the
> dependencies when using the uber JARs from other project outside of my
> own multi-module project.
>
> Questions:
>
>   1. Is there any more canonical way of doing what I did, i.e.
>      directly using the dependency-reduced POM generated by Maven
>      Shade in order to replace the original JAR when installing my
>      artifact? Then I could get rid of the Flatten plugin (which also
>      removes other stuff and even empty lines from my POMs, making
>      them look horrible) and just use Shade.
>
>   2. Can I achieve a similar result in a better way altogether?
>
>   3. Does anyone even happen to know a way to make this work within my
>      multi-module project in connection with building and running
>      tests with IntelliJ IDEA? BTW, I also experimented with attaching
>      the shaded JARs to the original artifact with special
>      classifiers. This again works with Maven, but not in IDEA.
>
> Sorry for the lengthy post, thanks for bearing with me. I really
> wonder if I am the only one having this kind of problem because I
> found nothing useful on StackOverflow or doing a global web search.
> Maybe I did not use the right search terms.

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]