How to use a custom library in Maven? - java

I am working on a software that uses Maven. My friend who works with me on it recently added a IO-Lib which makes it easier to handle packets sent by Minecaft: Pocket Edition Click here to see the software I'm talking about But, since the jar is not on the Maven Repo, I can use dependency the normal way. Is there anyway to use a custom library not in the maven repo?
My pom.xml:
<project>
<?xml version="1.0" encoding="UTF-8"?>
<groupId>net.trenterprises.diamondcore</groupId>
<artifactId>DiamondCore</artifactId>
<version>0.1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.0-rc1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.0-rc1</version>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.11</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>
<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>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.5</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>net.trenterprises.diamondcore.run</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<organization>
<name>Trenterprises</name>
</organization>
</project>

If the custom jar file is not in maven central, the next best thing is for it to be in a different repo. If that's the case, you can add additional repository details to the pom.xml file and it will pull from both repos.
The second best thing is to use the "mvn install:install-file" target to manually install the binary into your cache. Then it will resolve in environments backed by your cache. If you have a build system that lives outside of your working environment, it gets just a little bit harder.
Assuming you have to make this work in multiple maven environments (not just your own) and you don't have a private repository, you need to create one. You can download various maven repository management systems (Artifactory, etc.) install them, and then configure your in-house repository the same way you would add a second out-of-house repository.
If setting up a repository server seems daunting to you, while it is far from a perfect solution, for a little while you can use the "mvn install:install-file" target to install the file in each local cache (but one typo or cache clear and it's going to be messed up in that cache)

You may want to add a system scoped dependency. have a look here:
https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope
it explains the various ways you can import a dependency. not all require the dependency be held in a repository.

I think this is what lhasadad was talking about, but to elaborate: I have used <scope>system</scope> and <systemPath>some/path/to.jar</systemPath> to point Maven at local jars successfully in the past. For example:
<dependency>
<groupId>org.apache</groupId>
<artifactId>kafka_2.8.2</artifactId>
<version>${kafka.version}</version>
<type>jar</type>
<scope>system</scope>
<systemPath>${basedir}/lib/kafka_2.8.2-${kafka.version}.jar</systemPath>
</dependency>

Related

Error: JavaFX runtime components are missing, and are required to run this application Using Intelij on Linux

I've recently decided to take the plunge and start programming on Linux but the transition has been rough.
I'm currently trying to get a JavaFX program to run properly in InteliJ and I keep getting an error for Error: JavaFX runtime components are missing, and are required to run this application
I've tried several of the proposed fixes that you can find on Stack Overflow, namely this one and this one along with the walk-through on Gluon's own website but nothing that I have tried so far is working.
For a brief overview, I'm using...
Java 17 (I don't remember why exactly anymore).
JavaFX 19 through Maven
InteliJ Idea Community
& Fedora Workstation
I know for a fact that the code itself is good because it is the exact same code that I used on my windows machine and it worked fine. The only thing I've changed in regards to the code is the pom.xml file for Maven where I finally added JavaFX as a dependency while getting things ready for the new OS.
This is the pom.xml file. I'm not an expert with maven but everything does appear to be correct as best I can tell.
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>LibraryDesktopApp</groupId>
<artifactId>LibraryDesktopApp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>LibraryDesktopAppProgram</name>
<description>This is the desktop program for the library software suite.</description>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>19</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>19</version>
</dependency>
<dependency>
<groupId>org.controlsfx</groupId>
<artifactId>controlsfx</artifactId>
<version>11.1.1</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<resources>
<resource>
<directory>src</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.mypackage.MyClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.8</version>
<executions>
<execution>
<!-- Default configuration for running with: mvn clean javafx:run -->
<id>default-cli</id>
<configuration>
<mainClass>LibraryDesktop/src.Main</mainClass>
<launcher>app</launcher>
<jlinkZipName>app</jlinkZipName>
<jlinkImageName>app</jlinkImageName>
<noManPages>true</noManPages>
<stripDebug>true</stripDebug>
<noHeaderFiles>true</noHeaderFiles>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
These are screenshots of various configuration screens.
Libraries
Modules
Configuration
I have tried running the program both with and without the VM arguments and neither worked.
Any help would be greatly appreciated! Thanks!
The entire project was converted over to a modular approach and I re-worked the pom.xml file too.
It was a bit of headache to get working but in addition to fixing my issue, the new setup is honestly much nicer than what I was dealing with before.
On the off chance that someone else needs help with this same issue, I'm attaching a link to a fairly straightforward setup very similar to what I'm using. It does the job of explaining the process far better than I could.

Use Spring Boot app as a dependency [duplicate]

I have a Spring Boot application and I have created a Jar out of that. Following is my pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- WebJars -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.6.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
I want to use this Jar in my other application so added this jar to my application. But when I am calling a method in that Jar, it is throwing a ClassNotFoundException.
How can I fix this issue? How can I add a dependency to a Spring Boot JAR?
By default, Spring Boot repackages your JAR into an executable JAR, and it does that by putting all of your classes inside BOOT-INF/classes, and all of the dependent libraries inside BOOT-INF/lib. The consequence of creating this fat JAR is that you can no longer use it as a dependency for other projects.
From Custom repackage classifier:
By default, the repackage goal will replace the original artifact with the repackaged one. That's a sane behaviour for modules that represent an app but if your module is used as a dependency of another module, you need to provide a classifier for the repackaged one.
The reason for that is that application classes are packaged in BOOT-INF/classes so that the dependent module cannot load a repackaged jar's classes.
If you want to keep the original main artifact in order to use it as a dependency, you can add a classifier in the repackage goal configuration:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.4.1.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
With this configuration, the Spring Boot Maven Plugin will create 2 JARs: the main one will be the same as a usual Maven project, while the second one will have the classifier appended and be the executable JAR.
Tunaki's answer is correct but doesn't work in Spring Boot 2.
Spring Boot 1.x
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.5.20.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
...
</plugin>
Read more
Spring Boot 2.x
If you are using spring-boot-starter-parent, the repackage goal is executed automatically in an execution with id repackage. In that setup, only the configuration should be specified as shown in the following example:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
...
</plugin>
Read more
For Spring Boot 2 #Tunaki's answer must be modified a bit according to the documentation if spring-boot-starter-parent is used as parent :
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
Take note of the extra <id>repackage</id> necessary to overwrite to execution from the spring-boot-starter-parent.
if you want to use the spring-boot project as a dependency and same time want to run as a spring-boot jar then use the below configuration. by the below configuration, you can achieve two goals.
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>build information</id>
<goals>
<goal>build-info</goal>
</goals>
</execution>
<execution>
<id>repackage</id>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
This configuration creates two jars as shown below example screenshot:
What #Tunaki stated was mostly correct but the one missing part based on your original question was:
This throwing ClassNotFoundException. The External jar's used in
spring boot application is missing.
This is due to the fact that the FatJAR created from the maven packaging has the dependent libraries specified in a specific location that works for how Spring Boot executes the application. If you are just adding the JAR to another application's classpath then you should do what #Tunaki said and also include the dependent JAR files to the classpath. The best way to work with this is to use the Maven Dependency Plugin specifically targetting the dependency:copy-dependencies mojo to download all the dependencies into a folder that you can then specify as a library path when compiling the other application.
You can extend your project by maven-assembly-plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
After the build you will get 3 jars. The main one will be the same as a usual Maven project, while the second one will have the classifier appended with exec and be the executable JAR. The third jar name will be appended by jar-with-dependencies and will contain your classes with classes added as dependencies in your spring boot application(spring-boot-starter-web, thymeleaf,...), so into the pom of the application where you want to add that project as dependencie you won't have to add dependencies from spring boot project.
Use the build section provided below, it will do three things:
Create the spring boot jar using spring-boot-maven-plugin
Create a normal jar with your source code compiled classes using maven-assembly-plugin
Install the normal jar into the m2 folder locally
If you want to deploy the normal jar into a remote repository, configure the deploy plugin
<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>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>true</appendAssemblyId>
<descriptors>
<descriptor>src/main/resources/sources-jar-build.xml</descriptor>
</descriptors>
<finalName>${pom.artifactId}-${pom.version}</finalName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<executions>
<execution>
<id>install-file</id>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${pom.artifactId}-${pom.version}</file>
<artifactId>${pom.artifactId}</artifactId>
<groupId>${pom.groupId}</groupId>
<version>${pom.version}</version>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Place the below content in a file named "sources-jar-build.xml", into resources folder:
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>sources</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>jar</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.basedir}/target/classes</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
use below plugin for spring boot version 2.*
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.1.RELEASE</version>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
All existing answers are made under the assumption that the Spring Boot project upon which another project should depend is an application, which is fair enough since the question is phrased like that.
But if the underlying project is meant to be used as a library only, i.e. it contains no (sensible) Main class, there is obviously no executable code that needs to be repackaged at all.
So in that case, it makes more sense to skip the repackaging entirely like this:
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
I used version 2.2.5 and it's working. add it to your pom.xml
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.5.RELEASE</version>
<executions>
<execution>
<id>repackage</id>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
You can setup your projects so that the batch launcher relies on a jar, which would be shared with your other application.
Said differently, as per your initial request :
I want to use this Jar in my other application so added this jar to my application.
Let's say your jar is your project A, and your application is your project B.
Now, what I suggest, is that you remove the launching part from A ;
then you put it into a new project C, that would embed Spring Boot, and that would rely almost totally on A.
Then, since A is now a simple jar, B can use it as a dependency.
any project if you want add as a dependency you need that project <groupId>,<artifactId>,<version>, with these details you can add your project as a dependency in another module or application
for ex: your application pom details
<project
<groupId>com.sample</groupId>
<artifactId>sampleapp</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
</project>`
your dependency as like below
<dependency>
<groupId>com.sample</groupId>
<artifactId>sampleapp</artifactId>
<version>1.0</version>
</dependency>

Not adding JARs to staging folder on Google Cloud when using Maven

I'm running integration tests on the cloud for the Google Cloud Dataflows that I have written; checking that they read from Pub/Sub and write to BigQuery correctly, but when using Maven (mvn clean install), the staging folder is not populated with the required JARs. The only JAR that appears is a surefirebooter.jar. As a result, I get a NoClassDefFoundError for PipelineOptions (most likely because it is the first class from a dependency that's trying to be referenced) in the Stackdriver logs, and consequently the tests fail. Since they're running on the cloud I am indeed using a DataflowRunner as opposed to a DirectRunner.
When I run the integration tests from my IDE they work fine; the staging folder is populated with all the JARs and all is well. Also, when I run the tests using Maven but with a DirectRunner the tests run successfully, thus my problem only occurs when using Maven and a DataflowRunner. I assume that problem therefore lies with the pom.xml file, which I have given below:
<?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>group</groupId>
<artifactId>artifact</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.google.cloud.dataflow</groupId>
<artifactId>google-cloud-dataflow-java-sdk-all</artifactId>
<version>2.0.0-beta3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.0.0-M3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>2.0.2-beta</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Anyone know why this is happening and how I may resolve it?
When staging files, the Dataflow runner will automatically stage the the classes available to the current class loader. I believe that surefire plays some tricks with the classloader to make the tests easier to run.
One option would be to specify filesToStage on the pipeline options, which will override the normal "detect JARs to stage from the class loader". Alternatively, look at how surefire is managing the classpath, and make sure the SDK JARs are available in the classloader the test is running in.

Maven/Spring private repository setup

Me and my team are pretty new to java side of things.
We have created a new rest service that uses spring framework.
We are trying to get the build automated.
We have our own repo that we want to go to find dependencies.
We put all third party dependencies in this repo and want the build to look into this repo while searching for dependencies.
Our pom.xml looks like this.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.retrofit</groupId>
<artifactId>retrofit</artifactId>
<version>1.9.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
For these spring dependencies what are all the jars we need?
How do I find out which jars should we be having in our repo so that we can build our project?
You will need to specify the repository to use in your pom file. As an example we use a Nexus repository where we put other jars needed. It also acts as a cache against the Central repositories so we don't need to explicitly include all of the jars that come from there.
You will need something like this in your pom.xml file:
<!-- location for other artifact uploads -->
<repositories>
<repository>
<id>YourRepositoryId</id>
<url>http://yourrepo.com/nexus/content/repositories/thirdparty/</url>
</repository>
</repositories>
Then your build automation will need a way to specify the user and password. In a regular Maven setup you would use your user settings.xml file and populate it somewhat like this. Different automated build systems may do it differently so you would need to see where yours gets it's Maven settings from.
<!-- This exists so that environments without a user can still access the repository. -->
<settings>
<servers>
<server>
<id>YourRepositoryId</id>
<username>yourUserName</username>
<password>yourPassword</password>
</server>
</servers>
</settings>
In regard to determine the jar files to use the Maven Dependency Plugin is a good tool for analyzing a working build to see what is included.
Hopefully this helps but if not feel free to ask any questions.
You can try something like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>${maven-dependency-plugin.version}</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/alternateLocation</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
This is part of the Apache Maven Dependency Plugin.
If you also want to get the sources:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>${maven-dependency-plugin.version}</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/alternateLocation</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
<execution>
<id>sources</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<classifier>sources</classifier>
<outputDirectory>${project.build.directory}/alternateLocation</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
And look into the alternateLocation folder. And of course you can change that folder to your preferenced location.

Log4j2 custom plugins - annotation processing with Maven Assembly Plugin

I am not very familiar with Maven, I started using it just yesterday, but I like it. In my project I use Log4j2 library for logging and because of insufficiecy of advanced plugins (like appenders, converters) I need to use custom plugins. log4j-api and log4j-core (also with a bunch of other libraries) are added as dependencies in pom.xml associated with my project. Actually I am using version 2.0 of Log4j.
Log4j uses annotation processing to pre-load classes marked as #Plugin. As far as I know, in older releases of log4j, additional plugin entry had to be specified in pom.xml to trigger plugin processing, or the packages with custom plugins had to be typed into the packages attribute in the configuration file (https://logging.apache.org/log4j/2.x/manual/configuration.html#ConfigurationSyntax). But this is not supported since 2.0-rc2.
In v2.0 this should be done automatically, as long as log4j-core is available to the building engine. There is a file Log4j2Plugins.dat in myproject-0.0.1-SNAPSHOT.jar/META-INF/org/apache/logging/log4j/core/config/plugins/ that contains mappings of my custom plugins - that's OK.
For building with Maven I use also Maven Assembly Plugin. Its goal single is binded to package phase. After packaging the project I naturally have one additional jar in the target directory - myproject-0.0.1-SNAPSHOT-jar-with-dependencies.jar. However, Log4j2Plugins.dat file in this jar contains mappings of original plugins, the same file as in the log4j-core library. And that's the problem, since it doesn't hold any references to my custom plugins. It seems that the file from myproject-0.0.1-SNAPSHOT.jar is being overwritten with the original file from the log4j library, but I am not sure what's the case.
So when I run myproject-0.0.1-SNAPSHOT-jar-with-dependencies.jar, log4j can't find the plugin classes from my project. I think that myproject-0.0.1-SNAPSHOT.jar would run ok, but I can't run it without the dependencies.
The packages attribute in configuration should be re-enabled in 2.0.1 release, but if I don't want to wait for the release, I have to use the annotation processing method.
Do you have an idea how to fix it?
I tried to run it with release 2.0-rc1 of log4j, where the packages attribute of the configuration element was usable. The result is: log4j successfully loaded the class of my custom plugin. However, there were so many other errors (that arised in this specific release) that make the program even more unusable.
This is one good point, that ensures me that if the packages attribute will be enabled in next release 2.0.1, my plugin will work. It should be reinstated according to this issue tracking: https://issues.apache.org/jira/browse/LOG4J2-741
Added my 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.jjurm</groupId>
<artifactId>twbot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>twbot</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.jjurm.twbot.system.Run</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.jjurm.twbot.system.Run</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>1.1.7</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>net.snaq</groupId>
<artifactId>dbpool</artifactId>
<version>6.0</version>
</dependency>
<dependency>
<groupId>org.fusesource.jansi</groupId>
<artifactId>jansi</artifactId>
<version>1.11</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>commons-jxpath</groupId>
<artifactId>commons-jxpath</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>2.15</version>
</dependency>
</dependencies>
</project>
I think the problem stems from packaging the dependencies into the jar. Doing a quick dive into the code, it looks like the plugin processor overwrites the plugin dat file for each set of plugins it handles. My guess is that during the packaging process, your custom plugins are processed and written to the dat file, and then overwritten when your log4j dependency is processed for inclusion in the package. There may be better solutions, but off the top of my head I would suggest that you do one of the following:
Do not package the dependencies into your jar. Just package your project and then include the dependencies on your classpath when you execute. Even if you want to package everything in a single portable jar, doing this would allow you to at least confirm if your plugins are being overwritten, or if there is something else wrong.
Create a separate project for your custom plugins, package it separately from your main project, and then include the resulting jar as a dependency. As with option 1, make sure that you do not include the log4j jars in this package. Once you have created your custom plugin jar, you can package it along with the other dependencies in your main jar and it should work fine since your custom plugin jar will have its own plugin dat file.
Good luck!
Another solution is mentioned in Log4j 2 issue 673. Use maven shade plugin with specific transformer instead of maven assembly plugin.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<configuration>
<transformers>
<transformer implementation="com.github.edwgiz.mavenShadePlugin.log4j2CacheTransformer.PluginsCacheFileTransformer" />
</transformers>
</configuration>
<dependencies>
<dependency>
<groupId>com.github.edwgiz</groupId>
<artifactId>maven-shade-plugin.log4j2-cachefile-transformer</artifactId>
<version>2.6.1</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
If I understand it accurately, transformer creates Log4j2Plugins.dat file by correctly merging Log4j2Plugins.dat from all dependencies and the main jar, i.e. all plugins will be included.

Categories

Resources