Skip to content

Commit 4faee31

Browse files
Spring example (#20)
* Add spring web example * update base project name (not only sdk)
1 parent b070aba commit 4faee31

File tree

3 files changed

+108
-7
lines changed

3 files changed

+108
-7
lines changed

examples/README.md

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
* [About the examples](#about-the-examples)
44
* [Running the examples](#running-the-examples)
55
* [Prerequisites](#prerequisites)
6-
* [Java HTTP Server](#java-http-server)
6+
* [Spring](#spring)
77
* [Ktor](#ktor)
8+
* [Java HTTP Server](#java-http-server)
89

910
## About the examples
1011

@@ -20,21 +21,30 @@ All are a simple counter implemented using Datastar server-sent events.
2021

2122
To make the examples work as simply as possible, each back implementation is a JBang script.
2223

23-
JBang is a tool that allows to run Kotlin scripts taking care of all the dependencies without the need to use more heavy weight tools like Maven or Gradle.
24+
JBang is a tool that allows to run Kotlin scripts taking care of all the dependencies without the need to use more heavyweight tools like Maven or Gradle.
2425
You can find the installation instructions on the [official documentation](https://www.jbang.dev/documentation/jbang/latest/installation.html).
2526

26-
### Java HTTP Server
27+
### Spring
2728

28-
This example uses the plain Java `HttpServer` to serve the front end. ([code](java-httpserver/server.kt))
29+
This example uses `Spring` to serve the front end. ([code](spring/server.kt))
2930

3031
```shell
31-
cd ./java-httpserver ; jbang server.kt ; cd ..
32+
cd ./spring ; jbang server.kt ; cd ..
3233
```
3334

3435
### Ktor
3536

36-
This example uses the `Ktor` to serve the front end. ([code](ktor/server.kt))
37+
This example uses `Ktor` to serve the front end. ([code](ktor/server.kt))
3738

3839
```shell
3940
cd ./ktor ; jbang server.kt ; cd ..
4041
```
42+
43+
### Java HTTP Server
44+
45+
This example uses the plain Java `HttpServer` to serve the front end. ([code](java-httpserver/server.kt))
46+
47+
```shell
48+
cd ./java-httpserver ; jbang server.kt ; cd ..
49+
```
50+

examples/spring/server.kt

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import dev.datastar.kotlin.sdk.Response
2+
import dev.datastar.kotlin.sdk.ServerSentEventGenerator
3+
import kotlinx.coroutines.flow.MutableStateFlow
4+
import kotlinx.coroutines.runBlocking
5+
import org.springframework.boot.SpringApplication
6+
import org.springframework.boot.SpringBootConfiguration
7+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
8+
import org.springframework.context.annotation.Import
9+
import org.springframework.http.HttpStatus
10+
import org.springframework.http.MediaType
11+
import org.springframework.web.bind.annotation.GetMapping
12+
import org.springframework.web.bind.annotation.PostMapping
13+
import org.springframework.web.bind.annotation.ResponseStatus
14+
import org.springframework.web.bind.annotation.RestController
15+
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody
16+
import java.io.File
17+
import java.io.OutputStream
18+
import java.io.OutputStreamWriter
19+
20+
///usr/bin/env jbang "$0" "$@" ; exit $?
21+
//JAVA 21
22+
//KOTLIN 2.2.0
23+
//DEPS dev.data-star.kotlin:kotlin-sdk:1.0.0-RC1
24+
//DEPS org.springframework.boot:spring-boot-starter-web:3.5.5
25+
//DEPS org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2
26+
27+
fun main() {
28+
SpringApplication.run(CounterApp::class.java)
29+
}
30+
31+
@SpringBootConfiguration
32+
@EnableAutoConfiguration
33+
@Import(CounterController::class)
34+
open class CounterApp
35+
36+
@RestController
37+
class CounterController {
38+
39+
private val counter = MutableStateFlow(0)
40+
41+
@GetMapping("/", produces = [MediaType.TEXT_HTML_VALUE])
42+
@ResponseStatus(HttpStatus.OK)
43+
fun index() = StreamingResponseBody { stream ->
44+
File("../front/counter.html").inputStream().use { inputStream ->
45+
inputStream.transferTo(stream)
46+
}
47+
}
48+
49+
@GetMapping("/counter", produces = [MediaType.TEXT_EVENT_STREAM_VALUE])
50+
@ResponseStatus(HttpStatus.OK)
51+
fun counter() = StreamingResponseBody { stream ->
52+
runBlocking {
53+
val response = adapterResponse(stream)
54+
val generator = ServerSentEventGenerator(response)
55+
counter.collect { event ->
56+
generator.patchElements("""<span id="counter">${event}</span>""")
57+
58+
if (event == 3) {
59+
generator.executeScript("""alert('Thanks for trying Datastar!')""")
60+
}
61+
}
62+
}
63+
}
64+
65+
66+
@PostMapping("/increment")
67+
@ResponseStatus(HttpStatus.NO_CONTENT)
68+
fun increment() {
69+
counter.value++
70+
}
71+
72+
@PostMapping("/decrement")
73+
@ResponseStatus(HttpStatus.NO_CONTENT)
74+
fun decrement() {
75+
counter.value--
76+
}
77+
78+
private fun adapterResponse(stream: OutputStream): Response = object : Response {
79+
private val writer = OutputStreamWriter(stream)
80+
81+
override fun sendConnectionHeaders(
82+
status: Int,
83+
headers: Map<String, List<String>>
84+
) = Unit
85+
86+
override fun write(text: String) = writer.write(text)
87+
88+
override fun flush() = writer.flush()
89+
90+
}
91+
}

settings.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ plugins {
22
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
33
}
44

5-
rootProject.name = "datastar-kotlin-sdk"
5+
rootProject.name = "datastar-kotlin"
66

77
include("sdk")

0 commit comments

Comments
 (0)