Skip to content

Commit

Permalink
add ad-kotlin module in online-boutique (#510)
Browse files Browse the repository at this point in the history
  • Loading branch information
worstell authored Oct 19, 2023
1 parent 123ed41 commit e6eb05e
Show file tree
Hide file tree
Showing 2 changed files with 255 additions and 0 deletions.
177 changes: 177 additions & 0 deletions examples/online-boutique/services/ad-kotlin/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>
<groupId>xyz.block</groupId>
<artifactId>ad-kotlin</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<ftl.version>1.0-SNAPSHOT</ftl.version>
<java.version>11</java.version>
<kotlin.version>1.9.0</kotlin.version>
<kotlin.compiler.incremental>true</kotlin.compiler.incremental>
</properties>

<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>ftl-runtime</artifactId>
<version>${ftl.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>ftl-generator</artifactId>
<version>${ftl.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
<configuration>
<compilerPlugins>
<compilerPlugin>ksp</compilerPlugin>
</compilerPlugins>
<pluginOptions>
<option>ksp:apoption=dest=${project.build.directory}</option>
</pluginOptions>
</configuration>
<dependencies>
<dependency>
<groupId>com.dyescape</groupId>
<artifactId>kotlin-maven-symbol-processing</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>ftl-runtime</artifactId>
<version>${ftl.version}</version>
</dependency>
</dependencies>
</plugin>
<!-- Download the Wire compiler. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>xyz.block</groupId>
<artifactId>ftl-generator</artifactId>
<version>${ftl.version}</version>
<classifier>jar-with-dependencies</classifier>
<destFileName>ftl-generator.jar</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
<execution>
<id>copy-dependencies</id>
<phase>compile</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/dependency</outputDirectory>
<includeScope>runtime</includeScope>
</configuration>
</execution>
<execution>
<id>build-classpath</id>
<phase>compile</phase>
<goals>
<goal>build-classpath</goal>
</goals>
<configuration>
<outputFile>${project.build.directory}/classpath.txt</outputFile>
<prefix>dependency</prefix>
</configuration>
</execution>
</executions>
</plugin>
<!-- Run the Wire compiler -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>java</executable>
<arguments>
<argument>-jar</argument>
<argument>target/dependency/ftl-generator.jar</argument>
<argument>--endpoint=http://127.0.0.1:8892</argument>
<argument>--dest=${project.build.directory}</argument>
<argument>--module=ad</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/ftl</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package ftl.ad

import com.google.gson.Gson
import com.google.gson.annotations.SerializedName
import com.google.gson.reflect.TypeToken
import xyz.block.ftl.Context
import xyz.block.ftl.Ingress
import xyz.block.ftl.Method
import xyz.block.ftl.Verb
import xyz.block.ftl.serializer.makeGson
import java.util.*

data class Ad(@SerializedName("RedirectURL") val redirectUrl: String, @SerializedName("Text") val text: String)
data class AdRequest(val contextKeys: List<String>)
data class AdResponse(val ads: List<Ad>)

class AdModule {
private val database: Map<String, Ad> = loadDatabase()

@Throws(Exception::class)
@Verb
@Ingress(Method.GET, "/get")
fun get(context: Context, req: AdRequest): AdResponse {
return when {
req.contextKeys.isNotEmpty() -> AdResponse(ads = contextualAds(req.contextKeys))
else -> AdResponse(ads = randomAds())
}
}

private fun contextualAds(contextKeys: List<String>): List<Ad> {
return contextKeys.map { database[it] ?: throw Exception("no ad registered for this context key") }
}

private fun randomAds(): List<Ad> {
val ads = mutableListOf<Ad>()
val random = Random()
repeat(MAX_ADS_TO_SERVE) {
ads.add(database.entries.elementAt(random.nextInt(database.size)).value)
}
return ads
}

companion object {
private const val MAX_ADS_TO_SERVE = 2
private const val DATABASE_JSON = "{\n" +
" \"hair\": {\n" +
" \"RedirectURL\": \"/product/2ZYFJ3GM2N\",\n" +
" \"Text\": \"Hairdryer for sale. 50% off.\"\n" +
" },\n" +
" \"clothing\": {\n" +
" \"RedirectURL\": \"/product/66VCHSJNUP\",\n" +
" \"Text\": \"Tank top for sale. 20% off.\"\n" +
" },\n" +
" \"accessories\": {\n" +
" \"RedirectURL\": \"/product/1YMWWN1N4O\",\n" +
" \"Text\": \"Watch for sale. Buy one, get second kit for free\"\n" +
" },\n" +
" \"footwear\": {\n" +
" \"RedirectURL\": \"/product/L9ECAV7KIM\",\n" +
" \"Text\": \"Loafers for sale. Buy one, get second one for free\"\n" +
" },\n" +
" \"decor\": {\n" +
" \"RedirectURL\": \"/product/0PUK6V6EV0\",\n" +
" \"Text\": \"Candle holder for sale. 30% off.\"\n" +
" },\n" +
" \"kitchen\": {\n" +
" \"RedirectURL\": \"/product/9SIQT8TOJO\",\n" +
" \"Text\": \"Bamboo glass jar for sale. 10% off.\"\n" +
" }\n" +
"}"

private fun loadDatabase(): Map<String, Ad> {
return makeGson().fromJson<Map<String, Ad>>(DATABASE_JSON)
}

inline fun <reified T> Gson.fromJson(json: String) = fromJson<T>(json, object : TypeToken<T>() {}.type)
}
}

0 comments on commit e6eb05e

Please sign in to comment.