I have read numerous posts regarding this, and I was still not able to find a clear-cut answer.
We have the need to use a proprietary SDK in our maven project and this SDK contains ~315 jar files that are needed for around 30 lines of code (SAP product). Every answer I read dealt with adding individual jars to your local maven repo. That is fine and I understand that, but is it possible to add an entire directory of libraries. These libraries are only needed for compiling the project since they are already on the classpath of the target server (They would all be scoped as provided in a pom).
I've tagged Netbeans 8 since that is the IDE I am using, so if anyone knows a hack to get a maven project in netbeans compiled using libraries on Netbeans classpath that would be a good solution as well...
JAR's are just java .class organized in folders and Zipped. Extract all those 315 JARs to somewhere, thus merging all of their content, and then Zip it again to one single fat JAR file. Add this fat JAR to your local repository as you have read elsewhere.
This other question can help you with the JAR merging thing: How to combine two Jar files
Although there are many messy workarounds for this, the ideal would be to let the compilation fail and search for the missing compile jars using a search utility like agent ransack you can search within the jars in that directory for the missing classes referenced in the compiler errors. As you find the jars you need, add them as dependencies with the scope of provided.
A less clean option would be to zip all of the jars, use the dependency plugin to unpack them to a folder and add that folder to the classpath of the build, then remove them or exclude them from the final package.
Related
The scenario is that I have a bunch of java projects with source files and lib jar files (for example apache-commons). I have multiple projects like that in different locations (shared drives, web servers, etc). Some of these projects depend on others. For example the output (.jar) from one project is used to compile and produce output for an other.
What I want to do is, programmatically (headless), using java, collect the source files and libs for all projects, compile them in order, and at the end produce jar files for the end projects. So, for project #1, brings all source files to a directory, bring all dependent libs in the same directory, compile, and create a .jar. Then do the same for project #2 but also include in the libs (or class path) the output of project #1, etc.
The projects dependency is known. The order on which the projects need to compile is known.
Bringing the source files and lib files together is not a problem. What I am looking for is suggestions on how to go about compiling programmatically. One option that I am considering is maybe Eclipse JDT. But before I go that path, I would like to see what other similar options exist out there
(I do understand that there are better procedures and processes that can be followed in order to make it easier to get the end result but I have no control over those. The build needs to be done dynamically/programmatically as described above)
I have a project in Scala (a kind of test utility) which is currently used only in sbt run way. However for certain demo I want to prepare it in a form which does not require sbt or scala preinstalled (only JVM).
First I've tried to use sbt-assembly plugin but soon get lost fighting with duplicate entries. So now I'm curious whether I can simply compile it to:
single jar-file containing application itself;
and lib directory containing raw set of dependency jars.
I hope that in such case it would be easy to run with the help of Main-Class and Class-Path: ./lib/* fields in the manifest - am I wrong? If this is correct, how can I achieve this?
Update: at last I conquered (it seems so) the sbt-assembly approach, so now the question is not as urgent (though I'm still curious to extend my knowledge of using sbt).
When execute sbt-assembly, all depedencies, App and resources will package into a single jar file.
You can override config properties in runtime by:
java -cp conf/:myAppDemo.jar App.run.mainClass
put your config properties files in conf folder.
Sbt one jar plugin can resolve more dependency conflicts, then assembly plugin.
Also take a look on merge section of assembly plugin, that can help you to fix problems like log4j.xml duplication. If you have problems with two classes with the same classpath having different content, try to exclude some duplicated dependencies (library management)
I have a single very large codebase that compiles down to a JAR. I also use the shade plugin to compile it down and package it up with all dependencies. I also use the war plugin to get a WAR file.
With respect to the WAR file, once the goal is created I have a post-build event that simply copies the WAR file to its destination, so technically I'm good with that.
The problem I have is with the other two JARs. They both share the same artifactId since they're both built in a single pom.xml and this isn't acceptable for a number of reasons (including, but not limited to the fact that some caching of dependencies is pretty dumb about realizing that one JAR is the thin one and one is the full-dependency one).
What I need to do is create a pom.xml (or group thereof) suitable for builds (by Jenkins) that can use the same codebase (pulled from Github) but create two separate JAR files, each with their own artifactId.
Being a Maven novice, I've read through the beginning book and it seems to me that what I want is a parent pom.xml with two modules. But from what I can tell, each module means a separate directory with separate code. As I said, this is built from the same codebase. The only difference is one is built from the "regular" build, and the other is built using the "shade" plugin and goal.
The only other thing I can think of is build the "regular" JAR and then build the shaded JAR with a classifier of "full?" If this is the answer, may I humbly ask for some adult supervision on how to do this, as I'm not seeing how.
If that's not the answer, I suspect this must be a common problem, so again, some guidance would be very helpful!
The solution I came up with was to use a classifier for the "shaded" jar. Thus, the artifacts don't collide.
I then had an issue accessing it, but found the solution to that issue as well - How do I access a jar with a classifier?
How do I prevent IntelliJ from including 3rd-party JARs inside my JAR ?
It's insanely annoying. Basically I want one of these:
to produce jar with my code only. 3rd-party jar will be referenced in manifest.
OR
to produce jar with extracted classes of 3rd-party libraries.
The only problem is that IntelliJ produces JAR with other jar files inside. They are useless because java doesn't see them anyway when I run my jar via java -jar my.jar. I have to manually delete them and repack JAR/ZIP file.
Dependencies are not marked as "Export" in Settings.
I think jars end up in my jar because I added "compile output" in layout of my artifact. But I'm not sure how I can make compile output without jars of dependencies.
I tried setting Scope of dependencies to "Provided". It didn't help. They still get copied to output.
Thanks!
This behavior is controlled by the following options when you create a jar artifact in IDEA:
Refer to help for details.
So I'm fairly new to Java and especially Eclipse, so please excuse my ignorance. I took a project from a server and copied it locally to my machine. When I opened the workspace, I had many errors due to it not being able to find the jars. This makes sense because I don't have the same dir structure as the server I copied from. So if I copy the same external jar's to my machine and get it to compile into a jar and copy it back to the server, will it work? Or will it fail because now the external jar's are in a different place than it is expecting?
Also, down the road should I put the external jars into regular jars to avoid this problem?
You should be OK. Java is using what is called classpath to locate dependencies. The classpath may be different on the development machines, but as long as all the dependencies are on the classpath in the production everything should work.
To avoid issues with the synchronisation of directory structures the most common way is to use Maven - it will manage all the dependencies for you (but you have to manage the pom.xml - the Maven's project descriptor). A little clumsier way is to have the dependencies in the project, however you may end up with many projects having to include same jars, and then there will be version conflicts and so on.
For small projects you can manage dependencies yourself, however larger projects will need a more thought through strategy (like Maven).
In regard to the executable jars, make sure the Class-Path entry in <jarfile>:\META-INF\MANIFEST.MF is correct, e.g. where it references other jars, those jars are going to be there in the production. For example, assume we have ourjar.jar and assume this is a snippet from its MANIFEST.MF:
Class-Path: lib/myteamjar.jar
It will then be expected that a following directory structure is in place:
lib/myteamjar.jar
ourjar.jar
No, the location of the external jars does not mater. What you want to do is put the external jars on your classpath. How you do it depends on how you are running your java code. If you are running it from the CLI using the java command, it takes the classpath as an argument. If you want your code to build/run in Eclipse, you need to right click on your project, select "Build Path" > "Configure Build Path..." Use the "Add JARs..." button to add jars that are part of a project you have open and "Add External JARs..." to add jars that reside outside of the project. See specific documentation for your tool for more details about classpaths.
I would not recommend Maven to somebody who is fairly new to Java and Eclipse. I would forget about Eclipse, too.
You have a packaging and CLASSPATH issue. Focus on that.
What kind of project are you talking about? The answer you get will depend on what type of app you're creating. Is it an executable JAR? Then the right way to do it is to package everything into a ZIP file that's laid out exactly as the CLASSPATH in the JAR manifest expects.
If it's a web app, the right thing is a WAR file, with all the JARs your app needs in the WEB-INF/lib directory.
If you package things properly, you should end up with a single package that has everything laid out the right way. You should be able to deploy it to the server and make it all work.