Are Kotlin DSLs (typesafe builders) only for use i...
# server
a
Are Kotlin DSLs (typesafe builders) only for use internally by application developers? Want to create and expose a DSL for "power" end-users to define some complex objects that are currently quite tedious via a point-and-click UI, but think this is not possible. Allowing them to define via JSON/YAML is an option but the DSL format is even easier to use and validate.
v
Sure it is. Perfect example is Gradle. It provides a Kotlin DSL for its users to write build scripts in.
a
I wrote a blog post about just this, hope you find it helpful https://blog.devgenius.io/writing-a-dsl-in-kotlin-42a9029b93a6
a
@Vampire The people who use the Gradle Kotlin DSL are application developers. I'm talking about the end users of an application... like could they build an object with the DSL in a web form and submit it? Or write it in a separate file (instead of a JSON/YAML file) and reference it on the command line for processing?
v
What is the difference whether they are developers or not? The point is, the build script is a file with Kotlin DSL content that is interpreted by Gradle. So yes, you can also submit that via web form or supply a file on the command line. Latter you can also do with Gradle build scripts.
a
Maybe I'm not asking the right way... can you submit a file or string following a DSL's rules to a compiled Kotlin app and have the app convert it into Kotlin objects?
The more I'm thinking about this, I think the difference is the DSL requires the compiler to create objects. Gradle reads the file pre-compilation so it works. End users are interacting with a compiled application. JSON libs like Moshi or Jackson perform serialization (JSON <--> Kotlin objects). Those libs don't exist for DSLs, the compiler does it.
v
How often do I need to repeat it? Yes, it is. And no, Gradle does not need any pre-compilation. It just does it as you usually execute the same build script several times and so it is more performant to precompile and use the result than to work from the source for each invocation.
You can either need the embedded compiler to compile in your application and then execute if you have similar needs, or you can simply use #scripting to just interpret the script on-the-fly.
a
OK so if I receive a JSON file as the body of an HTTP post request, I can use Jackson or Moshi to deserialize it. How do I do it if instead of JSON, the POST body is an object definition as a DSL format?
v
You can use Moshi or Jackson, but I would actually use
kotlinx.serialization
. And I already told you that you use #scripting support for example. Your DSL is a Kotlin Script and you evaluate it. How exactly this is done depends on the concrete requirements, but I guess you should start with reading the documentation and then maybe ask in the proper channel.
a
I wish this was a helpful exchange because this is what I would like to accomplish however I don't see any examples of what you say is "simple" in 3 days of Google searching and documentation review. Let me be clear I am not talking about Gradle, I am trying to implement a DSL (as an alternative to JSON or YAML), as a way for end users of my JVM web (ktor or http4k) application to submit data objects. In other words: instead of submitting JSON
Copy code
{ 'type':'car',
  'model':'Subaru',
  'parts':{
    'tires':{'brand':'Yokohama', 'size':'285/35R19'},
    'oil':{'brand':'Mobil 1', 'viscosity':'0W40'},
  }
}
the users could submit something like this:
Copy code
car {
  model = 'subaru'
  tires {
    brand = 'Yokohama'
    size = '285/35R19'
  }
  oil(brand = 'Mobil 1', viscosity = '0W40')
}
v
I wish this was a helpful exchange
Me too, but you just repeat your inital question with different words multiple times and do not accept the answer I already understood when you asked the first time. Doesn't change my answer. And I never said it is "simple", I said it is "possible" and that you should read about and ask in #scripting on how to actually do it best.
I just provided Gradle as an example where exactly that is done. A user of Gradle provides something using a Kotlin DSL and Gradle interprets and processes it.
d
This may be something close to what you're hoping to do? https://kotlinexpertise.com/run-kotlin-scripts-from-kotlin-programs/
g
Just some ‘side remarks’: • I don’t really know what is the confidence your end users have with writing code but unless they actually are programmers I would not expect to much external users to especially enjoy using very programmatic apis. Even though it is possible, you have to balance the cost to potentially support those users that are not as comfortable with coding rules… Maybe it is worth it 🙂 • More importantly, when I read ideas where people want code to be interpreted at runtime I usually think it is not quite a good idea since it is a very nice back-door to inject malicious code. The recent Log4J vulnerability is a good example of where that kind of idea can lead… you know better than me what are your needs of course, and you probably already considered that… but I still think it’s worth emphasizing it for those who might read this feed 😛
👍 1
a
@Guillaume Taffin Great points, you are absolutely right. I'm helping a company build a tool for "power users" to bypass a very old desktop application. Define the objects using JSON rather than point-and-click through more than a dozen individual screens with lots of options. I thought instead of JSON or YAML maybe I could design a DSL that would be even easier and have some business logic built in. But you make a good point -- using a DSL you are writing code, it might look similar to JSON but it is much more powerful. And the more I think about that (and the fact they have no tooling), the less I expect the end users to be able to be successful. Leaning more towards writing a JSON Schema doc, using an off-the-shelf JSON validator and calling it a day. Thanks.
@David Saff Thank you, this is definitely the closest I've seen to what I was imagining. However the scripts still involve some Kotlin boilerplate such as `import`s and variable declarations. Even if I were to build a system to insert just the parts between
html {
and
}
the end users wouldn't have the tooling (code completion, all the other advantages of an IDE) to rapidly build a valid object. I will look into this more however, thank you.
@Vampire I appreciate your help Bjorn, perhaps some things that seem basic to you about how Gradle works or about the Scripting API are a bit higher-level than the applications I've built in the past. Thank you.
v
It's Björn, or Bjoern, not Bjorn. ;-) Why are you constantly putting words in my mouth? I also never said how Gradle is doing it is basic or easy, let alone you would be able to copy&paste. I just showed it as example that is doing exactly what you asked for to answer the question whether it is possible to do so and told you where to better ask about the topic.
l
@andyg This might also be relevant for you https://www.jetbrains.com/mps/
a
wow, this is actually very cool. thanks!