I have a project structure, where I have some basic projects, where all the features are implemented and on top of that some projects for different kinds of usage/deployment as follows:
foo-core
foo-production, depends on foo-core (produces a war file and i delivered to customers)
foo-standalone, depends on foo-core (produces a war used for internal testing)
foo-ui-test, depends on foo-core (UI tests with Arquillian+Selenium)
Now I have a rising number of classes that are useful for foo-standalone and for foo-ui-test, but I don't want to deploy these classes to the customer. Therefore foo-core is out as a possible project where to store these classes. The two remaining options are:
A new project foo-helper which depends on foo-core and make foo-standalone and foo-ui-test depend on foo-helper instead of foo-core.
Make foo-ui-test depend on foo-standalone
I'd like to go for option 2 as I already have a lot of projects. The remaining problem for option 2 is that both of these projects (foo-standalone and foo-ui-test) have a Spring WebApplicationInitializer...
Now I fiddled around with my build system (I use gradle) and was able to exclude the WebApplicationInitializer in the foo-standalone project and only explicitly include it when building the foo-standalone.war file.
The resulting build.gradle file for foo-standalone seems "hackish" and will break if I rename or move the WebApplicationInitializer class. I wonder, if there is another way to achieve what I'm looking for or if I have to make a new project.
Update
I moved the WebApplicationInitializer class from src/main/java to src/init/java and changed the build.gradle of foo-standalone as follows:
sourceSets {
init {
java {
compileClasspath += sourceSets.main.runtimeClasspath
}
}
}
war {
classpath sourceSets.init.runtimeClasspath
}
I guess that's the shortest, custom way to do this, or is there any built-in gradle functionality which does this?
Maven will only allow you to have a dependency to a JAR project. There is a feature where you can have war overlays, where one war project extends a child and overrides certain bits (see https://maven.apache.org/plugins/maven-war-plugin/overlays.html) this seems the relationship between your foo-standalone and foo-ui-test.
So make foo-helper a war project and make foo-standalone, foo-ui-test and foo-production extend it using war overlays.
foo-core can stay as a jar, if there are non-production bits create a foo-core-internal to depend on foo-core and ring fences the internal/test bits.
Related
Suppose I have one set of Java sources in the standard repository layout (ie. src/main/java). Now suppose I want to create two jars from this set of sources - one each using the classes produced from two different JavaCompile tasks that are configured differently. For example, I might have something like this:
tasks.named('compileA', JavaCompile).configure {
// one set of toolchain and options settings here
}
tasks.named('compileB', JavaCompile).configure {
// a different set of toolchain and options settings here
}
The question is, is it better to just have the main source set (supplying the compileA equivalent, and thus the jarA equivalent, for free) and commission compileB (and jarB) separately, or have two separate source sets, one each for compileA/jarA and compileB/jarB? What if I needed something like a war, where I need the source set's runtime classpath? Is there a way that I can make a warA and warB, where they each only have the classes from one or the other compile task?
Additionally, suppose that I have a multi-project build, where multiple projects have this compileA/compileB setup, and there are project dependencies between the subprojects. What else would I need to do in order to make it so that we end up with a jar that only consists of classes compiled using the various compileA tasks, and a different jar that only consists of classes compiled using the various compileB tasks?
How can we create a Maven test jar with Java 11 modules?
The only way I found is to add a module-info.java file to test/java and change the module name (e.g. append ".test"). Then provide the class in a separate package (e.g. append ".test") and export that package:
module my.module.test {
requires my.module;
exports my.module.test;
}
Otherwise the classes are not visible or I get split package issues.
But this isn't really the purpose of the test-jar goal and it limits access to "my.module".
What is the proper way to use test-jar with Java 11 modules? Or should it be avoided?
In my projects, I need to import third party jar file and Facebook SDK.
compile files('libs/SkinSDK.jar')
compile 'com.facebook.android:facebook-android-sdk:4.14.0'
Both include same BundleJSONConverter class. So, I cannot do generate signed APK. It always shows duplicate entry com/facebook/internal/BundleJSONConverter.
So, I want to exclude in Facebook or SkinSDK.jar. I tried like
compile ('com.facebook.android:facebook-android-sdk:4.14.0') {
exclude group: 'com.facebook.internal', module: 'BundleJSONConverter'
}
It's not working and showing same error.
The exclude method of the configuration closure for a dependency excludes transitive dependencies. So, if your module dependency depends on other modules, you can exclude them from your build. You can check out the transitive dependencies of the 'com.facebook.android:facebook-android-sdk:4.14.0' module on its Maven repository info page.
If the BundleJSONConverter class exists in a transitive dependency, you can exclude the specific module in the same way you are trying now. Just specify the group, the module and the version, like you do for dependencies.
If you just want to exclude one class for a dependency jar, take a look at the jar jar links tool and its Gradle plugin. It allows you to alter included jars, e.g. to change packages or remove classes.
The following (shortened) example shows the usage of the plugin and some methods to alter the dependency jar:
compile jarjar.repackage {
from 'org.apache.hive:hive-exec:0.13.0.2.1.5.0-695'
archiveBypass "commons*.jar"
archiveExclude "slf4j*.jar"
classDelete "org.apache.thrift.**"
classRename 'org.json.**', 'org.anarres.hive.json.#1'
}
Bumped into similar situation. This is what I did, not elegant as I hoped, but it works:
Rename the jar file (SkinSDK.jar in your case): .zip instead of .jar
Go "inside" the zip file (I'm using DoubleCommander, there are many other utilities for that), or extract it to a temporary folder.
Delete the duplicate class that causes the problem. Go "outside" the zip file.
Rename (or re-pack) the file from .zip to .jar . Compile.
Hope it works...
I had a similar problem with duplicated classes after importing a jar. In my case, the conflict was between a class in that jar and a class in my own project.
Below I share the solution you can use to discard classes that you have available in your own source tree, assuming the one in the jar is the right one to use:
android {
sourceSets {
main {
java {
filter.excludes = [
"com/package/Duplicated.java",
]
}
}
}
}
I need to make analyzing only root project, and ignore nested sub module, but it d
So I have this hierarchy:
ProjectMain
-src
-subProjectAngular
settings.gradle
My configuration settings.gradle
rootProject.name="ProjectMain"
include 'subProjectAngular'
I need to make analyzing only root project, and ignore nested sub module, but I got:
A multi-module project can't have source folders, so 'C:\Users\vagrant\develop-2\site\Source\Site\Vessels\src\main\java' won't be used for the analysis. If you want to analyse files of this folder, y
ou should create another sub-module and move them inside it.
Then I tried to add multi module configuration:
systemProp.sonar.projectKey=site
systemProp.sonar.projectName=vessels-test
systemProp.sonar.projectBaseDir=.
systemProp.sonar.sources=src
systemProp.sonar.modules=javamodule, angularmodule
systemProp.javamodule.sonar.projectName=vessels
systemProp.javamodule.sonar.sources=src
systemProp.javamodule.sonar.projectBaseDir=.
systemProp.javamodule.sonar.language=java
systemProp.angularmodule.sonar.projectName=angular
systemProp.angularmodule.sonar.projectBaseDir=.
systemProp.angularmodule
but got message at UI: no analysis has been performed
It's only works when I remove definishion of subproject from settings.gradle, and remove all submodule confguration
This configuration is not support yet in SonarQube.
But the good news is that this will change with SonarQube 6.4 (expect in early May 2017). See the following tickets:
SONAR-6724
SONARGRADL-5
A project runs on Google App Engine. The project has dependency that uses a class that can't be invoked on App Engine due to security constraints (it's not on the whitelist). My (very hacky) solution was to just copy a modified version of that class into my project (matching the original Class's name and package) that doesn't need the restricted class. This works on both dev and live, I assume because my source appears in the classpath before my external dependencies.
To make it a bit cleaner, I decided to put my modified version of that class into it's own project that can be packaged up in a jar and published for anyone else to use should they face this problem.
Here's my build.gradle:
// my jar that has 'fixed' version of Class.
compile files('path/to/my-hack-0.0.1.jar')
// dependency that includes class that won't run on appengine
compile 'org.elasticsearch:elasticsearch:1.4.4'
On my local dev server, this works fine, the code finds my hacked version of the class first at runtime. On live, for some unknown reason, the version in the elasticsearch dependency is loaded first.
I know having two versions of the same class in the classpath isn't ideal but I was hoping I could reliably force my version to be at the start of the classpath. Any ideas? Alternatively, is there a better way to solve this problem?
Not really sure if this is what people visiting this question were looking for, but this was what my problem and a solution that I reached at.
Jar A: contains class XYZ
Jar B: also contains class XYZ
My Project needs Jar B on the classpath before Jar A to be able to get compiled.
Problem is Gradle sorts the dependencies based on alphabetical order post resolving them which meant Jar B will be coming after Jar A in the generated classpath leading to error while compiling.
Solution:
Declare a custom configuration and patch the compileClasspath. This is how the relevant portion of build.gradle might look like.
configurations {
priority
sourceSets.main.compileClasspath = configurations.priority + sourceSets.main.compileClasspath
}
dependencies {
priority 'org.blah:JarB:2.3'
compile 'org.blah:JarA:2.4'
...
}
It's the app engine classloader I should have been investigating, not gradle...
App Engine allows you to customise the class loader JAR ordering with a little bit of xml in your appengine-web.xml. In my case:
<class-loader-config>
<priority-specifier filename="my-hack-0.0.1.jar"/>
</class-loader-config>
This places my-hack-0.0.1.jar as the first JAR file to be searched for classes, barring those in the directory war/WEB-INF/classes/.
...Thanks to a nudge in the right direction from #Danilo Tommasina :)
UPDATE 2020:
I just hit the same problem again and came across my own question... This time, live appengine was loading a different version of org.json than was being loaded in dev. Very frustrating and no amount of fiddling the build script would fix it. For future searchers, if you're getting this:
java.lang.NoSuchMethodError: org.json.JSONObject.keySet()Ljava/util/Set;
It's because it's loading an old org.json dependency from god-knows-where. I fixed it by adding this to my appengine-web.xml:
<class-loader-config>
<priority-specifier filename="json-20180130.jar"/>
</class-loader-config>
You'll also need a matching dependency in build.gradle if you don't already have one:
compile 'org.json:json:20180130'
According to gradle dependencies documentation, the order of dependencies defines the order in the classpath. So, we can simply put the libraries in the correct order in "dependencies".
But beware! here are two rules with higher priorities:
For a dynamic version, a 'higher' static version is preferred over a 'lower' version.
Modules declared by a module descriptor file (Ivy or POM file) are preferred over modules that have an artifact file only.