Maven: Dealing with a truly circular dependency - maven

I have a somewhat complex situation and I'm not sure what the best way to set up my Maven environment is.
I'm writing a framework to allow the creation of tests for a particular system. The system can host a variety of applications, and I have a set of tests for each application, which I'd like to keep separate from the framework (which handles the general concept of a "test", and message sending/receiving etc). Also, the framework provides a generic UI, so it can be built as a war and deployed allowing you to run and configure tests.
What I'm currently doing is building the framework both as a jar and war, listing the framework as a dependency in each application test suite, and pulling in all the framework code using an overlay so each suite can build its own war to deploy. This is gross.
What I'd like is to be able to specify (probably via profiles) which test suites to build in the framework, and end up with a single framework.war file with the specified suites included. Trying to build the poms for this I keep running into a circular dependency because:
To build the tests, the test projects must depend on the framework
To pull in the specified test jars, the framework must depend on those test projects
Things I've tried:
Make the test suites sub-projects of the framework:
This doesn't work as (I think) I can't package the final result as war (only pom packaging for aggregator projects)
List the test .jars as system dependencies:
This works, but it's gross to have to manually specify a path to the jar
Put the tests as java packages inside the framework and compile only what you want via filters:
technically possible, but I would really prefer the logical separation into separate maven projects as each test suite can be configured too, and I'd like to keep all that config out of the framework pom
What would be ideal would be a parent project pom that would:
compile the framework with no tests
compile the specified test suites
rebuild the framework .war, including the specified test suite jars
I'm not sure if this is possible and/or even advisable, but it seems the best solution to me. Thanks in advance for any suggestions for organizing this project.

Related

How can Gradle plugin access information about included builds?

I know you can access different modules (included using include) in a project via org.gradle.api.Project#getSubprojects(), and I know you can get the name and directories of separate builds that have been included (using includeBuild) via org.gradle.api.invocation.Gradle#getIncludedBuilds().
But how can my plugin get information such as the locations of Java source files and class files for projects included using includeBuild?
My goal here is to determine which files have changed in the current git branch (which I can do), and then collect their corresponding class files into a jar file that's used for our patching mechanism that inserts the patch jars at the front of the classpath rather than redeploying the whole application.
I don’t think it is a goal of Gradle to provide including builds with detailed information on included builds. Currently, the Gradle docs basically only state two goals for such composite builds:
combine builds that are usually developed independently, […]
decompose a large multi-project build into smaller, more isolated chunks […]
Actually, isolation between the involved builds seems to be an important theme in general:
Included builds do not share any configuration with the composite build, or the other included builds. Each included build is configured and executed in isolation.
For that reason, it also doesn’t seem to be possible or even desired to let an including build consume any build configurations (like task outputs) of an included build. That would only couple the builds and hence thwart the isolation goal.
Included builds interact with other builds only via dependency substitution:
If any build in the composite has a dependency that can be satisfied by the included build, then that dependency will be replaced by a project dependency on the included build.
So, if you’d like to consume specific parts of an included build from the including build, then you have to do multiple things:
Have a configuration in the included build which produces these “specific parts” as an artifact.
Have a configuration in the including build which consumes the artifact as a dependency.
Make sure that both configurations are compatible wrt. their capabilities so that dependency substitution works.
Let some task in the including build use the dependency artifact in whatever way you need.
Those things happen kind of automatically when you have a simple dependency between two Gradle projects, like a Java application depending on a Java library. But you can define your own kinds of dependencies, too.
The question is: would that really be worth the effort? Can’t you maybe solve your goal more easily or at least without relying on programmatically retrieved information on included builds? For example: if you know that your included build produces class files under build/classes/java/main, then maybe just take the classes of interest from there via org.gradle.api.initialization.IncludedBuild#getProjectDir().
I know, this may not be the answer you had hoped to get. I still hope it’s useful.

IntelliJ + Gradle Multiproject: How to tell how the target source set is called?

we are currently checking, whether we can switch from Eclipse to IntelliJ as an IDE.
In this project we are using gradle multi projects whose structure looks something like this:
Project
|-ProjectA
|-ProjectAImpl
|-main*
|-ProjectATest
|-test*
|-ProjectB
|-ProjectBImpl
|-main*
|-ProjectBTest
|-test*
= Source set or in IntelliJ it seems a module.
The ProjectBTest has a dependency to ProjectATest, which is configured as
compile project(":ProjectA:ProjectATest")
This always worked properly with Eclipse but in IntelliJ I'm having the problem, that the ProjectBTest is configured such, that it is looking for a module named "Project.ProjectA.ProjectATest.main", instead of "Project.ProjectA.ProjectATest.test"
This module can obviously not be found, leading to a lot of compiler errors.
Can maybe somebody give me a hint how I can tell IntelliJ or gradle here to take the proper module?
Thank you very much.
This is standard Gradle functionality. Unless you have other Gradle customizations (like feature variants or changing the source directories for a source set), project dependencies will naturally target the main source set.
There are several ways to solve this, but two primary ones that stand out to me:
Use Gradle's Java test fixtures.
The "test" source set is not naturally inheritable in any way in Gradle. There is no built-in consumable configuration that provides test classes to downstream projects. However, Java test fixtures allow you to use a separate testFixtures source set which is shareable. To do this, you would do the following:
Add the java-test-fixtures plugin to all projects which need to produce shared test sources
Move your shared test sources to <project directory>/src/testFixtures (ideally this would include as few actual test classes as possible, but rather just shareable test logic instead)
Change your dependency references to point to the upstream project(s)' test fixtures artifact: testImplementation(testFixtures(project(":ProjectA:ProjectATest"))
Register a tests configuration which includes the test classes as an output.
project.configurations.register("tests") {
extendsFrom(project.configurations[JavaPlugin.TEST_RUNTIME_CONFIGURATION_NAME])
}
tasks.register("testJar", Jar::class) {
classifier.set("test-classes")
from(project.the<SourceSetContainer>()[SourceSet.TEST_SOURCE_SET_NAME].output)
}
project.artifacts.add("tests", project.tasks.named("testJar"))
Downstream projects:
dependencies {
compile(project(":ProjectA:ProjectATest", "tests"))
}
None of the above code is tested. It may require some adjustments.
Java test fixtures are a supported way to produce shareable test sources, so they should be preferred, but the tests configuration may be quicker to implement, depending on your use case.

How to setup multiproject structure with maven?

I'm fairly unexperienced and all new to the whole world of build tools so here's my situation: I am developing a webapp with JSF, PrimeFaces and Hibernate on wildfly-9.0.2-final. All java files (incl. ManagedBeans, DAOs, Model classes, etc.) are currently in a regular eclipse java project called MyApp-CORE. There is no html or any other resources in that project, but all the third-party libraries like PrimeFaces, commons-xy, etc. Then I got two dynamic web projects with all the .xhtml files and stuff. Both web projects include the CORE in their build path (all done via eclipse built-in tools). Basically I followed Structure for multiple JSF projects with shared code so far. All projects are versioned using Git. I was now asking myself how to mavenize the whole thing and also how to properly include tests. The final result should be:
I want a build file for each web project that includes the CORE dependency and all of it's transitive dependencies, creates a .war file and deploys it either on the production system or locally (Depending on some parameters I want to be able to maintain).
This buildfile could then for instance test and build the CORE and then the .war file.
Since I'm using JSF, mostly the only option for testing is JSFUnit. Should I test each web project individually and put all the test cases there (which would be highly redundant because they're mostly the same, just a few features are different) or should I rather create a separate web project called MyApp-TEST which tests the CORE.jar and also - depending on some configuration - each web project.
I've already created a structure that makes it possible to include the core in the web project but unfortunately I loose the perks of hot deployment in wildfly when just including it as a dependency from my local maven repository.
So, to summarize it:
What would be a best practice for this setup, eventually leading to a continuous integration scenario?
How should I include the test cases (full integration tests that test actual UI behaviour)?
Which Tool (Maven, Gradle, Ant, etc.) would be best for that task?
Keep using hot deployment for smooth development?
Thanks in advance for any comments, hints or shared experience!

Library development/debug with Maven

I am in the processing of integrating Maven into my my projects. While maven has plenty of pros i'm finding it difficult to figure out how to maintain my current development process, which is as follows:
For creating SDKs I will create a sample app, which will depend on and directly reference the SDK source code, all from within the same code project. This means that I can make easily change/debug the SDK code with one click run/debugging.
I fear this won't really be possible with Maven. Can I create some type of Hybrid approach, where I continue my normal development approach and then push builds to Maven when it is appropriate.
Update - For Clarity
My problem is that when everything is done through maven, the dependencies are built and published to Maven. Then, the dependent project pulls down compiled references and uses them. My issues is that I don't want to go through this whole process every time I make a small change to a dependency.Thanks.
You should try creating parent level pom.xml with two modules - your library and simple app to test it. In simple app's pom.xml provide a dependency on library module.
Then open in your IDE parent pom as maven project. This should be sufficient for normal debug.
Other possible approach - install you library artifact into maven repo with sources. In this case you will be able to debug it, but test app still have to load use jars from repo.

Simple way to test requiring OSGI without lots of artefacts and dependencies

OSGI Testing frameworks - some observations.
I am in the middle of writing a system that makes use of OSGI. However all of the popular testing frameworks (Spring-OSGI, PaxExam) require a lot of artefacts for even the simplest test.
Wishlist / Goals
Ideally i would like a single Test that uses TinyBundle to assemble bundles and gives them to the framework. The framework will then do the heavy lifting of starting the container, deploying, running each test, updating the ui to show results etc.
On the surface it would appear that PAX-EXAM would satisfy this but it has additional requirements, which I have not been able to solve, within Eclipse. My problems are:
Each bundle requires a separate project.
Each project gets a manifest.mf in the $project/meta-inf/.
Ideally i would like to bundle all my manifests and "internal" classes in separate sub packages of the test rather than having them scattered about in their respective projects.
I have found packaging everything into the one project just does not work when the tests
execute even if the bundles provisioned are identical in content. However if i split everything into separate projects stuff just works.
Maven
I wish to avoid maven as this implies that a more complex system that would end up requiring building, deploying into the repo which in the end even when automated just slows things down even more. This would conflict with my use of Infinitest which automagically detects changed classes and just executes the right tests.
Eclipse Project Plugin launch configurations.
This approach requires one to pick the bundles to deploy prior to executing the junit test. This of course only works if one has separate projects with a one to one mapping per bundle. Again this goes against my attempts to consolidate all test dependeny bundles under one project.
How, Can it be done ???
How can i achieve this ?
Is this practically possible ?
Whats the simplest alternative ?
One alternative, which also leverages Pax Exam, is what we did in an OSGi testing framework (that tests OSGi framework implementations). Rather than duplicating the whole explanation of how it works, you can find that here:
http://opensource.luminis.net/wiki/display/OSGITEST/OSGi+testing+framework
It does not use Maven, and writing new tests is explained here:
http://opensource.luminis.net/wiki/display/OSGITEST/Writing+a+framework+test
Maybe some of the solutions can inspire you. All in all, there are many test frameworks out there for OSGi (just like there are for non-OSGi) but so far there has one been any one that "makes the rest obsolete".

Resources