Dear bnd community,
TL;DR
First of I didn’t pick the typical way of education to become a developer. I started off as a gardener interested in programming. Please be patient, if my level of knowledge is uncomplete.
I started at a small company planning to move to another platform. During dev internal meetings I heard conversations about Spring Boot, but it seems like leaders are very uncertain about which direction they should take. Of course my personal favorite is OSGi.
Unfortunately they doesn’t know all too much about it. To make them ever consider OSGi for future projects, migration has to be as easy as possible and I have to kickstart it on my own.
Thank god there is bnd, which abstracts away almost all the hard lifting - from assembly up to provisioning. The code generation part is perfectly covered.
The next thing which came into mind is code creation: IDE support. Intellij (read on) has good support for Gradle Kotlin DSL which provides in-place documentation out-of-the-box through code completion. Luckily there are language server projects aiming Kotlin as well, which are becoming better and better. Some of which have experimental Gradle Kotlin DSL support.
So the road I am thinking of is: Gradle Kotlin DSL -> bnd Kotlin DSL -> bndlib.
I started experimenting with a small project which maps basic bnd operations to a bnd string/script.
Showcase 1 - Basic Bnd Kotlin DSL
val instructions = bnd {
includeDefaults()
definePlugins()
defineConnections() // intented to setup connection settings but if I could directly use repositories provided by Gradle this would be obsolete
defineRepositories()
bndToolsTemplate(
type = MyConstants.Bndtools.Template.PROJECT,
name = project.name,
category = "Bnd Kotlin DSL samples"
) {
println("Run additional configuration logic in here")
println("This closure is valid but not necessary")
icon(project.file("resources/icon.png")) // Gradle's project instance
}
importPackage {
pattern("org.jetbrains.kotlin.*")
pattern("*")
patterns += "*" // possible as well
optional = true
}
bndPomRepository {
releaseUrl += repositories.mavenCentral().artifactUrls
}
mavenBndRepository {
poll_time = 4
releaseUrl += "https://repo.maven.apache.org/maven2/"
snapshotUrl += releaseUrl
label = "maven.central"
order = 0
}
}
Showcase 2 - Extensibility through extension functions:
/**
* following extension function would normally sit in a organization specific plugin
*/
fun Instructions.includeDefaults() {
include(URI("http://etcd.mycompany.local/build/env"))
include(rootProject.file("cnf/build.bnd"))
}
fun Instructions.defineConnections() {
connectionSettings {
maven()
bnd()
server {
// custom server settings
}
}
include(rootProject.file("cnf/build.bnd"))
}
fun Instructions.definePlugins() {
springComponent {
println("Configure SpringComponent plugin")
order = 100
}
}
fun Instructions.defineRepositories() {
val mycompanyrepo = mavenBndRepository("MyCompanyRepo") {
releaseUrls += project.repositories.get("mycompanyrepo").artifactUrls
order = 0
}
releaseRepo(mycompanyrepo)
baselineRepo(mycompanyrepo)
}
/**
* Extension functions which could be provided by 3rd party plugins
*/
fun Instructions.bndtoolsTemplate(
type: String = "project",
name: String = "Bndtools Template",
category: String = "templates"
): BndtoolsTemplateInstruction {
val instance = BndtoolsTemplateInstruction()
instance.type = type
instance.name = name
instance.category = category
return instance
}
fun Instructions.bndtoolsTemplate(
type: String = "project",
name: String = "Bndtools Template",
category: String = "templates",
configuration: BndtoolsInstruction.()->Unit
) {
val instance = bndtoolsTemplate(type, name, category)
configuration.invoke(instance)
return instance
}
Simply press ALT+TAB and voilá, You got documentation out of the box. Even with this simple instruction set, it’s already a joy to use.
But
At the moment these Instruction implementations share an print(PrintConfiguration)
method returning the generated String
which feels like back and forth when looking (superficially) at bndlib internals: I am serializing the build logic so that bndlib can deserialize it again!
Kotlin is a strongly typed language and as such, mapping to a dynamic language (which I consider bnd is) can sometimes be cumbersome.
Regarding direct access to classes in Gradle, classloader magic comes into mind.
Conclusion
I am really sorry, I don’t know that much about the bnd workflow. Up until now I had my projects prepopulated by templates which were just building good and I never questioned it. But now I am in front of a project, which needs deeper / more complex understandings of bnd.
Having good IDE (I like VS Code setup headless as a remote HTTP server connecting to my electron client app as well) support is a personal itch to me, even if my company won’t move to OSGi.
I am not asking You to do my work, but sometimes listening to experts helps alot, before walking 200km into the wrong direction.
Much thanks in advance
Adrian
BTW This is my first try getting involved into a open source project