This message was deleted.
# community-support
s
This message was deleted.
v
You can add it to the classpath, but most probably you should not do however you try to do it right now. šŸ˜„ Such use-cases are one of the main use-cases for Shared Build Services.
j
Thanks, if there's a better way to do it, I'm all in
šŸ‘Œ 1
I'd like all the logic to stay in the gradle script, it seems that to use Shared Build Services I have to create some sort of gradle plugin, which seems overkill to me given the amount of code. How can I add it to the classpath?
v
You don't need to create a plugin, you can also have the build service class right in your build script. Although it is trivial to create a plugin project and it has advantages like better maintainable, better understandable, testable, ...
If you just want to add a class to the build script, just do it, like
buildscript { dependencies { classpath("...") } }
. But really, a shared build service is the way to go for various reasons. When for example would you stop the testcontainer? In
doLast
of
test
? What if the tests failed and thus the
doLast
is not executed? In a
finalizedBy
task of
test
? What if liquibase task already failed and thus
test
is not even started? ...?
j
Yes you're right.
šŸ‘Œ 1
Can I access the Shared Build Service instance from a doFirst lambda ?
I need to get the random port of the container
to configure the task before its run
v
Yes, that's where you should do it. By accessing it there, you make sure it is created and bootstrapped the instance, providing you with any information you need. And if the task is skipped, for example because all tests are up-to-date, it will not be done. But if you say "configure the task" then only if you do not mean that you want to change the task configuration, because changing task configuration at execution time is highly discouraged or with configuration cache even forbidden.
If you need that port then as system property in the tests for example, you could probably use a
CommandLineArgumentProvider
as `jvmArgumentProviders`to lazily get the port from the service only if the task is actually going to be executed then.
Something like this:
Copy code
abstract class Foo : BuildService<BuildServiceParameters.None> {
    val port: Int

    init {
        port = Random.nextInt()
    }
}
val foo = gradle.sharedServices.registerIfAbsent("foo", Foo::class) {}
tasks.test {
    usesService(foo)
    jvmArgumentProviders.add(object : CommandLineArgumentProvider {
        override fun asArguments(): Iterable<String> =
            listOf("-DserverPort=${foo.get().port}")
    })
}
😲 1
j
I need the port for these 3 tasks : • Run liquibase to create the scema • Run Jooq Codegen to generate model Objects from the schema • Run tests (as in your example) I'll look into the
CommandLineArgumentProvider
to see if I can use it with liquibase
update
and
jooqcodegen
v
LiquibaseTask
extends
JavaExec
, so you can use the same there if setting as jvm arg is what you need there too
j
Indeed, it would work in that case with Liquibase. But JOOQ codegen on the other hand ... https://github.com/jOOQ/jOOQ/blob/main/jOOQ-codegen-gradle/src/main/java/org/jooq/codegen/gradle/CodegenTask.java Thanks for your help so far! I think I'll use a static port for now, even though the build may fail on rare occasions.
v
Where / how on that task would you need to set that port?
j
It's the JDBC URL, it contains the port
v
Where / how on that task would you configure the JDBC URL?
j
Copy code
project.jooq.executions[*].configuration.jdbc.url
in the build script it looks like :
Copy code
jooq {
    executions {
        create("main") {
            configuration {
                jdbc {
                    username = DB_USERNAME
                    password = DB_PASSWORD
                    url = "<postgresql://localhost>:RANDOMPORT/db_name"
                }
v
So not on the task at all, that is their extension. Well, depends on how that is implemented. If you can for example somehow lazily set that url, or it is lazily calculated, you could probably use the service there. But I don't know, never used jooq
j
type of jdbc is org.gradle.api.Action<MetaExtensions.JdbcExtension> Can it be lazily calculated ?
v
Sure it can, but I have no idea whether it is
j
I'll try and see
The action seems to be executed immediately, so the SharedBuildService is instanciated at configuration if I do :
Copy code
url = containerProvider.get().db.getJdbcUrl()
v
Yes, so then post a feature request to that jooq plugin to provide a way to lazily configure it and only if necessary, for example by calling these actions lazily only when needed, or by providing `Property`s for configuration or whatever. In the meantime, you probably have to use that static port configuration then.
j
Will do, thanks!
v
You can also see it easily by doing
Copy code
jooq {
    configuration {
        jdbc {
            println("setting url")
        }
    }
}
and then calling
gw help -m
You will get
setting url
printed and then a sax parse exception
j
yes, I did that as well šŸ™‚
v
Even without your requirement, this is pretty bad, as it is total waste of time to do these actions if there is nothing that needs it going to be executed
So that plugin is not following best practices anyway šŸ™‚
j
indeed
will report that as well, is there guidelines or documentation on these best practices to follow when writing a plugin?
v
There are some things mentioned in the Gradle docs, but for sure not everything. But doing unnecessary work is always a bad idea. šŸ˜„
j
Issue created: https://github.com/jOOQ/jOOQ/issues/16188 Once again thank you so much for your time!
šŸ‘Œ 1