An MVC library for the Spark-Kotlin project
  • Kotlin 88.6%
  • Java 11.4%
Find a file
2023-08-07 14:53:29 +01:00
src Use mockk's method chaining to simplify the creation of some mocks. Use listOf instead of arrayListOf in the FileUploadsTest 2018-05-07 10:00:53 +01:00
.gitignore Initial commit of the Caisson MVC library for Spark-Kotlin. Can dynamically create an instance of a class from a Spark-Kotlin request parameter map. Some Spek tests. 2018-03-28 22:10:34 +01:00
build.gradle Bump to Mockk version to 1.8.5 2018-07-03 21:44:20 +01:00
gradlew Initial commit of the Caisson MVC library for Spark-Kotlin. Can dynamically create an instance of a class from a Spark-Kotlin request parameter map. Some Spek tests. 2018-03-28 22:10:34 +01:00
gradlew.bat Initial commit of the Caisson MVC library for Spark-Kotlin. Can dynamically create an instance of a class from a Spark-Kotlin request parameter map. Some Spek tests. 2018-03-28 22:10:34 +01:00
README.md Update README.md 2023-08-07 14:53:29 +01:00
settings.gradle Initial commit of the Caisson MVC library for Spark-Kotlin. Can dynamically create an instance of a class from a Spark-Kotlin request parameter map. Some Spek tests. 2018-03-28 22:10:34 +01:00

Caisson

An MVC library for the Spark-Kotlin project

PROJECT CLOSED

Caisson is an attempt introduce some basic MVC functionality to the Spark-Kotlin project. It is inspired by SpringMVC, but with a much smaller and simpler scope. Step one is to introduce model binding and converters to Spark-Kotlin, using annotations and reflection to construct instances of Kotlin classes from a Spark-Kotlin request parameter map.

Users of the library will be able to bind any model class from a spark-kotlin request, mapping the request param names to the constructor parameters for the model. For instance, to bind the Person model from the spark-kotlin request, simply call the bind<>() function on the request, supplying the model class in the generics diamonds.

post("/addPerson") {
  val person = request.bind<Person>()
  println("person is ${person?.name}, born on ${person?.date}")
}

This assumes the following Person model and a custom converter class (annotated with @CConverter) to parse the request parameter string. Note that only fields defined in the class's primary constructor can be bound; you are welcome to add additional fields or calculated values in the class's init { } block. A data class is an obvious choice for a model, but ordinary classes work too.

data class Person(val name:String, @CConverter(converterClass = SimpleDateConverter::class) val date: Date)

class SimpleDateConverter : Converter {
	override fun convert(from: String): Date? {
		val sdf: SimpleDateFormat = SimpleDateFormat("dd/MM/yyyy")
		try {
			return sdf.parse(from)
		} catch (e: ParseException) {
			return Date()
		}
	}
}

File uploads

To implement file uploading, your model class must contain a field of type CaissonMultipartContent (or a List of these). Caisson will store each of the uploaded files' bytestreams in the CaissonMultipartContent object:

data class MyFiles(val upload: List<MultipartCaissonContent>)

And use these classes with Spark-Kotlin's normal request object. You must specify the names of the HTML input components used.

<form name="fileUpload">
  <input type="file" name="upload">
  <input type="file" name="upload">
</form>
val myFiles = request.bind<MyFiles>(arrayListOf("upload"))

Alternatively, if each input component has a different name, supply a List of their names as the third parameter.

<form name="fileUpload">
  <input type="file" name="drivingLicense">
  <input type="file" name="passport">
</form>
val myFiles = request.bind<MyFiles>(arrayListOf("drivingLicense","passport"))

This project is in the very earliest stages, and I have a lot to learn about Kotlin, HTTP requests, Reflection and more besides. So don't even think of using it :). There is a corresponding demo project hosted on github called https://github.com/v79/spark-caisson-integration which implements all the features of Caisson and may prove useful while I'm still working on the documentation.