Split the project into three modules for every actors #14
11 changed files with 85 additions and 263 deletions
26
README.md
26
README.md
|
@ -23,26 +23,26 @@ Alternatively, you can build and run the project manually by using
|
|||
[gradle](https://gradle.org/) and launching the application with [docker-compose](https://docs.docker.com/compose/).
|
||||
|
||||
```shell
|
||||
gradlew build
|
||||
# build the modules
|
||||
(cd ./applications/consumer/ && ./gradlew build)
|
||||
(cd ./applications/converter/ && ./gradlew build)
|
||||
(cd ./applications/producer/ && ./gradlew build)
|
||||
# start the docker based on the docker-compose.yaml file
|
||||
docker compose up
|
||||
```
|
||||
|
||||
## Configuration
|
||||
If you wish, you can modify the configuration of the `docker-compose.yaml` file to fit your needs.
|
||||
The configuration can be modified in the [docker-compose.yaml](./docker-compose.yaml) file to fit your needs.
|
||||
|
||||
The container `application` can be easily modified with the following environment variables :
|
||||
|
||||
| Name | Required | Format | Default | Description |
|
||||
|------------------------------|----------|-----------------------------------------------------|--------------------------------------------------------------------|---------------------------------------------------------------|
|
||||
| KAFKA_BOOTSTRAP_SERVERS | true | \<ip>[:port] | / | The Kafka server address |
|
||||
| TOPIC_TEMPERATURE_CELSIUS | false | string of alphanumeric characters, ".", "_" and "-" | temperature-celsius | The name of the Kafka topic for the temperature in Celsius |
|
||||
| TOPIC_TEMPERATURE_FAHRENHEIT | false | string of alphanumeric characters, ".", "_" and "-" | temperature-fahrenheit | The name of the Kafka topic for the temperature in Fahrenheit |
|
||||
| TEMPERATURE_LOCATION | true | \<latitude>, \<longitude> | 49.9, 2.3 ([Amiens, France](https://fr.wikipedia.org/wiki/Amiens)) | The coordinates where to get the temperatures from |
|
||||
You can find a list for each module of the project containing their individual configuration :
|
||||
- [producer](./applications/producer/README.md)
|
||||
- [consumer](./applications/consumer/README.md)
|
||||
- [converter](./applications/converter/README.md)
|
||||
|
||||
## Expectation
|
||||
The `application` container shall print the current temperature at the selected place in Fahrenheit every minute.
|
||||
You can also access this value with the REST api at the `http://localhost:8080/temperature` endpoint.
|
||||
You can also access this value with the REST api at the `http://localhost:8080/v1/temperature` endpoint.
|
||||
|
||||
## References
|
||||
The project use the [Open-Meteo API](https://open-meteo.com/) to fetch the current temperature at the
|
||||
given location.
|
||||
The project use the [Open-Meteo](https://open-meteo.com/) API to fetch the current temperature at the
|
||||
given location.
|
||||
|
|
|
@ -1,58 +1,15 @@
|
|||
# common
|
||||
# Module: Common
|
||||
|
||||
This project uses Quarkus, the Supersonic Subatomic Java Framework.
|
||||
This module contain common code that could be used between the three others modules of the application.
|
||||
|
||||
If you want to learn more about Quarkus, please visit its website: <https://quarkus.io/>.
|
||||
It implements some errors or some useful functionalities and structure to avoid redefining them in all the modules
|
||||
and making debugging easier by only modifying a single file to fix the corresponding issue everywhere.
|
||||
|
||||
## Running the application in dev mode
|
||||
## Build
|
||||
|
||||
You can run your application in dev mode that enables live coding using:
|
||||
This project is built automatically when building the others modules.
|
||||
|
||||
```shell script
|
||||
./gradlew quarkusDev
|
||||
```
|
||||
|
||||
> **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at <http://localhost:8080/q/dev/>.
|
||||
|
||||
## Packaging and running the application
|
||||
|
||||
The application can be packaged using:
|
||||
|
||||
```shell script
|
||||
However, you can still build it manually with the following command :
|
||||
```shell
|
||||
./gradlew build
|
||||
```
|
||||
|
||||
It produces the `quarkus-run.jar` file in the `build/quarkus-app/` directory.
|
||||
Be aware that it’s not an _über-jar_ as the dependencies are copied into the `build/quarkus-app/lib/` directory.
|
||||
|
||||
The application is now runnable using `java -jar build/quarkus-app/quarkus-run.jar`.
|
||||
|
||||
If you want to build an _über-jar_, execute the following command:
|
||||
|
||||
```shell script
|
||||
./gradlew build -Dquarkus.package.jar.type=uber-jar
|
||||
```
|
||||
|
||||
The application, packaged as an _über-jar_, is now runnable using `java -jar build/*-runner.jar`.
|
||||
|
||||
## Creating a native executable
|
||||
|
||||
You can create a native executable using:
|
||||
|
||||
```shell script
|
||||
./gradlew build -Dquarkus.native.enabled=true
|
||||
```
|
||||
|
||||
Or, if you don't have GraalVM installed, you can run the native executable build in a container using:
|
||||
|
||||
```shell script
|
||||
./gradlew build -Dquarkus.native.enabled=true -Dquarkus.native.container-build=true
|
||||
```
|
||||
|
||||
You can then execute your native executable with: `./build/common-1.0-SNAPSHOT-runner`
|
||||
|
||||
If you want to learn more about building native executables, please consult <https://quarkus.io/guides/gradle-tooling>.
|
||||
|
||||
## Related Guides
|
||||
|
||||
- Kotlin ([guide](https://quarkus.io/guides/kotlin)): Write your services in Kotlin
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
package fr.faraphel.common.kafka
|
||||
|
||||
import org.apache.kafka.clients.admin.Admin
|
||||
import org.apache.kafka.clients.admin.AdminClientConfig
|
||||
import org.apache.kafka.clients.admin.CreateTopicsResult
|
||||
import org.apache.kafka.clients.admin.NewTopic
|
||||
import java.util.*
|
||||
|
||||
|
||||
/**
|
||||
* A wrapper around KafkaAdminClient to simplify its configuration.
|
||||
* @param server the kafka server address
|
||||
* @param identifier the kafka identifier for the configuration
|
||||
* @see Admin
|
||||
*/
|
||||
class AdminUtils(
|
||||
private val server: String,
|
||||
private val identifier: String = "admin"
|
||||
) {
|
||||
private val adminConfig = Properties().apply {
|
||||
// set the identifier
|
||||
this[AdminClientConfig.CLIENT_ID_CONFIG] = identifier
|
||||
// set the server information
|
||||
this[AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG] = server
|
||||
}
|
||||
|
||||
private val admin = Admin.create(adminConfig)
|
||||
|
||||
/**
|
||||
* Create the topics in the kafka server.
|
||||
* @param topics the names of the topics to create.
|
||||
* @return the result of the operation.
|
||||
* @see Admin.createTopics
|
||||
*/
|
||||
fun createTopics(vararg topics: String): CreateTopicsResult {
|
||||
// convert the topics name into the corresponding operation
|
||||
val operations = topics.map { topic -> NewTopic(topic, 1, 1) }
|
||||
// run the command
|
||||
return this.admin.createTopics(operations)
|
||||
}
|
||||
}
|
|
@ -19,4 +19,3 @@ class Temperature(
|
|||
val asFahrenheit: Double
|
||||
get() = ((this.value - 273.15) * 1.8) + 32
|
||||
}
|
||||
|
||||
|
|
|
@ -1,58 +1,22 @@
|
|||
# consumer
|
||||
# Module: Consumer
|
||||
|
||||
This project uses Quarkus, the Supersonic Subatomic Java Framework.
|
||||
This module contain the code responsible for receiving values, displaying them in the container output and hosting
|
||||
the REST API where we can find the latest value received.
|
||||
|
||||
If you want to learn more about Quarkus, please visit its website: <https://quarkus.io/>.
|
||||
## Build
|
||||
|
||||
## Running the application in dev mode
|
||||
This project is built automatically when using [docker-compose](https://docs.docker.com/compose/) at the root.
|
||||
|
||||
You can run your application in dev mode that enables live coding using:
|
||||
|
||||
```shell script
|
||||
./gradlew quarkusDev
|
||||
```
|
||||
|
||||
> **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at <http://localhost:8080/q/dev/>.
|
||||
|
||||
## Packaging and running the application
|
||||
|
||||
The application can be packaged using:
|
||||
|
||||
```shell script
|
||||
However, you can still build it manually with the following command :
|
||||
```shell
|
||||
./gradlew build
|
||||
```
|
||||
|
||||
It produces the `quarkus-run.jar` file in the `build/quarkus-app/` directory.
|
||||
Be aware that it’s not an _über-jar_ as the dependencies are copied into the `build/quarkus-app/lib/` directory.
|
||||
## Configuration
|
||||
|
||||
The application is now runnable using `java -jar build/quarkus-app/quarkus-run.jar`.
|
||||
This module can be easily modified with the following environment variables :
|
||||
|
||||
If you want to build an _über-jar_, execute the following command:
|
||||
|
||||
```shell script
|
||||
./gradlew build -Dquarkus.package.jar.type=uber-jar
|
||||
```
|
||||
|
||||
The application, packaged as an _über-jar_, is now runnable using `java -jar build/*-runner.jar`.
|
||||
|
||||
## Creating a native executable
|
||||
|
||||
You can create a native executable using:
|
||||
|
||||
```shell script
|
||||
./gradlew build -Dquarkus.native.enabled=true
|
||||
```
|
||||
|
||||
Or, if you don't have GraalVM installed, you can run the native executable build in a container using:
|
||||
|
||||
```shell script
|
||||
./gradlew build -Dquarkus.native.enabled=true -Dquarkus.native.container-build=true
|
||||
```
|
||||
|
||||
You can then execute your native executable with: `./build/consumer-1.0-SNAPSHOT-runner`
|
||||
|
||||
If you want to learn more about building native executables, please consult <https://quarkus.io/guides/gradle-tooling>.
|
||||
|
||||
## Related Guides
|
||||
|
||||
- Kotlin ([guide](https://quarkus.io/guides/kotlin)): Write your services in Kotlin
|
||||
| Name | Required | Format | Default | Description |
|
||||
|-------------------------|----------|-----------------------------------------------------|---------|---------------------------------------------------|
|
||||
| KAFKA_BOOTSTRAP_SERVERS | true | \<ip>[:port] | / | The Kafka server address |
|
||||
| TEMPERATURE_TOPIC | true | string of alphanumeric characters, ".", "_" and "-" | / | The Kafka topic were the temperature can be found |
|
||||
|
|
|
@ -27,6 +27,7 @@ dependencies {
|
|||
// libraries
|
||||
implementation("io.quarkus:quarkus-kafka-client")
|
||||
implementation("io.quarkus:quarkus-kafka-streams")
|
||||
implementation("com.google.code.gson:gson:2.8.9")
|
||||
}
|
||||
|
||||
group = "fr.faraphel"
|
||||
|
|
|
@ -24,12 +24,13 @@ class Main : QuarkusApplication {
|
|||
server=kafkaServer,
|
||||
topic=topicTemperature
|
||||
) { message ->
|
||||
// format the time of the message to a proper string
|
||||
val time = timeFormatter.format(Instant.ofEpochMilli(message.timestamp()))
|
||||
// clean the values in the record
|
||||
val messageInstant = Instant.ofEpochMilli(message.timestamp())
|
||||
val messageContent = message.value()
|
||||
// print the value
|
||||
println("[${time}] ${message.value()}°F")
|
||||
println("[${timeFormatter.format(messageInstant)}] ${messageContent}°F")
|
||||
// update the value for the API
|
||||
TemperatureEndpoint.setTemperature(message.value())
|
||||
TemperatureEndpoint.updateData(messageContent, messageInstant)
|
||||
}
|
||||
|
||||
// indefinitely consume new values
|
||||
|
|
|
@ -9,7 +9,7 @@ import jakarta.ws.rs.Path
|
|||
* Always answer "Pong!"
|
||||
* Can be used to test if the API can be reached
|
||||
*/
|
||||
@Path("ping")
|
||||
@Path("/v1/ping")
|
||||
class PingEndpoint {
|
||||
/**
|
||||
* Handler for a GET request on this endpoint
|
||||
|
|
|
@ -1,23 +1,31 @@
|
|||
package fr.faraphel.consumer.rest
|
||||
|
||||
import com.google.gson.Gson
|
||||
import jakarta.ws.rs.GET
|
||||
import jakarta.ws.rs.Path
|
||||
import jakarta.ws.rs.Produces
|
||||
import jakarta.ws.rs.core.MediaType
|
||||
import java.time.Instant
|
||||
|
||||
|
||||
/**
|
||||
* This API endpoint return the latest temperature measured (in Fahrenheit)
|
||||
*/
|
||||
@Path("temperature")
|
||||
@Path("/v1/temperature")
|
||||
class TemperatureEndpoint {
|
||||
companion object {
|
||||
val jsonParser = Gson() ///< the json parser
|
||||
|
||||
private var temperature: Double? = null ///< the latest temperature value
|
||||
private var time: Instant? = null /// < the time of the latest value
|
||||
|
||||
/**
|
||||
* Setter to update the latest temperature value
|
||||
* @param temperature the new temperature value
|
||||
*/
|
||||
fun setTemperature(temperature: Double) {
|
||||
fun updateData(temperature: Double, time: Instant) {
|
||||
this.temperature = temperature
|
||||
this.time = time
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,7 +34,10 @@ class TemperatureEndpoint {
|
|||
* @return the latest temperature measured
|
||||
*/
|
||||
@GET
|
||||
fun get(): Double? {
|
||||
return temperature
|
||||
}
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
fun get(): String = jsonParser.toJson(mapOf(
|
||||
"value" to temperature,
|
||||
"time" to time?.toEpochMilli(),
|
||||
"unit" to "Fahrenheit"
|
||||
))
|
||||
}
|
||||
|
|
|
@ -1,58 +1,23 @@
|
|||
# converter
|
||||
# Module: Converter
|
||||
|
||||
This project uses Quarkus, the Supersonic Subatomic Java Framework.
|
||||
This module contain the code responsible for receiving values from a topic, converting them from
|
||||
Celsius temperature to Fahrenheit and send it back into another topic.
|
||||
|
||||
If you want to learn more about Quarkus, please visit its website: <https://quarkus.io/>.
|
||||
## Build
|
||||
|
||||
## Running the application in dev mode
|
||||
This project is built automatically when using [docker-compose](https://docs.docker.com/compose/) at the root.
|
||||
|
||||
You can run your application in dev mode that enables live coding using:
|
||||
|
||||
```shell script
|
||||
./gradlew quarkusDev
|
||||
```
|
||||
|
||||
> **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at <http://localhost:8080/q/dev/>.
|
||||
|
||||
## Packaging and running the application
|
||||
|
||||
The application can be packaged using:
|
||||
|
||||
```shell script
|
||||
However, you can still build it manually with the following command :
|
||||
```shell
|
||||
./gradlew build
|
||||
```
|
||||
|
||||
It produces the `quarkus-run.jar` file in the `build/quarkus-app/` directory.
|
||||
Be aware that it’s not an _über-jar_ as the dependencies are copied into the `build/quarkus-app/lib/` directory.
|
||||
## Configuration
|
||||
|
||||
The application is now runnable using `java -jar build/quarkus-app/quarkus-run.jar`.
|
||||
This module can be easily modified with the following environment variables :
|
||||
|
||||
If you want to build an _über-jar_, execute the following command:
|
||||
|
||||
```shell script
|
||||
./gradlew build -Dquarkus.package.jar.type=uber-jar
|
||||
```
|
||||
|
||||
The application, packaged as an _über-jar_, is now runnable using `java -jar build/*-runner.jar`.
|
||||
|
||||
## Creating a native executable
|
||||
|
||||
You can create a native executable using:
|
||||
|
||||
```shell script
|
||||
./gradlew build -Dquarkus.native.enabled=true
|
||||
```
|
||||
|
||||
Or, if you don't have GraalVM installed, you can run the native executable build in a container using:
|
||||
|
||||
```shell script
|
||||
./gradlew build -Dquarkus.native.enabled=true -Dquarkus.native.container-build=true
|
||||
```
|
||||
|
||||
You can then execute your native executable with: `./build/converter-1.0-SNAPSHOT-runner`
|
||||
|
||||
If you want to learn more about building native executables, please consult <https://quarkus.io/guides/gradle-tooling>.
|
||||
|
||||
## Related Guides
|
||||
|
||||
- Kotlin ([guide](https://quarkus.io/guides/kotlin)): Write your services in Kotlin
|
||||
| Name | Required | Format | Default | Description |
|
||||
|------------------------------|----------|-----------------------------------------------------|---------|-----------------------------------------------------------------|
|
||||
| KAFKA_BOOTSTRAP_SERVERS | true | \<ip>[:port] | / | The Kafka server address |
|
||||
| TEMPERATURE_CELSIUS_TOPIC | true | string of alphanumeric characters, ".", "_" and "-" | / | The Kafka topic were the temperature in celsius can be found |
|
||||
| TEMPERATURE_FAHRENHEIT_TOPIC | true | string of alphanumeric characters, ".", "_" and "-" | / | The Kafka topic were the temperature in fahrenheit can be found |
|
||||
|
|
|
@ -1,58 +1,23 @@
|
|||
# producer
|
||||
# Module: Converter
|
||||
|
||||
This project uses Quarkus, the Supersonic Subatomic Java Framework.
|
||||
This module contain the code responsible for getting the current temperature at a given location thanks to the
|
||||
[Open-Meteo](https://open-meteo.com/) API, and sending it into a topic.
|
||||
|
||||
If you want to learn more about Quarkus, please visit its website: <https://quarkus.io/>.
|
||||
## Build
|
||||
|
||||
## Running the application in dev mode
|
||||
This project is built automatically when using [docker-compose](https://docs.docker.com/compose/) at the root.
|
||||
|
||||
You can run your application in dev mode that enables live coding using:
|
||||
|
||||
```shell script
|
||||
./gradlew quarkusDev
|
||||
```
|
||||
|
||||
> **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at <http://localhost:8080/q/dev/>.
|
||||
|
||||
## Packaging and running the application
|
||||
|
||||
The application can be packaged using:
|
||||
|
||||
```shell script
|
||||
However, you can still build it manually with the following command :
|
||||
```shell
|
||||
./gradlew build
|
||||
```
|
||||
|
||||
It produces the `quarkus-run.jar` file in the `build/quarkus-app/` directory.
|
||||
Be aware that it’s not an _über-jar_ as the dependencies are copied into the `build/quarkus-app/lib/` directory.
|
||||
## Configuration
|
||||
|
||||
The application is now runnable using `java -jar build/quarkus-app/quarkus-run.jar`.
|
||||
This module can be easily modified with the following environment variables :
|
||||
|
||||
If you want to build an _über-jar_, execute the following command:
|
||||
|
||||
```shell script
|
||||
./gradlew build -Dquarkus.package.jar.type=uber-jar
|
||||
```
|
||||
|
||||
The application, packaged as an _über-jar_, is now runnable using `java -jar build/*-runner.jar`.
|
||||
|
||||
## Creating a native executable
|
||||
|
||||
You can create a native executable using:
|
||||
|
||||
```shell script
|
||||
./gradlew build -Dquarkus.native.enabled=true
|
||||
```
|
||||
|
||||
Or, if you don't have GraalVM installed, you can run the native executable build in a container using:
|
||||
|
||||
```shell script
|
||||
./gradlew build -Dquarkus.native.enabled=true -Dquarkus.native.container-build=true
|
||||
```
|
||||
|
||||
You can then execute your native executable with: `./build/producer-1.0-SNAPSHOT-runner`
|
||||
|
||||
If you want to learn more about building native executables, please consult <https://quarkus.io/guides/gradle-tooling>.
|
||||
|
||||
## Related Guides
|
||||
|
||||
- Kotlin ([guide](https://quarkus.io/guides/kotlin)): Write your services in Kotlin
|
||||
| Name | Required | Format | Default | Description |
|
||||
|-------------------------|----------|-----------------------------------------------------|---------|--------------------------------------------------------------|
|
||||
| KAFKA_BOOTSTRAP_SERVERS | true | \<ip>[:port] | / | The Kafka server address |
|
||||
| TEMPERATURE_TOPIC | true | string of alphanumeric characters, ".", "_" and "-" | / | The Kafka topic were the temperature in celsius can be found |
|
||||
| TEMPERATURE_LOCATION | true | \<latitude>, \<longitude> | / | The coordinates where to get the temperatures from |
|
||||
|
|
Loading…
Reference in a new issue