Ivy dependency conf map wildcard - java

In an ivy dependency,
Q1.
What is the difference between
conf="runtime->compile"
vs
conf="runtime->compile(*)"
What does the extra bracketed wildcard do?
Q2.
What does the following do?
conf="compile->compile(*)"
Isn't it a cyclical/self dependency? What is the point of mapping a conf back to itself?

The brackets are a fallback:
since 1.3 a fallback mechanism can be used when you are not sure that
the dependency will have the required conf. You can indicate to ivy
that you want one configuration, but if it isn't present, use another
one. The syntax for specifying this adds the fallback conf between
parenthesis right after the required conf. For instance,
test->runtime(default)
means that in the test configuration of the
module the
runtime
conf of the dependency is required, but if doesn't
exist, it will use the
default
conf instead. If default conf doesn't
exist then it will be considered as an error. Note that the
* wildcard can be used as fallback conf.
For Question2:
a conf is always read like:
ConfFromThisFile -> ConfFromDependency
So
compile->compile
will map the compile configuration of the dependency to the compile configuration of this file. It is no cycle. The bracket says: If compile does not exist in the dependency then use *.
See the Configuration Mapping Section of the ivy documentation for dependencies.

This syntax is for dependency fallback. runtime->compile means that the runtime configuration depends on the compile config. The compile config must be present or Ivy will report an error. However, runtime->compile(*) will try the compile configuration first to satisfy dependencies. But if compile doesn't exist, it will try all the other configurations. See the Configurations mapping section of the Ivy docs for more info.
Based on that, compile->compile(*) would indicate that compile needs any (all?) configurations. I am guessing that compile->(*) isn't valid syntax so the extra compile guarantees the fallback is used since compile isn't defined until after the configuration XML stanza is complete.
Note that it's not clear from the documentation if (*) means 'any' or 'all' configurations. So, I am not sure if Ivy will stop at the first configuration that matches all dependencies (if there is one) or if it brings in all the other configurations in a union.

Related

How to overwrite config in a Quarkus extension

Is there a way to overwrite a configuration in a Quarkus extension with a hard-coded value?
What I'm trying to do: I am creating a custom Quarkus extension for JSON logging, based on quarkus-logging-json but with additional (non static) fields. I reuse some classes from the extension's runtime library, so it is a Maven dependency of the runtime module of the extension (and the deployment also needs to be declared as a dependency to my deployment module, because the quarkus extension plugin checks this).
It seems to work fine, except that I now have 2 formatters, and the following line is logged:
LogManager error of type GENERIC_FAILURE: Multiple console formatters were activated
I would like to disable the quarkus-logging-json extension completely by hard-coding these values:
quarkus.console.json.enable=false
quarkus.file.json.enable=false.
Is there a way to do this?
Thank you.
An extension cannot override runtime configuration values, it can however set a default value using io.quarkus.deployment.builditem.RunTimeConfigurationDefaultBuildItem

Gradle project does not export implementation-dependency to other projects

My gradle project contains 3 sub-projects with one source file each:
root-project\
sub-project-abstract\
...AbstractFoo.java
sub-project-commons\
...ConcreteFoo.java (extends AbstractFoo)
sub-project-main\
...Main.java (instantiates ConcreteFoo)
build.gradle of sub-project-commons:
dependencies {
implementation(project(:sub-project-abstract))
}
build.gradle of sub-project-main:
dependencies {
implementation(project(:sub-project-commons))
}
The Main-class in sub-project-main is aware of ConcreteFoo, however, compilation fails with cannot access AbstractFoo.
For some reason, I expected sub-project-commons to "export" ConcreteFoo and AbstractFoo, since it's a implementation-dependency. Or in other words, form the perspective of sub-project-main, AbstractFoo is a transitive dependency.
However, this doesn't seem to be the case.
I know that I could probably make it work by explicitly adding sub-project-abstract as a direct dependency to sub-project-main. However, that's something I want to avoid due to the nature of the commons project (my actual project contains up to 10 subprojects, and it should be possible to reuse the commons-project without declaring a dependency to sub-project-abstract every single time the commons-project is referenced.
Is there a way to make the Main-class aware of AbstractFoo without directly declaring sub-project-abstract as a dependency (but indirectly via sub-project-commons)?
This is expected behavior for the implementation configuration. You should apply the Java Library Plugin and use the api configuration.
The key difference between the standard Java plugin and the Java Library plugin is that the latter introduces the concept of an API exposed to consumers. A library is a Java component meant to be consumed by other components. It’s a very common use case in multi-project builds [emphasis added], but also as soon as you have external dependencies.
The plugin exposes two configurations that can be used to declare dependencies: api and implementation. The api configuration should be used to declare dependencies which are exported by the library API, whereas the implementation configuration should be used to declare dependencies which are internal to the component.
[...]
Dependencies appearing in the api configurations will be transitively exposed to consumers of the library, and as such will appear on the compile classpath of consumers. Dependencies found in the implementation configuration will, on the other hand, not be exposed to consumers, and therefore not leak into the consumers' compile classpath. [...]
In sub-project-commons (Kotlin DSL):
plugins {
...
`java-library`
}
...
dependencies {
api(project(":sub-project-abstract"))
}
...

How to configure Equinox to make it require optional packages declared in bundle dependencies

I would like to configure Equinox so that it throws an exception when starting modules which don't have all their optional dependencies available.
Just like with missing non-optional dependencies.
Is this possible?
No.
This line added to satisfy StackOverflow's minimum character count.

Using custom annotation processors alongside Checker Framework

I'm working on a multi module maven based project in which one of the modules contains a few annotation processors for the custom annotations used by other modules. When I add a dependency of annotation processor module to any other module, the annotations of that modules are processed by those annotation processors.
But recently I integrated Checker Framework (for type annotations) and then all the custom annotation processors (I mentioned above) stopped working. Any idea on how to get them to work even with Checker Framework is greatly appreciated?
To clear the scenario,
Let's say I have a maven module named module_A. In this module I have a annotation (class level) called "#FoodItem". I need to enforce a rule that any class annotated with "#FoodItem" annotation should implement the interface "Food". So I wrote an annotation processor "FoodItemAnnotationProcessor" in the same module (module_A) which processes such classes and check for the compliance with that rule.
Then let's say I have another module named module_B which has a maven dependency to the module_A. In this module I have a class called "Pizza" which is annotated with "#FoodItem" annotation.
If a build the project (which has module_A and module_B) with the above configuration, the "FoodItemAnnotationProcessor" is executed at compile stage and validates the class "Pizza" for the rule mentioned above.
After that I integrated Checker framework to module_B (as mentioned here). Then checker framework related validations are executed at compile time as expected, but the "FoodItemAnnotationProcessor" ceased to work.
To understand the problem you must know how javac finds your annotation processors.
When you don't supply the --processor argument for javac (see doc-javac-options), then the annotation-processor auto-discovery feature (see javac-doc: Annotation processing) is activated. This means, that javac will search for all available annotation-processors in your classpath (or processorpath, if you have specified it).
Jars, which include a META-INF/services/javax.annotation.processing.Processor file, can specify their annotation processor classes and javac will automatically use them.
The "problem" is that the checker-framework has multiple multiple annotation processors for the checks, but you may only want to use some of those: thus the annotation-discovery process cannot be used and you must manually specify all annotation processors to run in your build file.
For a Maven build you can do it like this:checker-framework doc for Maven
<annotationProcessors>
<!-- Add all the checkers you want to enable here -->
<annotationProcessor>org.checkerframework.checker.nullness.NullnessChecker</annotationProcessor>
</annotationProcessors>
This will explicitly set the --processor argument for javac (see doc-javac-options), which disables the default annotation-discovery process.
So the solution is to manually add all annotation processors that you want to run (in addition to the checker-framework checkers).
E.g. when you want to run the NullnessChecker and Dagger, you must specify both:
<annotationProcessors>
<!-- Add all the checkers you want to enable here -->
<annotationProcessor>org.checkerframework.checker.nullness.NullnessChecker</annotationProcessor>
<!-- Add all your other annotation processors here -->
<annotationProcessor>dagger.internal.codegen.ComponentProcessor</annotationProcessor>
</annotationProcessors>
Hint:
to find out which annotation processors you are currently using, run your build and pass the Non-Standard Option -XprintProcessorInfo to javac.
UPDATE:
The checkers also support some sort of auto-discovery (doc-ref) - Note: I have not used this yet.
2.2.3 Checker auto-discovery
“Auto-discovery” makes the javac compiler always run a checker plugin,
even if you do not explicitly pass the -processor command-line option.
This can make your command line shorter, and ensures that your code is
checked even if you forget the command-line option.
To enable auto-discovery, place a configuration file named
META-INF/services/javax.annotation.processing.Processor in your
classpath. The file contains the names of the checker plugins to be
used, listed one per line. For instance, to run the Nullness Checker
and the Interning Checker automatically, the configuration file should
contain:
org.checkerframework.checker.nullness.NullnessChecker
org.checkerframework.checker.interning.InterningChecker

Gradle unable to resolve version for dependency

My project depends on the Pax Exam framework. I declare, among others, these dependencies on Pax (PAX_EXAM_VERSION = 3.4.0):
compile group: 'org.ops4j.pax.exam', name: 'pax-exam-junit4', version: PAX_EXAM_VERSION
compile group: 'org.ops4j.pax.exam', name: 'pax-exam-container-native', version: PAX_EXAM_VERSION
Both of these depend on org.ops4j.pax.exam:pax-exam-spi, which is the module causing my issue.
So, when I try to build my project, the error reported is this one:
Could not resolve org.ops4j.pax.exam:pax-exam-spi:3.4.0
...
Could not parse POM http://repo.maven.apache.org/maven2/org/ops4j/pax/exam/pax-exam-spi/3.4.0/pax-exam-spi-3.4.0.pom
Unable to resolve version for dependency 'com.google.guava:guava:jar'
I have tried:
excluding pax-exam-spi from the transitive dependencies of the modules I depend on (but notice I still need the classes in it to be able to compile), adding Guava to my first-level dependencies, then trying to make pax-exam-spi a first-level dependency with transitive = false (won't work, same problem as above).
same as above, but instead of doing transitive = false, trying to use artifact-only notation, like this:
compile "org.ops4j.pax.exam:pax-exam-spi:${PAX_EXAM_VERSION}#jar"
I know the root of the problem is that the guava version is not declared in the pax-exam-spi pom, but in its parent exam, which only declares the Guava version(s) to use in 2 different profiles' dependencyManagement sessions (this works in Maven because one of the profiles is activated if the property glassfish.release is NOT set, and the other if that property IS set). However, knowing this has not been useful so far :(
Please let me know if there's any not-so-hacky way to make sure Gradle does include the pax-exam-spi's jar in my classpath, but does not even try to parse its POM (in particular, referring to a hard-coded path to the jar is out of question!).

Categories