This is a good question I came across right now, exploring examples of many ways that Java developers can enjoy a class :-)
I started with the minimal version of your build.gradle (including only what is directly relevant), in particular:
plugins { id 'java' } sourceCompatibility = 1.8 repositories { mavenCentral() } jar { manifest { attributes 'Main-Class': 'com.oliverlockwood.Main' } } dependencies { compile 'org.apache.httpcomponents:httpclient:4.5.1' }
In this context, the My 'Main' class uses your sample code, that is:
package com.oliverlockwood; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; public class Main { public static void main(String[] args) { CloseableHttpClient client = HttpClients.createDefault(); } }
At this point I can run gradle clean build and then java -jar build/libs/33106520.jar (my project was named after this StackOverflow question) and I see the following:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/http/impl/client/HttpClients at com.oliverlockwood.Main.main(Main.java:8) Caused by: java.lang.ClassNotFoundException: org.apache.http.impl.client.HttpClients at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
This is subtly different from your error, but before we break it down and reproduce it, let me emphasize something: both this error and what you see are called at runtime when the class loader cannot find the class that it needed, There's a pretty good blog post here with more details on the difference between class classes and runtime classes.
If I run gradle dependencies , I can see the runtime dependencies for my project:
runtime - Runtime classpath for source set 'main'. \--- org.apache.httpcomponents:httpclient:4.5.1 +--- org.apache.httpcomponents:httpcore:4.4.3 +--- commons-logging:commons-logging:1.2 \--- commons-codec:commons-codec:1.9
I manually added them one by one to my classpath. (For reference, this is usually not considered good practice, but for the experiment I copied these banks to the build/libs folder and ran java -cp build/libs/33106520.jar:build/libs/* com.oliverlockwood.Main . Interestingly, this Failed to reproduce your exact problem. Recall:
- Without
org.apache.httpcomponents:httpclient available at run time, we fail because the HttpClients jar HttpClients not found. - With
org.apache.httpcomponents:httpclient:4.5.1 available at runtime, your problem doesn't show up - and I notice that the class your assembly doesn't find ( org.apache.http.conn.ssl.SSLConnectionSocketFactory ) is part of the same Apache library, which is very suspicious.
My suspicion is that your runtime path contains a different version of the apache httpclient library. Since there are all versions of lotta there, I am not going to test each combination, so instead you will leave the following advice to you.
- If you want to fully understand the root cause of your problem, then determine exactly which banks (including their versions) are present in your path to the runtime classes, including any banks that are packed inside yours if you create (more on this in paragraph 3) . It would be great if you shared these details here; analysis of the root causes usually helps everyone better understand :-)
- If possible, avoid using dependencies with the
compile fileTree(dir: 'lib', include: ['*.jar']) . Repository-based managed dependencies such as Maven or JCenter make it much easier to work with sequences than dependencies in a random directory. If these are internal libraries that you don’t want to publish to the open source artifact repository, it might be worth creating a local Nexus instance or similar. - Consider creating a “thick jar” instead of a “thin jar” —this means that all time-dependent packages are packaged in the jar you create. There's a nice Shadow plugin for Gradle that I would recommend - with this in place in my
build.gradle and running gradle clean shadow , I managed to run java -jar just fine, without having to manually add anything to my classpath.