Purpose of spring-boot-autoconfigure-processor? - spring-boot

What is the purpose of:
annotationProcessor "org.springframework.boot:spring-boot-autoconfigure-processor"
My application is working fine with or without it. The thin jar that I create, is also working fine in dependent project.
I am asking this because that line is working fine when I include it in local build.gradle. But as soon I push it to cloud, I get this error:
Could not find method annotationProcessor() for arguments [org.springframework.boot:spring-boot-autoconfigure-processor] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
So I was thinking to do without it. I am not seeing any affect on the thin jar or the dependent project.
Also, This page says that I must use annotationProcessor in build.gradle when using Gradle 4.6 or above. What if I use compileOnly option in Gradle 4.8?

spring-boot-autoconfigure-processor is an annotation processor that generates the file META-INF/spring-autoconfigure-metadata.properties for inclusion in your project's jar. This file helps with startup time, but is not necessary for your app to function correctly.
From the docs:
If that file is present, it is used to eagerly filter
auto-configurations that do not match, which will improve startup
time.

Related

Protobuf marshallers not registering when using Gradle?

I have a project where I'm trying to get protobuf to work with infinispan, quarkus and gradle. The problem is that although I'm following the instructions given in the Quarkus homepage: https://quarkus.io/guides/infinispan-client, it seems that when I'm using gradle, the marshallers are not generated and registered as they should be. To me it seems like this comes down to the org.infinispan.protostream:protostream-processor not executing when gradle is the build tool. Is this a conscious decision that only Maven is supported, or am I missing something obvious in my gradle setup?
Replications of the most simple cases can be found here: https://github.com/radiosphere/gradle-java-protobuf for gradle and here for maven: https://github.com/radiosphere/mvn-java-protobuf. These projects are extremely basic, basically trying to run a simple code on startup:
public void onStartup(#Observes StartupEvent startupEvent) {
RemoteCache<String, CounterState> cache = cacheManager.administration().getOrCreateCache("default", DefaultTemplate.DIST_SYNC);
cache.put("a", new CounterState(2L));
CounterState state = cache.get("a");
logger.infof("State: %s", state);
}
In the maven project this works, in the gradle project an exception is thrown saying that no marshaller can be found. Apart from build tool choice the projects should be identical.
The annotation processor runs in the Maven build because io.quarkus:quarkus-infinispan-client has a compile dependency on org.infinispan.protostream:protostream-processor.
Looks like Gradle made a decision to not use annotation processors found in the compile classpath:
Since implementation details matter for annotation processors, they must be declared separately on the annotation processor path. Gradle ignores annotation processors on the compile classpath.
That means you have to add an explicit annotationProcessor dependency:
annotationProcessor 'org.infinispan.protostream:protostream-processor:4.4.0.Final'

Gradle: Combine jars from sub-projects

I have a multi module gradle project. The project contains two subproject, i.e. a spring-boot application server and an npm front-end ui (which is just static javascript).
I can build both sub-projects. I can define:
implementation(project(':ui'))
in the dependencies section of the spring application and I get a running jar in the server projects build folder successfully serving the frontend.
However, I want to be able not to combine the two not within the server sub-project, but rather in the enclosing project.
I thought of something like:
build.gradle:
allprojects {
group = 'com.example.webapp'
version = '0.0.1-SNAPSHOT'
}
dependencies {
implementation(project(':server'))
implementation(project(':ui'))
}
settings.gradle:
rootProject.name = 'webapp'
include 'server', 'ui'
I think, I am completely wrong. Everything I find about gradle is either completely basic, or assumes way more than what I understood about it so far.
EDIT:
With my solution approach I am getting the following error:
A problem occurred evaluating root project 'webapp'.
Could not find method implementation() for arguments [project ':server'] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
EDIT 2:
The basic idea is from https://ordina-jworks.github.io/architecture/2018/10/12/spring-boot-angular-gradle.html
The implementation not found is caused by the lack of plugins applied to your root project. The implementation configuration is created by the java plugins in Gradle.
What you are trying to achieve requires a good understanding of Gradle and all the magic provided by the Spring Boot plugin.
You are effectively trying to reproduce some of that integration in your root project, without the help of the plugins.
An approach that might be easier would be to migrate your application project to be the root project and then have the ui as a subproject.

Equivalent of api for test dependency in gradle?

I'm having multi module gradle project. In one of my modules I'm having api dependency:
api('de.flapdoodle.embed:de.flapdoodle.embed.mongo')
I want to change it to dependency that will be visible in tests, across all modules. There is a testImplementation dependency but there is no testApi.
I cannot have this dependency on production classpath anymore since I want to use real mongo instance instead of embedded one. On the other hand I have tests in different modules that depend on data access - in that case I want to run those test with embedded mongo on test classpath.
How I can make this dependency visible in all modules tests?
The question (appears to me) is sharing the test code across modules in a multi-module project
Short answer - No - there is direct test dependency share across modules.
To share test code between modules internally via build settings
Official gradle route https://docs.gradle.org/current/userguide/java_testing.html#sec:java_test_fixtures
Simple hack
testImplementation files(project(':core-module').sourceSets.test.output.classesDirs)
add the above line either individually where you need or in root with subprojects() with appropriate condition
*there are other possible routes as well *
ex: via configuration
child.testImplementation extends parent.testImplementation (or runtime)
testCompileClassPath includes api dependencies so you are all good here, de.flapdoodle.embed.mongo will be visible in your tests.

Understanding Maven scoping better

I have been struggling to figure out what's the use of scoping that is provided by Maven
as mentioned here.
Why should you not always have compile time scoping? Real life examples would be really appreciated.
The compile scoped dependencies are only used during compilation.
The test scoped ones -- only during tests. Say you have tests using junit, or easymock. You obviously do not want your final artifact to have a dependency on them, but would like to be able to just depend on these libraries while running your tests.
Those dependencies which are marked provided are expected to be on your classpath when you're running the produced artifact. For example: you have a webapp and you have a dependency on the servlet library. Obviously, you should not package it inside your WAR file, as the webapp container will already have it and a conflict may occur.
One of the reasons to have different scopes for dependencies is that different parts of the build can depend on different dependencies. For example, if you are only compiling your code and not executing any tests, then there is no point in having Maven downloading your test dependencies (if they're not already present in your local repository, of course). The other reason is that not all dependencies need to be placed in your final artifact (whether it's an assembly, or WAR file), as some of the dependencies are only used during the build and testing phases.
compile
Will copy these jar files into prepared War file.
Ex: hibernate-core.jar need to have in our prepared War.
provided
These jars will be considered only at complie time and test time
Ex:
servlet.jar will be provided by deployed server, so no need to provide from our prepared War file.
test
These jars are only required for running test classes.
Ex: Junit.jar will be required only for running Junit test classes, no need to deploy these.
Scopes are quite well explained in here:
https://maven.apache.org/pom.html#Dependencies
As a reference, I copied the paragraph:
scope: This element refers to the classpath of the task at hand
(compiling and runtime, testing, etc.) as well as how to limit the
transitivity of a dependency. There are five scopes available:
compile
- this is the default scope, used if none is specified. Compile dependencies are available in all classpaths. Furthermore, those
dependencies are propagated to dependent projects.
provided - this is
much like compile, but indicates you expect the JDK or a container to
provide it at runtime. It is only available on the compilation and
test classpath, and is not transitive.
runtime - this scope indicates
that the dependency is not required for compilation, but is for
execution. It is in the runtime and test classpaths, but not the
compile classpath.
test - this scope indicates that the dependency is
not required for normal use of the application, and is only available
for the test compilation and execution phases.
system - this scope is
similar to provided except that you have to provide the JAR which
contains it explicitly. The artifact is always available and is not
looked up in a repository.
there are a couple of reasons that you might not want to have all dependencies to be default compile scope
reduce the size of final artifact(jar,war...) by indicating different scope.
when you have a multiple-modules project, you have ability to let each module have it's own version of dependency
avoid class version collision by provided scope, for instance if you are going deploy a war file to weblogic server, you need to get rid of some javax jars, like javax.servlet, javax.xml.parsers, JPA jars and etc. otherwise you might end up with class collision error.

Maven, NetBeans Platform, Wrapper Modules and Annotation Processors on dependencies

I have a Maven NetBeans platform application. One of its modules is a wrapper to a java project (jar) that exposes some services to the Lookup. In the wrapped project I use the maven-processor-plugin to process the annotations so everything gets registered in the Lookup. I’m unable to see the exposed classes on the wrapped module. I tried running the maven-processor-plugin but it is skipped since there are no source files in the wrapped module. Even if there were it wouldn’t fix the problem.
You can get the code here, in the Marauroa Server Manager project, Module: jWrestling Wrapper.
The code for the wrapped module can be found here. Annotated classes within the modules work fine.
Is there a way to execute the annotation processors on the dependencies of a project? Am I missing something obvious?
the wrapped jar project cannot contain nb.org annotations. these generate META_INF/generated-layer.xml file that is only read from a MODULE jar, not the wrapped non-module jar
the binary dependency contains some netbeans-originating annotations? and you want to process it through the maven plugin? that won't work. Most if not all netbeans annotations are compile-time only, meaning that they are processed at compile time and not retained in the bytecode. so only su
Besides for Netbeans annotations (which are based on jdk 1.6 annotation processors, you don't need the processor plugin, compile plugin should be sufficient.

Resources