I develop a little java utility library using maven. Now I'd like to add some demo / sample code to show how to use the library.
Where is the best place to put it?
In a sub-package with the other code. I don't like this since it means the demos will be included in the library jar file.
In a new maven artifact. That works, but I'd prever to have the demos closer connected to the library source.
As a sub-artifact. Haven't tried this yet. Seems to make everything a bit complex for something that should be simple.
Is there any common pattern to do this?
If it's some sample code snippets that run by themselves and just demonstrate how to use the library, then write them as unit tests, in the same module.
If it's more like a separate demo application (that a user might even interact with), then create a separate artifact. It's the standard way of doing it. If you really want to you could put it in the same module, but in a different source directory, but that's just making it harder on yourself.
Your library and you demo should probably share a parent module (of type "pom", not "jar" like the others), giving you a multi-module project. Then you can build both by launching maven from this parent module.
If you want to release your library and demo together (you can, but you don't have to), you can do that from the parent too.
In other words, it's not because they are separate modules, packaged in different artifacts, that they cannot be closely connected anymore. The different modules of a multi-module project still form one whole project.
You hadn't written what kind of utility library it is, but if it's something like apache commons, then most of the demos can be written as JUnit tests, which are placed in the same artifact. Good designed JUnit tests both tests your code and provide example how to use your utilities.
I prefer a new maven artifact, it can make your own artifact clean
I would recommend create a maven multi-module project where one module is the core and one module is the demo code. That way the user can choose if he wants to create both modules (they become separate artifacts) or if he just wants the core.
Related
I have multiple app projects of of roughly this layout:
example app (Java)
Java Wrapper with additional functionality
C++ + Shallow Java Wrapper
2nd example app (flutter)
flutter wrapper
Java Wrapper with additional functionality
C++ + Shallow Java Wrapper
3rd example app
flutter wrapper
Java Wrapper with additional functionality
C++ + Shallow Java Wrapper
All apps share the same main dependency (java Wrapper with additional functionality) and its dependency tree. Now I am developing on each app all the way down to C++ code. They are managed as git submodules in their respective parent project.
As there is a high change rate along the whole process, I want the final example to be built for testing from all sources.
I tried several approaches for tying this together into one gradle build:
1. Preferred (but failing) solution: settings.gradle in each project, each project only includes direct dependencies
Now I want this full tree to be managed in one flutter build. So I add the direct dependencies in each projects settings.gradle, just to learn that gradle only supports one toplevel settings.gradle. So this does not work. The presented solutions in aforementioned question mostly try to emulate support for multiple settings.gradle files.
2. Functioning but Ugly: Add all dependency projects are included in the toplevel settings.gradle
Do I really have to include all subprojects manually in the toplevel settings.gradle, when each of the subprojects knows its dependencies perfectly fine? Furthermore, since there are multiple projects depending on this, do I have to do this manually for each of them?
(And don't even get me startet about gradle not telling me, I have a wrong projectDir because I got a typo in the 100rth level of recursive descend!)
3. Probably Working Solution: Use composite builds
This will trigger the builds but now I have to resolve the build artifacts instead of the projects. So same problem with other artifacts.
4. Probably Working solution: Publish dependency projects to a maven (or other) repository and pull that into the app
I did not try this because I find the idea abhorent: I want to test one small change in the C++ code and now have to push that to a repository and potentially do the same on every project above?
This works for a stable project but not for flexible exploratory development. Sure, I want to publish something at the end but I don't want to publish every little step in between.
This left me wondering: Am I doing something unusual? I mean: is there nobody who has the same requirements that gradle does not seem able to fit:
live updates from all the way down to quick test local changes
no repeating of transitive dependencies on the toplevel
What is the common practice in this case?
After Lukas Körfer's comment I took a closer look at composite builds again and noticed that I had a misconception about them. I did not understand that their dependency resolution will solve the finding of the build artifacts for me.
Now I use the composite builds to tie together the whole build while using
implementation 'my.group:project'
to import the code of the subprojects and
includeBuild '../path/to/subproject/'
to pull them in.
Task: what I have is the large non-Gradle (make:-)) project, which contains many subprojects, each one in it's own subdirectory. I have to write functional test for some of these subprojects. These subprojects are producing independent results, but with the same structure, so there is many common code for testing these subprojects, so I want to share it in some special location.
Restrictions:
as developers requested, the tests for subprojects should be in the directory of this subproject (to be precise, in the subdirectory, for example, func_tests).
I have some shared dependencies for my test projects, that I usually use, for example, Google Guava, TestNG and so on, and also have some settings for test run (excludeGroups 'slow'...) and I prefer this settings to be common, still, that doesn't matter too much.
symbolic links are accepted way, if that's good design:)
If it's possible, I want to have IntelliJ IDEA correctly handle this dependency.
My ideas:
symlink src/main of every test subproject to some common directory (src/test is "individual"). This will greatly support IDE , but it would lead to copying all the dependencies and preferences. Also, I'm very unsure, if that's preferred way in Gradle.
create common project, which will be imported by every subproject, this will save dependencies (will it?), but I'm not sure IDEA will correctly handle this way.
What is the idiomatic way to do this with Gradle?
Look at samples/java/withIntegrationTests in your Gradle installation. This will give you some idea how to add your tests (there are other ways too). You want to tweak that setup to make sure that IDEA handles your tests. This is done by customization of idea.module.scopes.
Shared code and shared libraries: you can create a map like https://github.com/gradle/gradle/blob/master/gradle/dependencies.gradle and use it in different subprojects. BTW: Gradle codebase has a lot of integration tests and you can check how their build is configured to see if you want to apply some ideas.
While downloading Google Guice I noticed two main "types" of artifacts available on their downloads page:
guice-3.0.zip; and
guice-3.0-src.zip
Upon downloading them both and inspecting their contents, they seem to be two totally different "perspectives" of the Guice 3.0 release.
The guice-3.0.zip just contains the Guice jar and its dependencies. The guice-3.0-src.zip, however, did not contain the actual Guice jar, but it did contain all sorts of other goodness: javadocs, examples, etc.
So it got me thinking: there must be different "configurations" of jars that get released inside Java projects. Crossing this idea with what little I know from build tools like Ivy (which has the concept of artifact configurations) and Maven (which has the concept of artifact scopes), I am wondering what the relation is between artifact configuration/scope and the end deliverable (the jar).
Let's say I was making a utility jar called my-utils.jar. In its Ivy descriptor, I could cite log4j as a compile-time dependency, and junit as a test dependency. I could then specify which of these two "configurations" to resolve against at buildtime.
What I want to know is: what is the "mapping" between these configurations and the content of the jars that are produced in the end result?
For instance, I might package all of my compile configuration dependencies wind up in the main my-utils.jar, but would there ever be a reason to package my test dependencies into a my-utils-test.jar? And what kind of dependencies would go in the my-utils-src.jar?
I know these are a lot of tiny questions, so I guess you can sum everything up as follows:
For a major project, what are the typical varieties of jars that get released (such as guice-3.0.zip vs guice-3.0-src.zip, etc.), what are the typical contents of each, and how do they map back to the concept of Ivy configurations or Maven scopes?
The one you need to run is guice-3.0.zip. It has the .class files in the correct package structure.
The other JAR, guice-3.0-src.zip, has the .java source files and other things that you might find useful. A smart IDE, like IntelliJ, can use the source JAR to allow you to step into the Guice code with a debugger and see what's going on.
You can also learn a lot by reading the Guice source code. It helps to see how developers who are smarter than you and me write code.
I'd say that the best example I've found is the Efficient Java Matrix Library at Google Code. That has an extensive JUnit test suite that's available along with the source, the docs, and everything else that you need. I think it's most impressive. I'd like to emulate it myself.
What is the easiest way to see the libraries dependencies in Java project (eclipse)?
I am using Spring MVC and Hibernate so right now there are a lot of jar files and I even do not remember which one of them are responsible for what.
check out tattletale.
http://www.jboss.org/tattletale
See them how?
If you're using maven, use the dependency plugin's dependency:tree to get a hierarchical representation of what depends on what.
If you're not, ew; manual management of transitive dependencies sucks! You can use something like Dependency Finder or JDepend to provide similar info.
Not sure if this is what you mean, but to start with you can right-click the project (in Eclipse) and look at Properties -> Java Build Path. The Libraries tab should list what libraries you're using on your build path. (But you probably knew that.)
If it's a simple standalone project, you could of course always remove a library and see what interesting new errors pop up ;-)
For more complicated projects with interdependencies, it can take quite a bit of fiddling to get all your dependencies right. I generally recommend setting up a "core" project which holds (and exports) most of your third-party JARs (better yet, use user libraries, and putting that project on the build path of your other projects.
Edit after reading your comment: Ah, gotcha... you might be interested in the Plug-in Dependency Visualisation incubator project then - haven't used it myself but it sounds like it could do what you're after. Hope that helps!
I am converting a large Java project to use maven. I have a LOT of inter dependencies to work out, but I would like to get it off the ground with maven before I do the real cleanup work. I have broken it up into a few modules plus one giant module; let's call that module monolith.
Monolith has regular Java classes and some gwt classes (with interdependencies). I separated the two parts to have a directory structure like this:
./src/main/java/...
./src/client/gwt/...
So, I can easily get this to compile in eclipse with m2eclipse, but then I can't seem to find how to get it to compile with maven. I saw that the pom file has a build section where you can specify an alternate source and target, but I think it is not a repeatable attribute in the pom:
<build>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
</build>
In eclipse, I can adjust the project's .classpath file (in the project properties) to add additional source files (and output dirs) to accomplish what I am looking to do.
Is there any way to do this, or do I need to work out the dependencies first, and separate into separate modules?
If you go against the grain with maven it will be an uphill battle all the way.
Maven doesn't lean towards multiple main source directories, they would do better in maven environment as separate modules.
I've looked at a number of maven gwt projects and archetypes, and none of them seem to take the approach you've suggested.
Have a look at the source structure used by Hupa, also see the archetypes from the Ham and Eggs blog
http://hamandeggs.wordpress.com/2010/01/26/how-to-gae-eclipse-maven/
http://hamandeggs.wordpress.com/2010/07/25/gae-eclipse-maven-update-for-helios/
These also cater for App Engine.
If you really need to separate your java server source from your gwt client source, then monolith needs to be split into more modules.
It is quite common to see gwt projects with a package structure as follows:
com.company.project
.client
.server
.shared
And then specify the source paths in your gwt.xml to include client and shared
What you have is called a maven multi-module project. Take a look at this tutorial on the maven book.
So, I can easily get this to compile
in eclipse with m2eclipse, but then I
can't seem to find how to get it to
compile with maven.
-- I am not sure what you meant by this. M2Eclipse plugin is using maven to build your modules. Perhaps you can clarify this section. Hope the tutorial link helps you.
try to follow this tutorial http://maven.apache.org/plugins/maven-eclipse-plugin/reactor.html
main idea- start from creation of empty project from maven mvn archetype:create and then put you sources to created by maven structure...
also i can strongly recommend to check your dependency tree and effective pom with eclipse plugin tool when you perform this task (for avoid duplicate in dep. & other bad things)