My Project
- moduleA
- moduleAPT
- moduleJ
Above is my project structure. The moduleA is a shared library module, and moduleJ is a java module that contains some annotation classes, and moduleAPT is an annotation processing tool module that handles moduleJ's annotation classes.
Both moduleA and moduleAPT have a dependence line in their build.gradle file like this:
api project(':moduleJ')
Now i want to publish the moduleA to jcenter. The problem is the generated aar file do not contains source files in moduleJ.
How to merge moduleJ's classes to moduleA's aar file when compiling.
You can use this library to package aar
fat-aar-android
I'm using it, it can merge multiple module
Related
My app has a module (lets call it myModule) which uses a 3rd party library(lets call it 3rdParty). This 3rdParty library is an aar file that uses a video compression library(lets call it videoCompressor). And myModule is also using the same compression library with the same version.
p.s. A module can't use aar file directly, so I had to put it in the app and use it in myModule as mentioned in this post.
So here is the dependency hierarchy
app
dependencies {
implementation(':myModule')
implementation(':3rdParty')
implementation 'videoCompressor:1.2.3'
}
myModule
dependencies {
api project(':3rdParty')
implementation 'videoCompressor:1.2.3'
}
3rdParty is an aar file and it also uses videoCompressor:1.2.3 internally.
While trying to build the project I get this error
Type com.abedelazizshe.lightcompressorlibrary.data.AtomsKt is defined multiple times: /Users/xx/Documents/xx/temp/xx/app/build/intermediates/mixed_scope_dex_archive/devDebug/out/d557fe27570a7fdcab8e1782ef61e44224719c80849bd367030f40a11145859c_1.jar:classes.dex, /Users/xx/Documents/xx/temp/xx/app/build/intermediates/mixed_scope_dex_archive/devDebug/out/23b9eb6594f48cb29b67fd834a2ea73b6ec11312577ac3867a8befdc5815129a_1.jar:classes.dex
This seems to be because there are duplicate classes from the videoCompressor library. How can this be fixed?
I tried removing videoCompressor from the app and myModule, build gets created but there is runtime crash about NoClassDefFoundError.
I'm trying to import a Gradle multi-project repository into another Gradle project as a git submodule.
This is the structure of the multi-project repo:
MyLibrary
- lib-api
- api-config
- api-repository
- lib-impl
- impl-config
- impl-repository
Within the Gradle project MyLibrary, there are several modules that depend on other modules within that project. For example, lib-api:api-repository has the following dependency:
implementation project(':lib-api:api-config')
(the modules under lib-impl also include their respective api as a dependency)
So far everything is ok, I can build, run and test the projects under lib-impl.
Now I try to import the project into another project
I use git submodule add to add MyLibrary to MyProject. This is now the structure:
MyProject
- MyLibrary
- lib-api
- api-config
- api-repository
- lib-impl
- impl-config
- impl-repository
- api
- impl
In order to be able to use the modules under MyLibrary, I edit the settings.gradle file in MyProject to look something like this:
rootProject.name = 'MyProject'
include 'api'
include 'impl'
include 'mylibrary'
include 'mylibrary:lib-api'
include 'mylibrary:lib-impl'
include 'mylibrary:lib-api:api-config'
include 'mylibrary:lib-api:api-repository'
include 'mylibrary:lib-impl:impl-config'
include 'mylibrary:lib-impl:impl-repository'
The problem
Now that the modules under MyLibrary belong to the root project MyProject, all the internal dependencies within MyLibrary need to be prefixed with :mylibrary. But this is only the case if MyLibrary is currently a submodule of another project.
In order to build MyProject, I need to change the dependencies inside MyLibrary from this:
implementation project(':lib-api:api-config')
implementation project(':lib-api:api-repository')
to this:
implementation project(':mylibrary:lib-api:api-config')
implementation project(':mylibrary:lib-api:api-repository')
However, :mylibrary needs to NOT be present for MyLibrary to compile successfully by itself (i.e. if MyLibrary is the root project). But this change IS required for MyLibrary to work as a submodule.
This used to not be a big problem as I could always pull the submodule MyLibrary and edit the necessary build.gradle files. However, I have now started trying to set up continuous integration and I get errors about those imports being invalid inside MyLibrary whenever I try to build MyProject as CI will always get the code directly from the git repo.
I feel like if the following statement was valid, it could fix my problem:
implementation project(':mylibrary:lib-api:api-config').ifNotPresent(':lib-api:api-config')
Thanks in advance for any help
After a brilliant revelation, I realized that java code was allowed inside of the build.gradle file so naturally I did this:
dependencies {
if (rootProject.getName().equals("MyLibrary")) {
implementation project(':lib-api:api-config')
} else {
implementation project(':mylibrary:lib-api:api-config')
}
}
And it works!
I'm working on a multi module spring-boot project to build a REST API. Here is my project structure:
Parent project (packaging is pom)
core module (#SpringBootApplication + handle path like / or /status)
restControllerA module (Handle path like /routeA/*)
restControllerB module (Handle path like /routeB/*)
Everything is working in this project :)
In another non Spring project I would like to reuse a service of restControllerB. This service return the result of the request body validation.
First I try to add the restControllerB.jar as a dependency to this new project... But this jar does not contain its depedencies (who are in the fatJAR "core.jar"). When I run the project, I get a lot of ClassNotFoundException.
How can I manage to reuse this service as a dependency ? I thought to create a validator module which implements the validatorService interface, but I'm not sure if it is the best solution.
After few hours googling, It seems that creating an external librairy is the right choice. I create an external module and add it as a dependecy to restControllerB.
I have some java9 module that uses 3rd party library that is not Java9 module, just a simple utility jar.
However, the compiler complains that it can't find a package from my utility.
What should I do in module-info.java to enable usage of my 3rd party library?
You can use your library as an automatic module. An automatic module is a module that doesn't have a module descriptor (i.e. module-info.class).
But what name do you need to specify to refer to an automatic module? The name of the automatic module is derived from the JAR name (unless this JAR contains an Automatic-Module-Name attribute). The full rule is quite long (see Javadoc for ModuleFinder.of), so for simplicity, you just have to drop the version from its name and then replace all non-alphanumeric characters with dots (.).
For example, if you want to use foo-bar-1.2.3-SNAPSHOT.jar, you need to add the following line to module-info.java:
module <name> {
requires foo.bar;
}
To put it in simple steps, to use a 3rd party jar (e.g. log4j-api-2.9.1.jar below) in your module:-
Execute the descriptor command of jar tool
jar --file=/path/to/your/jar/log4j-api-2.9.1.jar --describe-module
This would provide you an output similar to
No module descriptor found. Derived automatic module.
log4j.api#2.9.1 automatic
In your module descriptor file, declare a requires to that module name as:-
module your.module {
requires log4j.api;
}
That's it.
I'm currently writing a custom maven plugin for generating a XML file in a multi-module maven project.
My maven structure is pretty standard: one parent project and a module by project components in the parent project folder:
-- Parent
-- module A
-- module B
-- module C
I need to list, by module, a set of classes flagged by a custom annotation.
I already wrote a set of custom annotations and an annocation processor to create a XML file at compile time in the corresponding module output directory (${project.build.outputDirectory}) .
Now i need to merge each module XML into one file, but i don't know how to access each modules from within my maven plugin except having each path set as parameters (i don't like this method).
Any idea on how to do this ?
Does maven plugins can traverse project modules ?
Thank you in advance.
To get the list list of all projects you can use:
List<MavenProject> projectList = MavenSession.getProjectDependencyGraph().getSortedProjects()
If one of your goals is correctly executed you will get everything you need. Every MavenProject contains a getBaseDir() etc.
After some researches, it seems that MavenProject.getCollectedProjects() will return the list of projects beeing manipulated by a goal execution in a multi-module project.