How to use dependencies from a jar file? - java

I am trying to import a jar file and to use its dependencies into a Maven project.
The jar file I want to import is itself another Maven project and includes all of the dependencies of it.
I managed to import my jar file and to use the java code (from my packages in src/main in the Maven project jar file) but the project where I imported mt jar file still does not recognize the dependencies of the jar.
For example, I am trying to import org.json.JSONObject (whom dependency is defined in the jar file) but there is a compiling error.
Is there any way to do what I want or any other solution ?
Thank you !
(Sorry for the bad level of explanation, I am French and it is quite hard form me to explain in details my problem)
EDIT
Here are samples of my pom from my jar file :
<!-- One of the dependency I want to use -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20160212</version>
<scope>test</scope>
</dependency>
<!-- The plugin I used to create my jar file with dependencies -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2</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>
I then included the jar file using an "in-project" repository as explained here : http://charlie.cu.cc/2012/06/how-add-external-libraries-maven/
The error message is a compiling error message saying that the org.json.JSONObject is not recognized :
package org.json does not exist

You add the json lib only for test scope.
Remove the scope and the error should gone.
<!-- One of the dependency I want to use -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20160212</version>
</dependency>

Related

maven-jar-plugin: How to create a different artifact name for tests?

Let's say that I put the following plugin in my pom.xml file:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>make-a-jar</id>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<finalName>my-artifact-name</finalName>
</configuration>
</execution>
</executions>
</plugin>
and I run "mvn clean install".
Maven creates two jar files in target library.
The first jar file compiles the source files and the second jar compiles the test files. Both of these jar will have the same artifact name.
If I want to use the jar of source code as a dependency in another project, I can put the following dependency in the other project:
<dependency>
<groupId>groupId</groupId>
<artifactId>my-artifact-name</artifactId>
<scope>system</scope>
<type>jar</type>
<systemPath>${basedir}/lib/my-artifact-name.jar</systemPath>
</dependency>
So far so good.
A problem arises if I also want to add a dependency for the test files. In this case I will have two dependencies with the same groupId and artifactId and different systemPath. Maven will not read two dependencies with same groupId and artifactId. Only one of them will be read.
One solution that I can think of is to make Maven to give a different artifact name for test.
Do you know how to do it?
My general answer to that would be:
The tests in src/test/java are only for running them during the build. They need not be put into any jar.
If you need classes as helper classes for your tests, you can create a separate jar which contains these classes. This can then be used as test dependency.
In any case, try to avoid <systemPath>. If you build your project with mvn clean install on your computer, you can reference the resulting jar with a dependency like
<dependency>
<groupId>groupId</groupId>
<artifactId>my-artifact-name</artifactId>
<version>1.2.3</version>
</dependency>
anywhere on the same account/computer without giving a <systemPath>.

neo4j procedure depending on signed jar (mapdb)

I have created a neo4j user-defined procedure. It also compiles and works in neo4j.
Recently though, I added a dependency to my procedure plugin that prevents neo4j from starting when I try to run the newly built jar. Concretely, I receive following exception at the bottom of the stack trace:
Caused by: java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
The only thing I changed is to add MapDB to my dependencies. So I suspect that it depends on some signed artifact. As it turns out neo4j plugins are "uber-jars" (i.e., shaded jars) which doesn't work very well with signed dependencies.
I figured I could try to exclude MapDB from the shading by changing the scope to provided and additionally adding the mapdb jar to plugins folder of neo4j. So the plugins folder of neo4j now includes both mapdb.jar and myprocedure.jar.
This doesn't seem to work though: neo4j starts, but when calling my procedure I receive a ClassNotFound Exception.
Any ideas on how I can solve this dilemma? I really depend on something like MapDB as my graph is very large and keeping everything in my procedure in-memory regularly leads to memory exceptions.
Many thanks in advance!
The important part of my pom.xml should it help (I started off with the procedure template so it still looks quite similar):
<dependencies>
<!-- other dependencies that don't make a difference ... -->
<dependency>
<groupId>org.mapdb</groupId>
<artifactId>mapdb</artifactId>
<version>3.0.7</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>${neo4j.version}</version>
<scope>provided</scope>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>org.neo4j.test</groupId>
<artifactId>neo4j-harness</artifactId>
<version>${neo4j.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>1.4.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<!-- Neo4j Procedures require Java 8 -->
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<!-- This generates a jar-file with our procedure code,
plus any dependencies marked as `compile` scope.
This should then be deployed in the `plugins` directory
of each Neo4j instance in your deployment.
After a restart, the procedure is available for calling. -->
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
So, one solution that worked was to use the maven-assembly-plugin instead of the maven-shade-plugin. The assembly plugin creates a standalone jar with all dependencies without re-packaging all dependencies.
Of course, I had to remove the <scope>provided</scope> for mapdb so it is also included in the assembled jar.
The rest is just replacing the shade plugin with following snippet (thanks to this question here):
<plugin>
<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>
</configuration>
</plugin>
Afterwards I received another exception which I thought was due to a wrong signature:
Caused by: java.lang.VerifyError ...
Turns out this was just because I had another procedure in neo4j that uses the same dependencies as mapdb. Quick fix was to remove that procedure library.
Of course, there are also other solutions, including removing the signature, or re-signing it. However, I explicitly did not want to remove any signatures.
I'm not aware that neo4j is checking any jar signatures by default. I suspect the repackaging of mapdb artifact being the culprit.
To validate that, remove the shade or assembly plugin in and build a jar that solely contains your code. Copy that jar and the mapdb.jar into the plugin folder and observe logs during a restart.

Importing testng classes when scope marked 'test'

I have a testng dependency in pom.xml with 'test' scope:
</dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
My folder layout is as follows:
src/test/java - test source folder
src/test/resources - test resources folder
When trying to import testng in classes created under src/test/java/ IntelliJ can not find testng.
First of all open Maven Projects tab and simply refresh to get in sync.
Secondly, open the project structure and check if your sources are marked correctly.
Without more info, this is what I would suggest.
I suspect you have src/test/java in one module/project and you would like to reuse it in other module/project? If that's correct you need to build and install your test jar (add to your source project):
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Then you can use it in other projects by adding maven dependency.

Maven: How do I get .so libraries bundled in package

I have a third party library coming with .jar and .so file.
I configured pom.xml as following:
<dependency>
<groupId>com.abc.def</groupId>
<artifactId>sdc</artifactId>
<version>1.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.abc.def</groupId>
<artifactId>sdc</artifactId>
<version>3</version>
<scope>compile</scope>
<type>so</type>
</dependency>
With this configure, I successfully tested through Intellij and apk file under target contains structure like lib/armeabi/sdc.so
However, after I do mvn clean package, the apk file generated did not contain sdc.so file, and after installing apk file on android device, lib folder is empty.
Searching through the internet, and did not find answer.
Btw, I do add <nativeLibrariesDirectory>${project.basedir}/libs</nativeLibrariesDirectory> into pluginManagement as mentioned Native libraries (.so files) are not added to an android project, but does not help.
Updates:
If someone is facing same problem as I am that SO file did not copy over, please try manually copy the so file over as following:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<id>copy</id>
<phase>prepare-package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.abc.def</groupId>
<artifactId>libdef</artifactId>
<version>2.1.3</version>
<type>so</type>
<destFileName>libdef.so</destFileName>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/libs/armeabi</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
I suggest you to use maven-android-plugin version 2.8.3 or more.
The scope of your native lib must be runtime (not sure it is required, but anyway it's a fact)
The artifactId must start with lib (i.e. it must be libsdc)
<dependency>
<groupId>com.abc.def</groupId>
<artifactId>libsdc</artifactId>
<version>3</version>
<scope>runtime</scope>
<type>so</type>
</dependency>
The artifactId will be the library name so load it with this line of code
System.loadLibrary("sdc");
reference
Note: I don't know if sdc if the real artifactId, but if it's the case you must consider re-publishing it with the lib prefix.
I would suggest looking into the Assembly plugin: http://maven.apache.org/plugins/maven-assembly-plugin/ I have not used it in any Android project yet, but I do use it in my regular java server projects which require non-maven items be in expected locations.

How to setup Maven dependencies between test folders in two projects?

I have a project setup like this:
parent
|_____project-a
|_____project-b
I want classes in the test folder of project-b to resolve classes in the test folder of project-a.
Actually, I want to access both classes from the main folder and stuff from the test folder.
Is this possible?
Thanks
You can build project A with the goal test-jar
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
Then include it with type test-jar in project B:
<dependency>
<groupId>com.example</groupId>
<artifactId>project-a</artifactId>
<type>test-jar</type>
<version>1.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
Since content of test folder is not included into target for project it cannot be used outside.
The best way i think is to move common classes to project like 'project-testcommons' and use it in project-a and project-b with 'test' scope.

Categories