How to enable Hibernate bytecode instrumentation just before Intellij IDEA run? - java

In gradle you can achieve it using:
apply plugin: 'enhance'
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.hibernate:hibernate-gradle-plugin:VERSION'
}
}
dependencies {
compile group: 'org.hibernate.javax.persistence', name: 'hibernate-jpa-[SPEC-VERSION]-api', version: '[IMPL-VERSION]'
compile group: 'org.hibernate', name: 'hibernate-gradle-plugin', version: 'VERSION'
}
What if instead of running the project through Gradle, I want to run my main class directly through Intellij (shift-F10). Is it possible to also perform build-time bytecode instrumentation just before the application run? How should I achieve this?

Hibernate does "bytecode instrumentation" at runtime, so you don't have to do anything special for it to happen.
Actually it is not bytecode instrumentation, which means changing existing classes, but proxying, which means, the existing classes are used by classes that get generated on the fly.

Related

Can't add an extension to a quarkus project

I tried to add an extension with command .\gradlew addExtension --extensions=io.quarkus:quarkus-resteasy-mutiny --stacktrace. I got the following error:
Caused by: org.gradle.api.GradleException: No platforms detected in the project
at io.quarkus.gradle.tasks.QuarkusPlatformTask.platformDescriptor(QuarkusPlatformTask.java:45)
at io.quarkus.gradle.tasks.QuarkusPlatformTask.getQuarkusProject(QuarkusPlatformTask.java:188)
at io.quarkus.gradle.tasks.QuarkusAddExtension_Decorated.getQuarkusProject(Unknown Source)
at io.quarkus.gradle.tasks.QuarkusAddExtension.addExtension(QuarkusAddExtension.java:59)
I figured something is lacking in the configuration, but I can't find what.
My build.gradle file:
plugins {
// Apply the application plugin to add support for building a CLI application in Java.
id 'application'
id 'io.quarkus'
}
repositories {
// Use JCenter for resolving dependencies.
jcenter()
mavenCentral()
gradlePluginPortal()
}
dependencies {
// Use JUnit test framework.
testImplementation 'junit:junit:4.13'
// This dependency is used by the application.
implementation group: 'io.quarkus', name: 'quarkus-resteasy', version: '1.12.2.Final'
implementation group: 'io.quarkus', name: 'quarkus-resteasy-mutiny', version: '1.12.2.Final'
}
application {
// Define the main class for the application.
mainClass = 'wells.App'
}
First of all, the --extensions parameter of the addExtension task does not take Maven coordinates but extension names without the quarkus- prefix, like so:
% ./gradlew addExtension --extensions="hibernate-validator"
> Task :addExtension
? Extension io.quarkus:quarkus-hibernate-validator has been installed
Additionally, I strongly recommend to let Quarkus manage the dependency versions for you. Quarkus is an opinionated framework and puts a lot of effort into managing dependencies for us. To take advantage of that, add an enforcedPlatform clause to your build.gradle script. Example:
dependencies {
implementation enforcedPlatform("io.quarkus:quarkus-universe-bom:1.12.2.Final")
// This dependency is used by the application.
implementation group: 'io.quarkus', name: 'quarkus-resteasy'
implementation group: 'io.quarkus', name: 'quarkus-resteasy-mutiny'
// Unit and integration tests
testImplementation 'io.quarkus:quarkus-junit5'
}

Gradle dependencies in JHipster format "groupId:artifact"

I am posting here to understand how does JHipster work with Gradle dependencies, in particular with regards to the fact that I am unable to copy some of them into a Gradle submodule I have created inside my JH project.
For example, the following doesn't work in a Gradle submodule
compile "junit:junit"
Error is
Could not resolve: junit:junit
However, the classic one copied from mvnrepository works great
compile group: 'junit', name: 'junit', version: '4.12'
Some additional information: I am creating a submodule that contains a set of classes related to testing, mainly a large load of custom Hamcrest matchers copied from another project from the Ant world. The original project had a lot of spaghetti code mess, so now I am refactoring into an isolated Gradle module. The testlib module shall depend on the testing frameworks and contain everything required for writing good tests. It can be compared to spring-test project you would use to write your own Spring-based tests.
At the moment, the gradle file looks like
plugins {
id "java"
}
configurations {
providedRuntime
implementation.exclude module: "spring-boot-starter-tomcat"
}
repositories {
mavenLocal()
mavenCentral()
jcenter()
}
group 'org.example' //different from com.acme of super-project
version '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
dependencies {
compile group: 'org.assertj', name: 'assertj-core', version: '3.13.2'
compile group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.5.2'
compile group: 'org.hamcrest', name: 'hamcrest', version: '2.1'
compile group: 'org.mockito', name: 'mockito-core', version: '3.0.0'
compile group: 'org.springframework.boot', name: 'spring-boot', version: spring_boot_version
compile "junit:junit" //Fails
}
Question
So the question is in two parts:
why does the scope "orgId:name" syntax work in the JHipster-generated module but not in submodules? Is it part of standard Gradle syntax?
why is that not working in a sub-module? Does JHipster apply a custom plugin to apply the correct version number that is clearly missing? How I do the same in a sub-module that is supposed to contain only Java library code?
With regards to JHipster, a little of more investigation helped. According to this answer, there is a trick in Gradle called Bill Of Materials project, so...
TL;DR
Add the following to the sub-project
// import JHipster dependencies BOM
implementation platform("io.github.jhipster:jhipster-dependencies:${jhipster_dependencies_version}")
So that the whole block looks like
dependencies {
// import JHipster dependencies BOM
implementation platform("io.github.jhipster:jhipster-dependencies:${jhipster_dependencies_version}")
compile "org.assertj:assertj-core"
compile "org.junit.jupiter:junit-jupiter-api"
compile "org.hamcrest:hamcrest"
compile "org.mockito:mockito-core"
compile "org.springframework.boot:spring-boot"
compile "junit:junit"
}
Long answer
Maybe in the future when I will understand Gradle more. Or just edit this answer 😁 to contribute
The bom defines the versions (besides other things) of 3rd party dependencies to be used so you can omit the explicit version. If you do not use the bom you can also write compile "junit:junit:4.12" but keep in mind jhipster uses already junit5 for all tests by default.
Regarding the import of the bom you can do it like you proposed or try to apply that dependency to all gradle subprojects in your main gradle file.

Generated resource output not found in test classpath in gradle build

I am attempting to configure a gradle (version 4.6) build (as a part of a multi-module project) that uses a Java "script" to generate resources into the main sourceSet, which are then referenced in my test configuration. The idea is that I'd ultimately like to create a jar that is simply a resource bundle for inclusion in another module of my build, but I have java files both to generate these resources and to execute verification tests on them before packaging.
I currently have three sourceSets configured: the standard "main" and "test", and a custom sourceSet "generator" which holds resources used as inputs to the generator "script" and the source for the generator script itself. I've registered a main output directory according to this documentation (see "working with generated resources"), pointing to a JavaExec class that runs the generator with the "generator" sourceSet runtime classpath to output resources into the main classpath.
All of this appears to work- I can find the output in the correct directory when running :<module>:build, showing that the script is both running properly and that it is done as a dependency to the main compile task. However, when I try to reference the generated output in the tests with getClass().getClassLoader().getResource("<baseGeneratedOutputDirectory>"), I get a null value back, suggesting that my generated output is not being included in the test runtime classpath. The documentation clearly states that the...
Java plugin will use those dirs in calculating class paths and for jarring the content
...so I'm not sure why my files aren't getting picked up. Below is my abridged build.gradle file. Note that I'm overriding the generator task type in order to set it up with build caching, but I still see this bug with caching turned off.
apply plugin: 'java-library'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
sourceSets {
generator {
java.srcDirs = ['src/generator/java']
resources.srcDirs = ['src/generator/resources']
}
main {
java
resources
output.dir("$buildDir/generated-files/main", builtBy: 'generateConfig')
}
test {
java
resources
}
}
dependencies {
api project(':server:server_protobuf_classes');
api project(':common:game-config-util')
api 'com.google.protobuf:protobuf-java:3.5.1'
generatorImplementation project(':common:game-config-util')
generatorImplementation project(':server:server_protobuf_classes');
generatorImplementation group: 'commons-io', name: 'commons-io', version: '2.5'
// ...
testCompile group: 'junit', name: 'junit', version: '4.11'
testCompile group: 'org.hamcrest', name: 'hamcrest-all', version: '1.3'
testCompile group: 'commons-collections', name: 'commons-collections', version: '3.2.2'
// ...
}
task generateConfig(type: GenerateConfig) {
outputs.dir("$buildDir/generated-files/main")
classpath sourceSets.generator.runtimeClasspath
main = "com.project.ProtobufConfigurationProcessor"
}
#CacheableTask
class GenerateConfig extends JavaExec {
}
EDIT: Adding the following makes the tests pass, but I'm confused why I'd need to manually configure the test resource directory like this. Shouldn't the test task pick up build output from the main source set by default?
sourceSets {
test {
resources.srcDirs = ["$buildDir/generated-files/main"]
}
}

build.gradle: compile group vs compile, buildscript, classpath

What is the difference between "compile group" and "compile"? Just another way to define a dependency?
Ex:
compile group: 'org.slf4j', name: 'slf4j-jcl', version: '1.7.21'
And i think this also will work:
compile("org.slf4j:slf4j-jcl:1.7.21")
Why do i have the declare mavenCentral() again and another dependencies block inside the buildscript block?
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.0.RELEASE")
}
}
From my point of view, when you compile something it will be in your classPath?
compile specifies an external dependency for the project you are building. compile requires group, name, and version. These can either be broken out or specified using the short form "group:name:version". see Gradle Dependency Management Basics
The buildscript block declares the dependencies of your gradle build itself while the normal dependencies block declares the dependencies of the project you are going to build

Multiproject build: dependency to tests jar

I'm restructuring/refactoring build process for a big(ish) project. Currently it contains over a dozen separate modules built with standalone build scripts each. I want to integrate them all into a single multiproject build in Gradle.
After I integrated all sources into a single tree, fixed build.gradles, I came upon the following problem. Dependencies for many modules contain something like:
dependencies {
compile group: 'com.company', name: 'Module', version: '1.2.3'
// ...
testCompile group: 'com.company', name: 'Module', version: '1.2.3', classifier: 'tests'
}
I want the build to use jars from the subproject, not from a repository. I replaced compile ... with compile project(':Module') and it works fine. However, I cannot find the way to pass 'tests' specifier to the testCompile project... dependency.
Is there a way to pick up the tests jar as a dependency to testCompile?
In the producing project you will need to declare the "Test" JAR as outgoing artifact.
configurations {
testUtils
}
task testUtilsJar(type: Jar) {
...
}
artifacts {
testUtils testUtilsJar
}
In the consuming project you depend on it as such:
dependencies {
testCompile project(path: ':Module', configuration: 'testUtils')
}

Categories

Resources