Optaplanner - NullPointerException when creating jar file - java

My program works fine from my IDE (IntelliJ) but for some reason, when I try to create a jar file I get following error when I run the program from a terminal:
Exception in thread "main" java.lang.NullPointerException at org.optaplanner.core.config.score.director.ScoreDirectorFactoryConfig.buildDroolsScoreDirectorFactory(ScoreDirectorFactoryConfig.java:461)
org.optaplanner.core.config.score.director.ScoreDirectorFactoryConfig.buildScoreDirectorFactory(ScoreDirectorFactoryConfig.java:331)
org.optaplanner.core.config.solver.SolverConfig.buildSolver(SolverConfig.java:220)
org.optaplanner.core.impl.solver.AbstractSolverFactory.buildSolver(AbstractSolverFactory.java:57)
org.optaplanner.EmployeeRoster.main(EmployeeRoster.java:31)
This is my line 31 in EmployeeRoster:
Solver solver = SolverFactory.createFromXmlResource(SOLVER_CONFIG_XML).buildSolver();
SOLVER_CONFIG_XML is a String containing my path for my XML solver-config,
it looks like this
<?xml version="1.0" encoding="UTF-8"?>
<solver>
<solutionClass>org.optaplanner.solver.Roster</solutionClass>
<entityClass>org.optaplanner.domain.Assignment</entityClass>
<scoreDirectorFactory>
<scoreDrl>org/optaplanner/solver/employeeShiftsScoreRules.drl</scoreDrl>
</scoreDirectorFactory>
<localSearch>
<termination>
<secondsSpentLimit>5</secondsSpentLimit>
<bestScoreLimit>0hard/0medium/0soft</bestScoreLimit>
</termination>
<!--<termination>
<unimprovedStepCountLimit>5</unimprovedStepCountLimit>
</termination>-->
<acceptor>
<entityTabuSize>7</entityTabuSize>
</acceptor>
<forager>
<acceptedCountLimit>1000</acceptedCountLimit>
</forager>
</localSearch>
</solver>
Also here's my pom.xml file if that should be relevant:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.btrg.dfb</groupId>
<artifactId>optaplanner</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.optaplanner</groupId>
<artifactId>optaplanner-core</artifactId>
<version>7.3.0.Final</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.8</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>org.avalin.optaplanner.EmployeeRoster</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-my-jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<executions>
<execution>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
What might I be doing wrong?

For me, the issue had to deal with how I wanted to run the jar (java -jar), and consequently how I built the jar. The NullPointerException arose when I upgraded to optaplanner-core/7.4.1 from 6.4.0. This issue was not present back when I was still using 6.4.0.
Exception:
java.lang.NullPointerException
at org.kie.internal.io.ResourceFactory.newByteArrayResource(ResourceFactory.java:66)
at org.drools.compiler.kie.builder.impl.AbstractKieModule.getResource(AbstractKieModule.java:299)
at org.drools.compiler.kie.builder.impl.AbstractKieModule.addResourceToCompiler(AbstractKieModule.java:264)
at org.drools.compiler.kie.builder.impl.AbstractKieModule.addResourceToCompiler(AbstractKieModule.java:259)
at org.drools.compiler.kie.builder.impl.AbstractKieProject.buildKnowledgePackages(AbstractKieProject.java:243)
at org.drools.compiler.kie.builder.impl.AbstractKieProject.verify(AbstractKieProject.java:74)
at org.drools.compiler.kie.builder.impl.KieBuilderImpl.buildKieProject(KieBuilderImpl.java:250)
at org.drools.compiler.kie.builder.impl.KieBuilderImpl.buildAll(KieBuilderImpl.java:218)
at org.drools.compiler.kie.builder.impl.KieBuilderImpl.buildAll(KieBuilderImpl.java:176)
at org.optaplanner.core.config.score.director.ScoreDirectorFactoryConfig.buildDroolsScoreDirectorFactory(ScoreDirectorFactoryConfig.java:503)
The following is a temporary workaround I did to resolve the NullPointerException and just get the application to run.
Use IntelliJ's gradle to build one big jar with all dependencies.
Unzip the jar, for example, to unzippedJar/ directory.
Modify unzippedJar/META-INF/kie.conf
Rejar the files.
Run the jar with java.
Step 1. Building the jar
dependencies {
...
compile group: 'org.optaplanner', name: 'optaplanner-core', version:'7.4.1.Final'
compile group: 'org.optaplanner', name: 'optaplanner-benchmark', version:'7.4.1.Final'
...
}
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Self contained jar with all dependencies',
'Implementation-Version': version,
'Main-Class': 'path.to.class.with.main.method'
}
baseName = 'fatJar'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
Step 2. Unzip
unzip fatJar.jar -d unzippedJar/
Step 3. Modify kie.conf
The "fatJar" task flattened the dependencies - duplicate file names are allowed in the jar. This resulted in four unzippedJar/META-INF/kie.conf files, only one of which was used. Regardless of whichever kie.conf file was used, this was my final kie.conf.
org.kie.api.internal.assembler.KieAssemblers = +org.optaplanner.core.impl.solver.kie.KieSolverAssemblerService
org.kie.api.internal.assembler.KieAssemblers = org.kie.internal.services.KieAssemblersImpl
org.kie.api.internal.runtime.KieRuntimes = org.kie.internal.services.KieRuntimesImpl
org.kie.api.internal.weaver.KieWeavers = org.kie.internal.services.KieWeaversImpl
org.kie.api.internal.runtime.beliefs.KieBeliefs = org.kie.internal.services.KieBeliefsImpl
org.kie.api.io.KieResources = org.drools.core.io.impl.ResourceFactoryServiceImpl
org.kie.api.marshalling.KieMarshallers = org.drools.core.marshalling.impl.MarshallerProviderImpl
org.kie.api.concurrent.KieExecutors = org.drools.core.concurrent.ExecutorProviderImpl
org.kie.api.KieServices = org.drools.compiler.kie.builder.impl.KieServicesImpl
org.kie.internal.builder.KnowledgeBuilderFactoryService = org.drools.compiler.builder.impl.KnowledgeBuilderFactoryServiceImpl
Step 4. Rejar
For whatever reason, specifying the MANIFEST.MF file did nothing for me, hence I left it out.
jar cf rejard.jar .
Step 5. Run the jar
java -cp rejard.jar path.to.class.with.main.method

Following #Arturo W's answer, I can suggest another fix using maven's
assembly plugin to
make a fat jar.
As stated in the documentation:
"If two or more elements (e.g., file, fileSet) select different sources for
the same file for archiving, only one of the source files will be archived.
[...] The order of the phases is as follows: 1) FileItem 2) FileSets
3) ModuleSet 4) DependencySet and 5) Repository elements."
META-INF/kie.conf is provided in org.optaplanner.core's archive, hence
maven packages optaplanner's version over the custom one define in your
repository.
To include it, we exclude all META-INF/kie.conf files during unpackaging
and manually copy our version using the <file></file>
option in a custom descriptor file.
Here's how we do it:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- ... -->
<build>
<plugins>
<!-- ... -->
<!-- fat jar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptors>
<descriptor>src/assembly/distribution.xml</descriptor>
</descriptors>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.veryseriouscompany.veryseriousproject.app.Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<!-- ... -->
To fix the inclusion of kie.conf, we'll have to write a custom descriptor,
defined in src/assembly/distribution.xml. We start from a predefined
descriptor:
jar-with-dependencies.
That's a good starting point.
src/assembly/distribution.xml
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
<id>epigno-jar-with-dependencies</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
<scope>runtime</scope>
<!-- Exclude all META-INF/kie.conf during unpacking -->
<unpackOptions>
<excludes>
<exclude>META-INF/kie.conf</exclude>
</excludes>
</unpackOptions>
</dependencySet>
</dependencySets>
<files>
<file>
<!-- Manually copy your custom kie configuration file from your repository. -->
<!-- Please replace this path by whatever path is relevant for your project. -->
<source>src/main/resources/META-INF/kie.conf</source>
<outputDirectory>META-INF</outputDirectory>
</file>
</files>
</assembly>
When you are finished, run
mvn package
Hopefully, this will package the correct kie.conf in your fat jar!

Related

maven-jar-plugin generates jar with wrong MANIFEST.MF

I want to generate an jar file including its dependencies. Here is my pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>vehicle</artifactId>
<groupId>org</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>vehicle.cli</artifactId>
<dependencies>
<dependency>
<groupId>org</groupId>
<artifactId>vehicle.model</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/libs
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>
org.vehicle.cli.Main
</mainClass>
</manifest>
<manifestEntries>
<Class-Path>.</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
The dependency org.vehicle.model I take it from a custom nexus repository.
After running mvn package I get the target folder with the libs folder and the jar file in the same hiarachy:
- target
- libs
- vehicle.model-0.0.1-SNAPSHOT.jar
- commons-cli-1.4.jar
- vehicle.cli-0.0.1-SNAPSHOT.jar
When I execute the vehicle.cli-0.0.1-SNAPSHOT.jar (java -jar vehicle.cli-0.0.1-SNAPSHOT.jar) I get an exception java.lang.NoClassDefFoundError for the classes in the vehicle.model-0.0.1-SNAPSHOT.jar
It's strange because I have all the dependencies jar already in the libs folder, so I unpack the vehicle.cli-0.0.1-SNAPSHOT.jar to check the MANIFEST.MF and see the following:
Manifest-Version: 1.0
Created-By: Maven Jar Plugin 3.2.0
Build-Jdk-Spec: 16
Class-Path: . libs/vehicle.model-0.0.1-20210203.101620-3.jar libs/commons-cli-1.4.jar
Specification-Title: vehicle.cli
Specification-Version: 0.0
Implementation-Title: vehicle.cli
Implementation-Version: 0.0.1-SNAPSHOT
Main-Class: org.vehicle.cli.Main
What makes me confused is in the line for ClassPath, it's calling the jar file named libs/vehicle.model-0.0.1-20210203.101620-3.jar while this jar file is not existing. I expect it should call the jar file with name: libs/vehicle.model-0.0.1-SNAPSHOT.jar, because it is the one that was copied to the libs folder by the maven-dependency-plugin. I dont understand where is the version -0.0.1-20210203.101620-3 coming from.
Can anyone explain me what is the problem here and how to fix it? Thank you!
We have run into something like this before. There is a bug reported for the jar plugin that was not fixed. Luckily, there is a workaround. Adjust the manifest in the jar plugin like this:
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>org.vehicle.cli.Main</mainClass>
<useUniqueVersions>false</useUniqueVersions> <!-- important! -->
</manifest>
<manifestEntries>
<Class-Path>.</Class-Path>
</manifestEntries>
</archive>
If that isn't enough, the dependency plugin has a similar <useBaseVersion> property that may be enabled.

Error: Could not find or load main class while executing jar file

I have created two java file my maven project one is POJO class and another one is java main class file. I want to make my project as an executable jar file which i want to run externally using java -jar command.
Please find my pom.xml file
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ElasticSearchUtility</groupId>
<artifactId>ElasticSearchUtility</artifactId>
<version>1.0.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.1.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.1.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>rest</artifactId>
<version>5.1.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>false</downloadJavadocs>
</configuration>
</plugin>
<!-- Set a compiler level -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- Make this jar executable -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/log4j.properties</exclude>
</excludes>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.es.utility.DocumentIndex</mainClass>
<classpathPrefix>dependency-jars/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
<!-- Copy project dependency -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<!-- exclude junit, we need runtime dependency only -->
<includeScope>runtime</includeScope>
<outputDirectory>${project.build.directory}/dependency-jars/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
While am executing my jar file using java -jar command. Am getting the error
Error: Could not find or load main class com.es.utility.DocumentIndex
Please find my project structure also :
If there are no classes in the .jar it's probably because maven can't find them. The default path for java classes in Maven is src/main/java, try moving them there and run Maven again.
To add to #kshetline's comment, make sure com.es.utility.DocumentIndex is the correct path to your main class. When you unzip the generated jar, DocumentIndex.class should be in the com/es/utility folder.

Maven com.google cannot be resolved to type

New to Maven. I built my project using Maven and generate a Protobuf executable and generate the source to my project. I'm using eclipse and compiling in Java. I don't seem to have the library properly imported so I get a lot of errors when viewing the generated code through eclipse.
I am receiving error Maven com.google cannot be resolved to type
I've looked at numerous suggestions and can't seem to find a resolution to this problem. My build path seems to be correct from what I think.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.henosisknot.com</groupId>
<version>0.1.0</version>
<name>ChatBot-Henosisknot</name>
<url>henosisknot.com</url>
<description>Chatbot for henosisknot.com</description>
<artifactId>Chatbot-Henosisknot</artifactId>
<packaging>pom</packaging>
<profiles>
<profile>
<modules>
<module>com</module>
</modules>
</profile>
</profiles>
<organization>
<name>Henosisknot.com</name>
</organization>
<properties>
<!-- protobuf paths -->
<protobuf.input.directory>${project.basedir}/src/main/java/com/proto</protobuf.input.directory>
<protobuf.output.directory>${project.basedir}/src/</protobuf.output.directory>
<project.build.dir>${project.basedir}/build</project.build.dir>
<!-- library versions -->
<build-helper-maven-plugin.version>1.9.1</build-helper-maven-plugin.version>
<maven-antrun-plugin.version>1.8</maven-antrun-plugin.version>
<maven-dependency-plugin.version>2.10</maven-dependency-plugin.version>
<maven-shade-plugin.version>2.4.2</maven-shade-plugin.version>
<os-maven-plugin.version>1.4.1.Final</os-maven-plugin.version>
<protobuf.version>3.0.0</protobuf.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
<build>
<extensions>
<!-- provides os.detected.classifier (i.e. linux-x86_64, osx-x86_64) property -->
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>${os-maven-plugin.version}</version>
</extension>
</extensions>
<directory>${project.build.dir}/classes</directory>
<outputDirectory>/users/andor/workspace/Chatbot-Henosisknot/build/classes</outputDirectory>
<plugins>
<!-- copy protoc binary into build directory -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>${maven-dependency-plugin.version}</version>
<executions>
<execution>
<id>copy-protoc</id>
<phase>generate-sources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.google.protobuf</groupId>
<artifactId>protoc</artifactId>
<version>${protobuf.version}</version>
<classifier>${os.detected.classifier}</classifier>
<type>exe</type>
<overWrite>true</overWrite>
<outputDirectory>${project.build.dir}</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<!-- compile proto buffer files using copied protoc binary -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>${maven-antrun-plugin.version}</version>
<executions>
<execution>
<id>exec-protoc</id>
<phase>generate-sources</phase>
<configuration>
<target>
<property name="protoc.filename" value="protoc-${protobuf.version}-${os.detected.classifier}.exe"/>
<property name="protoc.filepath" value="${project.build.dir}/${protoc.filename}"/>
<chmod file="${protoc.filepath}" perm="ugo+rx"/>
<mkdir dir="${protobuf.output.directory}" />
<path id="protobuf.input.filepaths.path">
<fileset dir="${protobuf.input.directory}">
<include name="**/*.proto"/>
</fileset>
</path>
<pathconvert pathsep=" " property="protobuf.input.filepaths" refid="protobuf.input.filepaths.path"/>
<exec executable="${protoc.filepath}" failonerror="true">
<arg value="-I"/>
<arg value="${protobuf.input.directory}"/>
<arg value="--java_out"/>
<arg value="${protobuf.output.directory}"/>
<arg line="${protobuf.input.filepaths}"/>
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.0</version>
<configuration>
<protocExecutable>/usr/local/bin/protoc</protocExecutable>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<includes>
<include>**/com/**</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>main.java.com.chatbot.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>com.chatbot.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
The one thing to remember with Apache Maven is that a key tenet in it's design is the principle of "convention over configuration". This means that if we stick to the maven conventions then our pom.xml files become a lot smaller and simpler.
And you seem to have configured your way into trouble. The key elements for your build are:
You're building a jar file
It contains classes that you have written
It contains classes that will be generated from .proto files that are in your source tree.
Build the right kind of artifact
As you're building a jar file, your pom should declare the packaging correctly:
<packaging>jar</packaging>
Process the .proto message files
Now, I'm going to focus on processing your .proto files because that seems to be causing you the most trouble right now.
Install protoc if necessary
The first thing it needs is an executable copy of the protoc executable.
Your sample pom.xml above is both downloading a version from the maven repository into ${project.build.dir}, aka the target directory, and trying to use /usr/local/bin/protoc for the same purpose.
You may or may not actually have the latter in place. If not then:
If your target directory contains protoc-3.5.1-1-osx-x86_64.exe then we can use that, otherwise:
Point your browser at search.maven.org;
Search for com.google.protobuf;
Click on the protoc link and directly download the version that you want.
Then:
Copy the downloaded artifact to /usr/local/bin/
Rename it to protoc, and
Make it executable:
chmod a+x protoc
Set up the protobuf-maven-plugin
You have already discovered the protobuf-maven-plugin.
Setting this up is the key to resolving your remaining problems.
By convention, it expects to find your .proto files in:
src/
main/
proto/
with a conventional java package structure below that. Therefore:
Move the .proto files into this location.
Your protobuf-maven-plugin configuration is then ok, although I suspect that you do not need the:
<goal>test-compile</goal>
line.
Last steps
Finally, you should completely remove the maven-compiler-plugin declaration.
Remember that maven conventions will be used to set this up properly.
As protoc is now hand installed, we can get rid of some large slabs of XML from your pom file:
<description>ffffff</description>
<artifactId>fffffff</artifactId>
<!-- you're building a jar -->
<packaging>jar</packaging>
<!-- the profiles section was meaningless -->
<organization>
<name>fffff</name>
</organization>
<properties>
<!-- protobuf paths -->
<!-- you were fighting maven with these properties -->
<!-- library versions -->
<maven-shade-plugin.version>2.4.2</maven-shade-plugin.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<!-- generate java from .proto files -->
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.1</version>
<configuration>
<protocExecutable>/usr/local/bin/protoc</protocExecutable>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- maven compiler plugin declaration is usually redundant unless you want a specific version -->
<!-- I have not addressed this... -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
...
</plugin>
</plugins>
</build>

Creating jar by maven to read resources text file from the same jar file

I have simple maven project in Eclipse. The application contains file: src/main/resources/test.txt. I would like to read the file and write it on the output. It works in Eclipse, but not from command line after creating jar file. How to configure the project to work in both ways.
Where am I wrong?
Not correct jar file, java code, manifest, maven configuration?
Application structure:
Application structure
Running:
java -jar fileRead-0.0.1-SNAPSHOT.jar
Error:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/io/IOUtils
at fileRead.FileRead.main(FileRead.java:11)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.io.IOUtils
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)
... 1 more
Java code:
package fileRead;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
public class FileRead {
public static void main(String[] args) {
String file = null;
try {
file = IOUtils.toString((new FileRead()).getClass().getClassLoader().getResourceAsStream("test.txt"));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(file);
}
}
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.fileRead</groupId>
<artifactId>fileRead</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>fileRead</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.directory.studio</groupId>
<artifactId>org.apache.commons.io</artifactId>
<version>2.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>fileRead.FileRead</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
fileRead-0.0.1-SNAPSHOT.jar:
fileRead
FileRead.class
META-INF
maven
MANIFEST.MF
test.txt
MANIFEST.MF:
Manifest-Version: 1.0
Built-By: msmorenda
Class-Path: org.apache.commons.io-2.4.jar commons-io-2.4.jar
Created-By: Apache Maven 3.5.0
Build-Jdk: 1.8.0_121
Main-Class: fileRead.FileRead
test.txt:
abc
def
ghi
The problem is that MANIFEST.MF is pointing to the required dependencies. But the dependencies are not in the same directory as the generated jar file. To copy the required libraries (commons-io) you need to add another plugin to your pom as follows:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<classpathPrefix>lib</classpathPrefix>
<addClasspath>true</addClasspath>
<mainClass>fileread.FileRead</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
The maven-dependency-plugin with the above configuration will copy the required libraries in the lib directory under target. Now if you make the target directory your current directory and call java -jar <name_of_jar> everything should work.
Note: if your want to move your jar file to another location you should package it with the lib directory together. And note too, that I changed the package name of your class to fileread instead of fileRead. Reason? Java convention.
you can create an assembly with maven which includes the libraries you need and then use "mvn package" to create it
pom.xml
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<descriptors>
<descriptor>src/assemblies/bin-with-dependencies.xml</descriptor>
</descriptors>
<tarLongFileMode>gnu</tarLongFileMode>
</configuration>
</plugin>
</plugins>
</build>
src/assemblies/bin-with-dependencies.xml
<assembly>
<id>bin-with-dependencies</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory></outputDirectory>
<unpack>false</unpack>
<scope>compile</scope>
</dependencySet>
<dependencySet>
<unpack>false</unpack>
<scope>runtime</scope>
<useProjectArtifact>true</useProjectArtifact>
</dependencySet>
</dependencySets>
</assembly>
this creates and archive containing a folder with your jar and all it's libraries
and then run it like
java -cp {directory_jars}/* fileread.FileRead ...
"/*" possibly only works on windows

Maven not including manifest attributes for LWJGL install

I am trying to setup a LWJGL project using Maven. I am using the example "getting started" source code from the official website.
This includes a few lines accessing LWJGL's manifest attributes, such as a simple version check:
System.out.println("Hello LWJGL " + Version.getVersion() + "!");
This runs without any problems in the Eclipse environment (of course after having built the project with Maven), but when running clean install and then running **-jar-with-dependencies.jar through cmd, the following exception get's thrown:
java.lang.NullPointerException
at org.lwjgl.system.APIUtil.apiGetManifestValue(APIUtil.java:97)
at org.lwjgl.Version.getVersion(Version.java:33)
at HelloWorld.run(HelloWorld.java:43)
at HelloWorld.main(HelloWorld.java:130)
This is because the Manifest object created by APIUtil does not include any attributes - but only in the built version by Maven.
Why is this? Is my pom.xml buggy, or is LWJGL 3.0.0 just not ready for this?
This is my pom.xml:
<properties>
<mainClass>HelloWorld</mainClass>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<finalName>${project.artifactId}-${project.version}.jar</finalName>
</properties>
<dependencies>
<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl-platform</artifactId>
<version>3.0.0</version>
<classifier>natives-windows</classifier>
</dependency>
<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl-platform</artifactId>
<version>3.0.0</version>
<classifier>natives-linux</classifier>
</dependency>
<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl-platform</artifactId>
<version>3.0.0</version>
<classifier>natives-osx</classifier>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>${mainClass}</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
This errors happens because LWJGL 3.0.0 is looking inside the Manifest a property called "Implementation-Version", but when you made the uber-jar, this property was not set.
This is not really an issue with how you made the uber-jar: the Manifest that was created by maven-assembly-plugin looks like:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: Me
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_102
Main-Class: HelloWorld
You can see it inside META-INF/MANIFEST.MF of the jar-with-dependencies. This file does not have a "Implementation-Version" property. This is normal: when this executable JAR was created, all the MANIFEST of all dependencies were (rightfully) ignored, only to generate one containing the "Main-Class", just so that the JAR is executable.
The uber-jar cannot contain what is inside each of the dependencies manifest. For example, "Implementation-Version" is a property that is present in the manifest of multiple libraries, so which one should it keep? (There can be only one Manifest at the end, in the uber-jar). So the issue comes up because we're making an executable JAR, which can only have 1 Manifest so it cannot aggregate all the properties inside each of the dependencies manifest.
There are 2 possible solutions:
Ignore it. After all, this is not really an error.
Don't make an executable jar by embedding all the dependencies inside a single JAR, but create a ZIP assembly with each dependencies inside a lib folder: this way, each Manifest will be kept. This is done by telling the maven-jar-plugin to add a Manifest entry for the main class with the addition of the classpath and creating a custom assembly descriptor.
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<mainClass>${mainClass}</mainClass>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptors>
<descriptor>/path/to/assembly.xml</descriptor>
</descriptors>
</configuration>
</plugin>
where /path/to/assembly.xml is the path to the assembly descriptor, relative to the location of the POM, being:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>dist</id>
<formats>
<format>zip</format>
</formats>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
</dependencySet>
</dependencySets>
</assembly>
With such a configuration, running mvn clean install will create a ZIP file artifactId-version-dist.zip. Unpacking it and running (replacing <finalName> with the finalName of your JAR)
java -jar lib\<finalName>.jar
will print the version without any issues.

Categories