Create a jar with only one main class and only its dependecies - java

I have a Java that contains many main classes. I want to create a Jar with only one main class and only its dependencies. I want only the code of the main class and dependencies to be included in the jar. I use Maven to make my jar.

The maven way is to have maybe one parent project, and for every application one module project. Every single application project has one Main-Class specified in the META-IBF/MANIFEST.MF, and separate minimal dependencies. Probably need to have one or more library project for internal dependencies.
/all
/lib-a
pom.xml --> lib-a-0.1-SNAPSHOT.jar
/lib-b
pom.xml --> lib-b-0.1-SNAPSHOT.jar
/app-m
pom.xml --> app-m-0.1-SNAPSHOT.jar
/app-n
pom.xml --> app-n-0.1-SNAPSHOT.jar
...
pom.xml --> all-src-0.1-SNAPSHOT.zip
--> all-0.1-SNAPSHOT.jar
The applications generate a manifest with a Main-Class: ... entry.
The dependencies are defined per application.
You might have the idea of having just one project, and a smart maven plugin that handles local dependencies, but why.
You could keep all sources in one project, say generating as artifact a zip with sources.
And every application project could take a specific list of sources from the zip. Hard.
If you indeed want something very customized, I think going back to ant + ivy would be more effective.

Related

How to find java classes that needs a dependency in maven pom.xml file

I have a Maven based project, and I use IntelliJ. The pom.xml file probably contains dependencies that I don't need. How can I find which Java files (in particular the import statements) that need a specific dependency in the pom.xml file? Alternatively, how can I find which dependencies I don't need in the pom.xml?
I have tried to comment out a dependency from pom.xml, build the project and look what breaks. In at least one case, I saw no compile time problems, but there was a runtime problem. This method is also more effort than I want.
I have also tried to find information in the IntelliJ Project explorer, section "External Libraries". But the items listed there are not always present in the pom.xml file. Each versioned item there expands to a tree with a jar file on top, and I can ask IntelliJ about the usage of the contained items. I have found the usage of some packages contained in jar files, but the number of packages to investigate simply becomes too large.
Here is a dependency that I want to know if I need or not:
<!-- https://mvnrepository.com/artifact/com.googlecode.soundlibs/mp3spi -->
<dependency>
<groupId>com.googlecode.soundlibs</groupId>
<artifactId>mp3spi</artifactId>
<version>1.9.5.4</version>
</dependency>
This particular dependency results in three items in the External Libraries list (there are two sub dependencies apparently). Asking IntelliJ for usage of these libraries, I can't find any usage in my own files. But if I remove the dependency from the pom.xml file, I get runtime problems.
Maven offers you the dependency:analyze goal which gives you the artifacts that are declared in your pom but not used by any part of your source code. Beware, though, that there may be dependencies that are only used at runtime.

How to tell the project to download internal dependency?

I have a JAR. It is not a FAT JAR. It only contains my classes. But my JAR has a dependency upon azure-servicebus. I don't want to add azure-servicebus to my jar and make it a fat jar.
I just want that when the project adds my jar, it should download azure-servicebus automatically.
I am using Maven to create a jar (without dependencies).
How do I specify that? Is this possible?
edit:
I want the project that is adding my jar as a dependency should download azure-servicebus WITHOUT project having to add dependency for azure-servicebus or me packaging azure-servicebus within the jar file.
Assuming you already have a maven structue in your project, you would add the following line to your pom.xml:
<!-- https://mvnrepository.com/artifact/com.microsoft.azure/azure-servicebus -->
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-servicebus</artifactId>
<version>1.2.12</version>
</dependency>
If you don't have a maven structure, you'd need to generate one. This usually can be achieved within the IDE you're using.
If you want the resulting jar not having the service-bus, you can make the dependency some kind of compile only, which would be more or less a duplicate of this question: Is there a Maven "compiler-only" scope for dependency artifacts .
However, this would imply that your target runtime has to include the definition for the classes in some way (via -cp switch maybe).
From my POV: If you need a dependency to run your program, include it as long as the licence allows that.
If I understand you correctly, the structure you are talking about is:
some-project depends on your-jar which depends on azure-servicebus.
If some-project declares a Maven dependency on your-jar, then it gets azure-servicebus automatically as dependency because Maven does transitive dependency resolution. So when you build some-project, azure-servicebus will be on the class-path and if some-project is a WAR/EAR, than azure-servicebus will be part of that WAR/EAR.
I asked this question without knowing something very important.
When jars are put into artifactory, a corresponding .pom file also has to be placed alongside it (outside of the directory). This pom file is what tells the dependent project that the jar you are dependent upon, requires so and so dependencies itself.
This answer helped me understand:
https://stackoverflow.com/a/50002072/4828463
Thanks to everyone who tried.

Maven self-contained child artifact

I have a project which has 3 pom files: parent file (very basic one, just declares its children), main pom for building project itself and a pom file for generating swagger client library. The client artifact is getting downloaded into our Nexus.
The problem is that when I want to use a client library in another project as a dependency it also requires a parent artifact. I don't want to download it into Nexus since it's so basic and will only flood the repository. I've tried packing some kind of an uber-jar, but it doesn't work for me - jar is huge and contains all dependencies, yet it still needs parent artifact. Are there any workarounds?
While I generally would not care about having an additional Parent POM in the repository (our repository contains 2000 different self-created artifacts in various versions, it is not "flooded"), you can have a look at the
https://www.mojohaus.org/flatten-maven-plugin/
which allows you to make your pom smaller, and includes the possibility to get away without a Parent POM.

How to use maven to generate code and package it without dependencies?

I have a project that generates some classes and resources that should then be packaged into a jar.
The class that does the generating has several dependencies. The generated classes have no dependencies.
My initial solution was to use the maven assembly plugin to only include the generated files. Unfortunately, the packaged pom includes all the dependencies required to do the generation. Consumers of this jar pull in a bunch of unnecessary dependencies.
I looked into the maven shade plugin. I compile once, run the generator class with mojo's exec plugin, the compile a final time. Then shade of course runs in the package phase. It creates a dependency-reduced-pom.xml without the excessive dependencies. So run mvn clean package and look in target/foo.jar. I expect the jar in the meta-inf folder to be the reduced dependency jar. But it's the full pom. I don't know how have the generated pom replace the one that is packaged.
Another poor solution I tried was using multiple profiles with their own dependency section. I run maven once with the generating profile, then again with the packaging profile. This works, but sucks because you have to run multiple maven commands. It's not jenkins friendly.
Am I going about this the wrong way? How should I go about arranging a project that generates some code and some text files that are then packaged in a maven friendly artifact?
1) One possibility is to make all your dependencies <optional>true</optional>.
The pom will still have the dependencies but the projects using your library won't try to download them.
2) Use plugin dependencies with the exec plugin.
That works well if the generator class is defined on another project.
Ideally you would call your generator using a plugin and avoid adding those dependencies to your project. That may not be worth doing depending on what your project is for and how reusable your generator has to be.
3) If you are using maven-shade-plugin the dependency-reduced-pom.xml is normally used. Check your .m2 repository to see the contents of the pom that is copied there when you do mvn install. It's likely that its contents will match the dependency-reduced-pom.xml

Maven / eclipse project structure

I am still fairly new to Maven, I finally have it how I want but now I need to break it all over again.
Here is my scenario:
I need to write two different server applications, which use identical core functionality; just, what is done with that framework is very different. One server application is very easy/simple - it's already done - whereas the other is a lot more complicated.
The code is written in a dependency injection style (using Guice, if it matters), so it should be extremely easy to break apart.
My question is this: how would you structure the projects in Eclipse, using Maven? Would you set up three different projects, something like:
server-core
server-appEasy
server-appComplicated
where each server would have it's own pom. Or, would you keep it all in one project? I need to be able to easily recompile appEasy in, say, a month from now, while I work on appComplicated. The classes for appEasy are already in a subpackage. Note: core would not work by itself without at least a mock dependency injection. It doesn't have a main class.
All thoughts appreciated, even on things I haven't thought of.
I would have a structure like this:
/server
/server-core
pom.xml
/server-appeasy
pom.xml
/server-appcomplicated
pom.xml
pom.xml
So each project has its own pom.xml that allows you to build that project in isolation.
However the parent folder also has a pom.xml, which will build all the projects if run. You can do this by including the projects as modules in the parent pom.
E.g. In the parent pom.xml
<modules>
<module>server-core</module>
<module>server-appeasy</module>
<module>server-appcomplicated</module>
</modules>
You can also use managed dependencies in the parent pom tio allow you to centralise external dependency and plugin version numbers.
I would suggest to structure all as a Maven Multi Module project.
The parent project, would have the three projects as modules, the 3th party dependency versions, and the version of your project as a property.
Then, in the server-appComplicated and server-appEasy I would add a dependecy to the server-core.
In this way you will gain:
1- A root project to compile (the parent), that it will generate the two servers and the core-lib.
2- A point where to handle the version numbers and the common dependencies.
I hope it helps
Im not a maven expert but here is my 2 cents.
Each project needs its own pom.
Do you need to build all the projects together? In that case it might make sense to have a parent pom , which has all the common dependencies.
EDIT: In that case, I feel just have three separate 3 pom files for each project.
There are multiple ways to do this, depending on how you need it when it comes to deployment. Assuming that 'server-core' is a shared artifacts among your 'server-appEasy' and 'server-appComplicated' artifacts, I would suggest something as below
Create a Maven Project 'server-core'
Add two module projects
by name 'server-appEasy' and 'server-appComplicated'
Make sure the module projects have their parent set as the 'server-core'
In the end you should have three projects (each has separate pom.xml), where
a. Building 'server-core' will also build the modules
b. Building either of the 'easy' and 'complicated' modules independently on need basis will also build the server-core.
Hope this helps!

Categories

Resources