Outsource java packages for reuse in other projects with gradle - java

Ive got an Project an within it,I developed a bunch of classes wich is kept very abstract so I could use it in other projects. How should I outsource the package in a way so I can include it via gradle or by the IDE in the end?
Also the reusable packag-content is still in development so I want do work on it in paralelle.
Can anybody tell me how to solve this?

In your build.gradle use a custom build to collect only the package that you want
task customBuild(type: Jar) {
from ("src/main/java/abstract/"){
into "abstract"
}
version = ""
baseName = "myClasses"
}
it will build you a jar file inside build/libs/YouJarName
Now you can copy the jar to anywhere you want, and include it in another project in that way :
dependencies {
compile fileTree (dir : "your/jar/location", includes: ["myJar.jar"])
}

Related

Gradle + Eclipse : use class from existing project in a new project

I know there are a lot of questions that seem similar. I have also spent a few hours getting to grips with Gradle multiprojects. But I still don't understand what the best course of action is here. Incidentally I am using Groovy as my coding language, but explanations referencing Java would be just as good.
I have developed an Eclipse Gradle project, "ProjectA", which in particular has a class, IndexManager, which is responsible for creating and opening and querying Lucene indices.
Now I am developing a new Eclipse Gradle project, "ProjectB", which would like to use the IndexManager class from ProjectA.
This doesn't really mean that I would like both projects to be part of a multiproject. I don't want to compile the latest version of ProjectA each time I compile ProjectB - instead I would like ProjectB to be dependent on a specific version of ProjectA's IndexManager. With the option of upgrading to a new version at some future point. I.e. much as with the sorts of dependencies you get from Maven or JCenter...
Both projects have the application plugin, so ProjectA produces an executable .jar file whose name incorporates the version. But currently this contains only the .class files, the resource files, and a file called MANIFEST.MF containing the line "Manifest-Version: 1.0". Obviously it doesn't contain any of the dependencies (e.g. Lucene jar files) needed by the .class files.
The application plugin also lets you produce a runnable distribution: this consists of an executable file (2 in fact, one for *nix/Cygwin, one for Windows), but also all the .jar dependencies needed to run it.
Could someone explain how I might accomplish the task of packaging up this class, IndexManager (or alternatively all the classes in ProjectA possibly), and then including it in my dependencies clause of ProjectB's build.gradle... and then using it in a given file (Groovy or Java) of ProjectB?
Or point to some tutorial about the best course of action?
One possible answer to this which I seem to have found, but find a bit unsatisfactory, appears to be to take the class which is to be used by multiple projects, here IndexManager, and put it in a Gradle project which is specifically designed to be a Groovy library. To this end, you can kick it off by creating the project directory and then:
$ gradle init --type groovy-library
... possible to do from the Cygwin prompt, but not from within Eclipse as far as I know. So you then have to import it into Eclipse. build.gradle in this library project then has to include the dependencies needed by IndexManager, in this case:
compile 'org.apache.lucene:lucene-analyzers-common:6.+'
compile 'org.apache.lucene:lucene-queryparser:6.+'
compile 'org.apache.lucene:lucene-highlighter:6.+'
compile 'commons-io:commons-io:2.6'
compile 'org.apache.poi:poi-ooxml:4.0.0'
compile 'ch.qos.logback:logback-classic:1.2.1'
After this, I ran gradle jar to create the .jar which contains this IndexManager class, initially without any fancy stuff in the manifest (e.g. name, version). And I put this .jar file in a dedicated local directory.
Then I created another Gradle project to use this .jar file, the critical dependency here being
compile files('D:/My Documents/software projects/misc/localJars/XGradleLibExp.jar' )
The file to use this class looks like this:
package core
import XGradleLibExp.IndexManager
class Test {
public static void main( args ) {
println "hello xxx"
Printer printer = new Printer()
IndexManager im = new IndexManager( printer )
def result = im.makeIndexFromDbaseTable()
println "call result $result"
}
}
class Printer {
def outPS = new PrintStream(System.out, true, 'UTF-8' )
}
... I had designed IndexManager to use an auxiliary class, which had a property outPS. Groovy duck-typing means you just have to supply anything with such a property and hopefully things work.
The above arrangement didn't run: although you can do build and installdist without errors, the attempt to execute the distributed executable fails because the above 6 compile dependency lines are not present in build.gradle of the "consumer" project. When you put them in this "consumer" Gradle project's build.gradle, it works.
No doubt you can add the version to the generated .jar file, and thus keep older versions for use with "consumer" projects. What I don't understand is how you might harness the mechanism which makes the downloading and use of the dependencies needed by the .jar as automatic as we are used to for things obtained from "real repositories".
PS in the course of my struggles today I seem to have found that Gradle's "maven-publish" plugin is not compatible with Gradle 5.+ (which I'm using). This may or may not be relevant: some people have talked of using a "local Maven repository". I have no idea whether this is the answer to my problem... Await input from an über-Gradle-geek... :)
You should be able to update the Eclipse model to reflect this project-to-project dependency. It looks something like this (in ProjectB's build.gradle):
apply plugin: 'eclipse'
eclipse {
classpath.file.whenMerged {
entries << new org.gradle.plugins.ide.eclipse.model.ProjectDependency('/ProjectA')
}
project.file.whenMerged {
// add a project reference, which should show up in /ProjectB/.project's <projects> element
}
}
These changes may be to the running data model, so they may not actually alter the .classpath and .project files. More info can be found here: https://docs.gradle.org/current/dsl/org.gradle.plugins.ide.eclipse.model.EclipseModel.html
This issue is discussed here: http://gradle.1045684.n5.nabble.com/Gradle-s-Eclipse-DSL-and-resolving-dependencies-to-workspace-projects-td4856525.html and a bug was opened but never resolved here: https://issues.gradle.org/browse/GRADLE-1014

Gradle - one project, multiple packages, multiple jars

I'm asking you about a very basic question but I hope you can find the time to help me:
I'm trying to realise a java-project, that can spit out several different programs which partially have dependencies on other projects of mine.
In order to keep it simple, I want to have all the code in one project, run by Gradle, so if I make changes to a central library (the database connector for example) all the child-programs automatically recieve the changes.
An example could look like this:
project:
program_A
central_library
program_B
output:
program_A.jar (including central library)
program_B.jar (including central library)
Now I'm having serious troubles finding a correct buildscript for this and was wondering if someone here could help me out.
P.S. : Since I'm new to this, if I should realize this through different modules within the Gradleproject instead of different packages in the Gradleprojects sourcefile, feel free to tell me :)
One way to approach this is to have a root project, that holds the three other projects inside of it.
Specify the sub-projects inside its settings.gradle file:
rootProject.name = 'RootProject'
include 'program_A'
include 'central_library'
include 'program_B'
With this in place, program_a can depend on central_library by adding a dependency in its build.gradle:
dependencies {
compile project(':central_library')
}
I have a similar setup in one of my projects, although the "central library" is the root project and the submodules are test environments.
Create a root directory and put each library or program into its own sub-directory.
Create a gradle project in each subproject.
You can for example create a skeleton gradle project by running
gradle init --type=java-library
or
gradle init --type=java-application
Then in the root directory create a gradle multi-module project. Basically
run only
gradle init
and then create a settings.gradle and list all sub-projects there.
This is actually described very well in the gradle documentation:
https://guides.gradle.org/creating-multi-project-builds/
If I understand correctly, what you want to do is, when you change your local projects, you want other projects to see those details. For this you need to publish your projects to some kind of repo, like maven repo. You can do this from command line gradle publishToMavenLocal, or gradle build pTMl. You can also do this in build.gradle file with something like the following:
task sourceJar (type : Jar) {
classifier = constants.extSources
from sourceSets.main.allSource
}
publications {
mavenJava(MavenPublication) {
from components.java
artifact(sourceJar) {
classifier "sources" //classifier = constants.extSources
}
}
}

How to include subproject classes in jar?

After hours of researching and trying I hope that someone can explain how we can have Gradle including classes of one or more subproject into a specific jar.
Lets say we have just three modules
Core
App
Web
Obviously the App and Web project artifacts (jars) should contain all classes from the Core project.
Settings gradle:
rootProject.name = 'MyProject'
include 'MyProjectCore'
include 'MyProjectApp'
include 'MyProjectWeb'
MyProjectApp / MyProjectWeb:
...
dependencies {
...
compile project(':MyProjectCore')
}
The projects can be compiled but the output jars do not contain the core classes.
Okay finally I found a working solution even if it might not be the best.
For the App and Web projects I overwrite the jar task like this to add the source sets of the Core module.
jar {
from project.sourceSets.main.allSource
from project(":MyProjectCore").sourceSets.main.java.srcDirs
}
With this you can add all *.class files created in your subprojects into your jar automatically:
jar {
from {
subprojects.collect { it.sourceSets.main.output }
}
}
To make sure the .class are there, make sure the root project depends on the subprojects:
dependencies {
compile project(':mySubProject')
}

Gradle Jar - Include dependencies' classes

I'm working on a server application and using gradle for this. If i run "bundle", gradle creates a jar file which includes all compiled java classes of my project. But, obviously, you cannot run this jar because of the missing dependencies.
I currently these own task:
task bundleJar(type: Jar) {
manifest {
attributes 'Main-Class': 'your.own.start.main.class'
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
But this includes "ALL" dependencies classes. It is possible to integrate only classes which are needed by my application? Are they any problems with reflections?
Another thing I thought about. Some libraries disallow to ship them in another application. So I only provide the source code to my users. They download it and execute the gradle task. This should be ok, shouldn't it?
Is it better to bunld eeverything in one jar, or is it possible to create a seperate folder for needed classes?
Thx:)
In your example, you do configurations.compile.collect so you will zip everything from the compile scope. you could change that with the class declared from your runtime scope (configurations.runtime.collect). sure it would mean that those classes have already been downloaded when you are doing the build.

How do you create additional jar artifacts from compiled classes using Gradle?

I can't tell if this is a bug with Gradle 1.0m7, or if we are just doing this wrong.
We have some classes that get compiled as apart of a project, that we want to individually jar into it's own artifact. These are for example standalone domain model objects, that we want to share with another project.
I'd prefer not to go the multi-project build route, so how do we tell Gradle to create another jar for these?
Currently we are doing this:
task modelJar(type: Jar) {
classifier = 'model'
from fileTree(dir: sourceSets.main.classesDir).matching { include 'com/foo/bar/model/**' }
}
artifacts {
archives modeljar
}
The issue here, is the modeljar task runs before the classes are compiled. At first we didn't realise this and thought this was working. Turns out, the artifact was picking up classes from the previous run, not the current run. Doing clean before the build results in a jar with no classes in it, and reveals the problem.
I was looking at custom configuration, but it seems pretty complex and I didn't want to overly complicate the build file.
Appreciate any advice.
Thanks.
the most convenient way to do this is
task modelJar(type: Jar) {
classifier = 'model'
from sourceSets.main.output
include 'com/foo/bar/model/**'
}
Some background:
sourceSets.main.output is a buildable filecollection. This means that if a task works with this file collection, gradle knows that this file collection must be created before another task can use it. in this particular case, sourcesets.main.classes is wired to the classes task of the java plugin. Therefore you your modelJar task does not need to depend on the classes task explicitly.
How about making modelJar task depend on classes (built-in) task? This should make sure compilation is done before modelJar task.
task modelJar(dependsOn: classes, type: Jar){
...

Categories