Create multi Jar by for loop task call with gradle - java

In my project, there is a package com.fool.bar.names
under this package, I have 'tom', 'jerry', 'black', 'john' and many names...
I want to for loop the names package directory, and package tom.jar,jerry.jar,black.jar...
I use ant for now, An ant target call another target works well and simple.
But this project need migrate to gradle
I tried to use task call other task, but always got could not find method with arguments []
I tried to define my own task class to resolve the error, but my owner task class could not use the Jar task.
PlZ, anybody can help...

If the classes inside each package (tom, jerry, black, ...) independent of each other, then the easiest way would be to create subprojects (modules) for each of these, and put only the corresponding packages into each module. If you do this, and apply the java plugin to each module, then you don't need to write any special tasks with filtering, just run the jar task for the whole project, and you're basically done.
If there are dependencies between the packages, (but not circular) then you just have to make the modules depend on each other.
Is there any particular reason for keeping these packages in the same module?

Related

How can I have separate debug and release versions of gradle project that pull in different versions of the same class?

I have two versions of the same Java class (same name / methods). Since it's Java, both .java files have the same name. I want to configure gradle in such a way that I can build a "debug" version of my application that pulls in one of these files, and a "production" version of my application that pulls in the other one. How would I go about doing this?
This class has only static methods. I don't ever want to make an instance of this class. I additionally don't want to add the overhead of an if statement in each of the methods on this class to check which version I'm in.
Following #JFabianMeier's answer you could use 4 projects:
with the production version class
with the debug version class
with code that uses either of the two, parameterized according to Migrating Maven profiles ... → Example 6. Mimicking the behavior of Maven profiles in Gradle. (I'm also a Maven guy and therefore can't tell you exactly how to do it in Gradle.)
a multi-project with 1./2./3. as sub[-]projects for building all of them in one go, maybe parameterized to build just 1.+ 3. or 2.+ 3.
Have you tried creating production and debug source directories/sets? According to the docs you can use multiple directories when specifying source directories in your source set. Try dropping the different versions of your class in their respective production/debug source directories.
I haven't tested myself (not sure about the syntax), but this is based on the Gradle's Java compilation documentation.
sourceSets {
// Could also name this production
main {
java {
srcDirs ['src/main/java', 'src/prod/java']
}
}
debug {
java {
srcDirs ['src/main/java', 'src/debug/java']
}
}
}
You could do the following:
Put the class into a separate project (so generate a separate jar from it)
Then you can have two different jars, for production and debugging
Then you can pull either one or the other jar in gradle depending on a parameter.
Alternatively, you could look into template engines like Velocity which allow you to generate source code during the build depending on variables and then compile it.
Android has a neat feature called Product Flavors. It lets you swap classes at compile time effortlessly and keep your project clean.
This post is very good to get a taste of it: https://android-developers.googleblog.com/2015/12/leveraging-product-flavors-in-android.html
And here is the full documentation: https://developer.android.com/studio/build/build-variants#product-flavors

Java, IntelliJ, maven project - importing issues

This might be a silly question, but I need to know. I'll delete it if it's too silly to answer.
In a maven project in IntelliJ, I have the following structure:
procedure
e2e
cucumber (same level as common)
src
test
java
e2e
support
File: ScenarioState.java
package e2e.support
common (same level as cucumber)
src
main
java
common
testdata
File: Case.java
package common.testdata
Is there any way to import the package e2e.support (where ScenarioState.java resides) into the file Case.java in the common.testdata package?
I've been playing around with maven imports, dependencies etc., but I haven't found a way to do it. I might have to redesign some classes to get around it, but that would impact other parts of the project and I'd like to avoid it if possible.
If you really want to do that (and I would strongly recommend to either leave the project alone or restructure it first), define an additional source directory as in
How to add an extra source directory for maven to compile and include in the build jar?
But beware that a project like this will haunt you till the end of time.
One could have in the common's pom.xml a dependency to cucumber with <type>test-jar</type>.
However this violates the concept of src/main for the final product, and src/test for the unit-tests (not incorporated in the product, separate test classes).
(In src/test there can be other classes, so maybe easiest would be for common to have a src/test instead.)
If ScenarioState has nothing to do in src/main, one could place it in a more low-level library cucumberbase in src/main. And make a dependency in cucumber to cucumberbase with <scope>test</scope>. In <common> a normal dependency to cucumberbase.
Keep this main-test separation as otherwise other developers risk insanity.

Cyclic reference when a java util library is tested with external mock util library also using the java util lib

Problem
In java, I have a a "Util project" using another "Mock project" when doing unit test.
My problem is that the "Mock Project" is as well using the "Util project" to build some of the Mock object.
When i use maven to build my projects, i can't build it cause one project miss the jar from the second and reverse case for the other project.
Example
As you can see in the example below, it make sense that both project needs each other and each piece of code is located in the right project, what is "Mock" is in "Mock" project, what is "Util" is in "Util" project.
public class TestProjectUtil
{
#Test myMethod()
{
//some code
GeneratedEntity obj = ProjectMockUtil.generateEntity();
}
}
public class ProjectMockUtil
{
public static EntityObj generateEntity()
{
//Some code
EntityObj obj = new EntityObj();
MethodList names = ProjectUtil.Reflection.getMethodList(obj);
//Some code
}
}
Question
How should you deal with this type of situation. I tried to force maven to still build my project and ignore failure but as soon as one class fail to compile then the generated jar does not include any class at all, so the jar is empty.
As well i do not believe that a refactoring is ultimately needed in my case, the different classes are in the right projects and i do not want to duplicate my code for the sake of having the same class in both project to satisfy maven and make it work.
What might be the best approach ?
option 1
Another way to do it is to build the first project as a JAR WITHOUT MAVEN, in this case your jar is usable by the second project when you run maven for the first time. (the JAR will need to be added as dependency in the POM).
After that you can build the first project normally with maven, then rebuild the second project again but this time change the JAR reference in the POM to use dependency from local repository (the one you just build with first project).
And for future build always use MAVEN as before, it will work properly.
Option 2
Another way to do so is to merge the 2 projects together, its not always logic to do so but in my case, it could be logic to merge 2 class util together and create a separation via package name, for instance first project under dev.helper.helperjse, then the second project dev.helper.helpermock
In this case we don't have the issue with circular reference since within a project circular reference are accepted and normal.
Option 3
Another way is to change the argument of the maven compilation plugin and pass argument to force compilation error .class to be added to the jar file and to not fail on error. (this one i did not find what are the arguments yet, Happy if someone knows).

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){
...

How can I generate list of classes in order of dependency?

I'm doing a build script for a Java application to run inside the Oracle JVM. In order to import the 50-odd classes, it appears I need to bring them in in order, so any dependencies are present before compilation.
For each class, I'm running 'create or replace and compile java source {className} as {classPath}' for each file. Doing this gives me a compilation error, as the required class(es) are not imported.
How can I generate a list of the classes, in dependency order - that is, as you go down the list, the class's dependencies are listed above. I would prefer to do this as an Ant task.
Also if you have a better idea of how to get these classes imported, I'd love to hear your ideas.
I can't imagine why you'd need to do this, but if you really need to do this, I wonder if hacking a little classloader that prints out each class as it loads and load your app from there would give you a dependency graph?
Compile the classes in the filesystem using the Ant task javac. Use the task depend if more rigorous dependency checking is needed. Use the loadjava tool to load the .class and .java files into the database in arbitrary order.
In order to import the 50-odd classes, it appears I need to bring them in in order so any dependencies are present before compilation.
I have never had to do such a thing simply to compile Java.
This is what Ant was born for. I'd recommend just doing this with Ant. Set the <classpath> and you'll have no trouble.
Brute force method: put the 50 CREATEs in a batch file and execute it until no errors are found. Create the loop in a shell script. Of course it will never end if there are errors in the sources, but I'm assuming they are ok.
Can you not load in a jar file? Why does it have to be individual classes?

Categories