maven .ClassNotFoundException how to make the jar executable - eclipse

I am new with Maven and I have the following problem. I have a project A which I have added as dependency in another project.
This is what I have added to my pom
</build>
<dependencies>
<dependency>
<groupId>the id</groupId>
<artifactId>artifact id</artifactId>
<version> the version</version>
<scope>compile</scope>
</dependency>
In Eclipse everything is working, but when I try to open the jar file I get this message:
Caused by: java.lang.ClassNotFoundException: the name of project A
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 3 more
So what am I missing ?
Any suggestions would be helpful

When you want to run your application as:
java -jar yourapp.jar
you have take care of two things:
Make sure you have your main class listed in MANIFEST.MF, which I belive you did already.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<mainClass>your.package.YourMainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
Make sure that when you run you application your classpath is properly built. There are couple of ways to do that, but the easiest way would be to use the shade plugin. It will unpack all your dependencies and put them into one jar.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
If you need the other solution without using the shade plugin, just let me know.

Eclipse does its own compilations automatically in the background. The result is that your dependency's jar file is probably available in Eclipse but not in your local maven repository. Try running "maven clean install" in the terminal on your local dependency first (this will add it to your local maven repository), then afterwards build your downstream project with another "maven clean install".
This will create a jar file in the "target" directory at the root of your maven project.

Related

How to rid latest Eclipse (2021-03) of MANIFEST.MF (No such file or directory) error?

Over the last few years, for our Parent POM project in Eclipse, I've had to employ slightly different tweaks to Eclipse's configuration, to avoid having Eclipse give errors like:
...target/classes/META-INF/MANIFEST.MF (No such file or directory) pom.xml
I know I can manually rid these errors, by right-clicking the parent project and doing
Maven > Update Project
but that only works until the next build when I do another "clean install".
In the past, I got Eclipse to stop complaining by making these 2 Eclipse tweaks:
Preferences > Maven > check "Automatically update Maven projects configuration (experimental)"
Preferences > Maven > Java EE Integration > uncheck "Maven Archiver generates files under the build directory".
But, this no longer work, with the latest versions of Eclipse (e.g., Version: 2021-03).
Why does Eclipse do this and how can I rid myself of this annoyance, once and for all?
I found a solution.
The problem is caused by the standard maven-compiler-plugin. When it generates a JAR file, it deletes target/classes/META-INF/MANIFEST.MF.
Eventually (but not right away), Eclipse notices this and complains that the manifest file is missing.
Cleaning the project (as often recommended in related Stack Overflow questions) is not a solution. Although it makes the errors go away temporarily, the errors will soon return, the next time maven-compiler-plugin generates another JAR file.
A permanent solution is to include this additional plugin to my POM, which not just generates a manifest file, but KEEPS it at target/classes/META-INF/MANIFEST.MF:
...
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>bundle-manifest</id>
<phase>compile</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<index>true</index>
<manifest>
<addDefaultSpecificationEntries>false</addDefaultSpecificationEntries>
<addDefaultImplementationEntries>false</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
...
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
...
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
...
</plugin>
</plugins>
...
</build>
...

Exclude Maven Dependency during Eclipse Application Runtime

When I try to run a Java Application on Eclipse, a conflict between two dependencies is causing the application to fail.
I am trying to upgrade my project Java version from OracleJDK 8 to OpenJDK 11. As a result, I also had to also needed to update a GWT dependency from 2.6.0 to 2.8.2, as well as switch from MOJO gwt-maven-plugin to the tboyer version as well. Additionally, the build is done on Maven 4.0.0 on Eclipse IDE 4.9.0.
Snippet of the pom.xml
<properties>
<gwt.version>2.8.2</gwt.version>
...
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt</artifactId>
<version>${gwt.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-dev</artifactId>
<scope>provided</scope>
</dependency>
...
<build>
<plugins>
<plugin>
<groupId>net.ltgt.gwt.maven</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>1.0-rc-10</version>
<executions>
<execution>
<id>compile-common</id>
<goals>
<goal>compile</goal>
<goal>test</goal>
</goals>
<configuration>
<moduleName>XXXXModule</moduleName>
</configuration>
</execution>
<execution>
<id>XXXX</id>
<goals>
<goal>compile</goal>
<goal>test</goal>
</goals>
<configuration>
<moduleName>XXXXModule</moduleName>
</configuration>
</execution>
<execution>
<id>XXXX</id>
<goals>
<goal>compile</goal>
<goal>test</goal>
</goals>
<configuration>
<moduleName>XXXXModule</moduleName>
</configuration>
</execution>
<execution>
<id>XXXX</id>
<goals>
<goal>compile</goal>
<goal>test</goal>
</goals>
<configuration>
<moduleName>XXXXModule</moduleName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
So when I run the application on Eclipse, I get the following error:
SEVERE: Application encountered an exception during Start.
XXXX.ApplicationException: Failed to reflect on start method.
at XXXX.ApplicationLauncher.startApplication(ApplicationLauncher.java:471)
at XXXX.ApplicationLauncher.doRun(ApplicationLauncher.java:185)
at XXXX.ApplicationLauncher.main(ApplicationLauncher.java:67)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at XXXX.ApplicationLauncher.startApplication(ApplicationLauncher.java:469)
... 2 more
Caused by: java.lang.NoSuchMethodError: org.apache.tomcat.util.ExceptionUtils.preload()V
at org.apache.catalina.startup.Tomcat.<init>(Tomcat.java:181)
....
After investigating, I discovered that two of my dependencies tomcat-embed-core-7.0.91 & apache-jsp-8.0.9.M3 both contain ExceptionUtils with several difference, hence the Exception. Furthermore, the apache-jsp is being pulled by the gwt-dev dependency which is only required during the Maven build to run the gwt-maven-plugin.
gwt-dev:2.8.2
apache-jsp:9.2.14.v20151106
apache-jsp:8.0.9.M3
But for some reason, Eclipse is including gwt-dev and it's dependency as part of the runtime path even though I have the 'provided' scope tag in the pom.xml.
I have tried excluding the apache-jsp dependency, but a compile issue occurs because apparently gwt-dev is still being added which depends on apache-jsp.
Summary
The TBroyer GWT-Maven-Plugin requires the pom file to include gwt-dev as a dependency in order to run correctly during a build.
However, when running the application on Eclipse, a NoSuchMethodException occurs on org.apache.tomcat.util.ExceptionUtils.preload()V
The issue is there are two ExceptionUtil classes with same package from different jars and methods.
One of the jars is apache-jsp which is a dependency of gwt-dev. Gwt-dev and it's dependencies should not be part of the runtime classpath.
Question: Is there a way to ensure the gwt-dev is only used during the Maven build and not part of the Eclipse Java Application runtime classpath?
Yes, you can ensure isolated classpath for client and server sides. You need to apply the multimodule layout. This is also the main difference between the old MOJO gwt maven plugin and the new generation tbroyer gwt maven plugin, the new one support multimodule correctly. Check this archetype as a reference for the multimodule layout. Also, use the packaging:gwt-app to configure the gwt maven plugin executions automatically.
Making it work with eclipse run action (tomcat or gwt) is a bit more difficult. Until you correctly apply the tbroyer gwt maven plugin and the multimodule layout, you will be able to use mvn tomcat7:run and mvn gwt:codeserver in the terminal. Then, the recommended strategy to use it in your IDE is to configure this maven goal and run it using the maven tooling of your IDE. This makes it work exactly the same in all your environments (terminal, CI, eclipse, intellij, etc).

Unable to get external class files of scala in build jar eclipse

I'm trying to create a runnable jar from scala spark project which consumes redis library. So, I created classes from Scala-Redis github project and used the package in my present code. The project builds and runs through eclipse interface but When I try to create jar - I receive classNotfound exception. On checking it was noticed that redis class was not included in build jar. I'm using other external jars as well. They are included in build but not the redis one. Where I'm going wrong or missing ?
Pom.xml is :-
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>package-jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>true</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.spark.ReCalculateOdo</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
I've included the class folder in build path run configurations. Suggestions please, Thanks,
I tried one trick and it worked. I don't know why this happens but its working for my case. So the idea is whenever you want a jar just clean build the project then run the project in eclipse now create maven install. You will find a jar in target folder of project. So , now you can use it with command line. It'll work.
Thanks,

How to tell Maven to update manifest's Bundle-Version?

I'm building Eclipse's plugins using Maven, and I'm looking for a way to tell Maven to update the Bundle-Version in the META-INF\MANIFEST.MF file.
The trick is, I need a clean way to do it. So that further colleagues (or even me in some months/years) may not break the final automated build.
Here is what I tried :
Using "Bundle-Version: ${project.version}" in the MANIFEST.MF
On a maven point-of-view, this is working.
BUT my Eclipse project is constantly displaying an error : The specified version does not have the correct format (major.minor.micro.qualifier)
Using the above but in another META-INF folder (named META-INF-MAVEN) that is used by maven instead of the original :
<resources>
<resource>
<directory>META-INF-MAVEN</directory>
<targetPath>META-INF</targetPath>
<filtering>true</filtering>
</resource>
</resources>
This is still "working", but the needed duplication of MANIFEST.MF file is far away from what I'm looking for. This is a large trap for future errors, like editing the original MANIFEST.MF file and forgetting the maven one, resulting in a bugged release.
Using org.apache.maven.plugins to add the Bundle-Version tag at compile-time from the pom file :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestFile>target/classes/META-INF/MANIFEST.MF</manifestFile>
<manifestEntries>
<Bundle-Version>${project.version}</Bundle-Version>
</manifestEntries>
</archive>
</configuration>
</plugin>
This is the most promising way, BUT it only works if the original MANIFEST.MF does not have a Bundle-Version line.
The result is, again, an error within the Eclipse project.
And so, here I am, asking for any idea.
Thanks.
Following solution finds the Bundle-Version: line in META-INF/MANIFEST.MF and replaces it with the Maven project version. replacer maven plugin was used for that but there are certainly other maven plugins that can do the same work like find-and-replace-maven-plugin.
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.3</version>
<executions>
<execution>
<id>update-manifest-version</id>
<phase>process-resources</phase>
<goals>
<goal>replace</goal>
</goals>
<configuration>
<file>${basedir}/META-INF/MANIFEST.MF</file>
<regex>true</regex>
<replacements>
<replacement>
<token>Bundle-Version: .*</token>
<value>Bundle-Version: ${project.artifact.selectedVersion.majorVersion}.${project.artifact.selectedVersion.minorVersion}.${project.artifact.selectedVersion.incrementalVersion}.qualifier
</value>
</replacement>
</replacements>
</configuration>
</execution>
</executions>
</plugin>

GWT compilation is skipped in maven when module packaging is pom

I am trying to reuse a assembled gwt compilation in another war. For this i am try to change the current maven module's packaging from war to pom. I then plan to use maven-assembly-plugin to zip up gwt's module js output and use that later on in another war module.
I tried changing the packaging tag from <packaging>war</packaging> to <packaging>pom</packaging> in pom.xml from Validation sample . gwt-maven-plugin never enters into compilation. Instead, it skips compilation!!!!!
What is happening?
Is this expected?
Is there any workaround?
To join multiple gwt compiled modules into a single .war file, it is very easy with the maven-dependency-plugin
Package all your gwt examples as habitual (.war), and install them mvn install or mvn deploy if you have a private maven repo.
Create an empty maven module of type war, with no code but with the maven folder structure, you can put any additional stuff you need here like a global src/main/webapp/index.html.
Configure the new module to use the maven-dependency-plugin like shown below, and run mvn package:
<dependency>
<groupId>my.group</groupId>
<artifactId>example1</artifactId>
<version>...</version>
<type>war</type>
</dependency>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-gwt-examples</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>my.group</includeGroupIds>
<includes>**/example1/**</includes>
<outputDirectory>${project.build.directory}/${project.artifactId}-${project.version}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Finally and related with the gwt-maven-plugin, like with any other maven pluging, it would be enough to select an appropriate phase of the pom-packaging life cycle (package, install or deploy):
...
<packaging>pom</packaging>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
...
<configuration>
...
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
Unfortunately, gwt-maven-plugin specifically disallows compilation when packaging is pom, take a look to line #269 of CompileMojo.java
You can create the reusable modules (that you mention as samples in the comments) as separate GWT projects with no EntryPoint. Package them as jar and add the following as resources:
the client side source code
other resource items that will be necessary for the final compilation (images, xml files, etc.)
Something like this:
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
...
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/services/**</include>
<include>**/client/**</include>
<include>**/public/**</include>
<include>**/*.gwt.xml</include>
</includes>
</resource>
</resources>
</build>
That's it, you can reuse it in any other GWT project. When you will do so, you just have to add the dependency (to the reusable module) in the pom.xml and import in the *.gwt.xml.
As for Maven's behaviour, it seems correct. pom packaging is going through package, install and deploy phases and
By default, the compile goal is configured to be executed during the ''prepare-package'' phase to run as late as possible.
You could change the phase in the plugin's execution, but I think it's risky because you can't know when exactly during the package phase will your code get compiled.