Repository files navigation

Build Status

Spring Fu (for functional APIs) is an experimental Kotlin micro-framework based on functional configuration intended to test ideas for upcoming Spring Boot releases. It makes it easy to create lightweight Spring-powered applications with functional APIs instead of annotations. See the reference documentation for more details.

Overview

A simple Spring Fu web application rendering an HTML page and exposing a JSON HTTP endpoint looks like that:

funmain(args:Array<String>) = application {
bean<UserRepository>()
bean<UserHandler>()
webflux {
val port =if (profiles.contains("test")) 8181else8080
server(netty(port)) {
mustache()
codecs {
jackson()
}
routes(ref = ::routes)
}
}
}.run(await =true)
funroutes() = routes {
val userHandler = ref<UserHandler>()
GET("/", userHandler::listView)
GET("/api/user", userHandler::listApi)
}

It leverages a subset of Spring Boot, Spring Framework, Spring Data and Spring Security to provide an alternative configuration model for developing applications in Kotlin.

  • Functional bean registration instead of JavaConfig for both internals and application

  • Features are configured explicitly via expressive configuration leveraging Kotlin domain-specific languages (DSL)

  • Flexible programmatic configuration

  • Leverage a subset of Spring Boot

  • Minimal reflection usage

  • No classpath scanning

  • No annotation processing

  • Modules provide configuration DSL and dependencies for other Spring projects and JVM ecosystem

  • Reactive and coroutines web client and server based on WebFlux functional API

  • Reactive and coroutines persistence via Spring Data (MongoDB supported)

  • No blocking web/persistence support is provided since coroutines provides support for imperative programming.

Upcoming features:

In addition to the whole Spring and Reactor teams, credits to Thomas Girard for its spring-webflux-kotlin-dsl experiment that initially demonstrated this approach was possible and to Konrad Kaminski for his awesome spring-kotlin-coroutine project.

Please send us your feedback on the #spring channel of Kotlin Slack. Feel free to open issues, contribute fixes or new modules via pull requests.

Getting started

Spring Fu 0.0.1 is currently under active development so no release is available yet, but you have can try 0.0.1.BUILD-SNAPSHOT builds.

Bootstrap

A Spring Fu bootstrap is an archive containing minimal project templates designed to allow you getting started quickly and easily Spring Fu applications. To start a new project, download a bootstrap .zip archive, extract it and follow README.adoc instructions.

Documentation

To start with Spring Fu, you can read the reference documentation.

API documentation will be available shortly.

You can have a look to the sample applications:

Functional configuration

Spring Fu functional configuration is leveraging Kotlin DSL that allows you to configure your application explicitly. Each custom block like configuration, actuators or webflux is in fact a more high level beans {} block with a custom DSL provided for easy configuration. Since this configuration is code, you can use any kind of custom programmatic bean registration without having to implement your own @Conditional annotation.

Here is an example of a typical Spring Fu application functional configuration.

funmain(args:Array<String) = application {
configuration {
AppConfiguration(name = env["SYSTEM_ENV"] ?: "default")
}
actuators(beans = false, mapping = false)
logging {
level(INFO)
level("org.springframework", DEBUG)
logback {
consoleAppender()
rollingFileAppender(file =File("log.txt"))
}
}
profile("data") {
bean<UserRepository>()
bean<ArticleRepository>()
mongodb(uri = "mongodb://myserver.com/foo")
listener<ContextStartedEvent> {
ref<UserRepository>().init()
ref<ArticleRepository>().init()
}
}
profile("web") {
bean<HtmlHandler>()
bean<ApiHandler>()
webflux {
val port = if (profiles.contains("test")) 8181 else 8080
server(netty(port)) {
cors(origin = "example.com")
mustache()
codecs {
jackson()
protobuf()
}
routes(ref = ::routes)
security { // TODO }
}
client {
codecs {
jackson()
}
}
}
}
}.app.run(await = true, profiles = "data, web")
data class AppConfiguration(
val name: String,
val remoteUrl: String = "http://localhost:8080"
)
fun routes() = routes {
val htmlHandler = ref<HtmlHandler>()
val apiHandler = ref<ApiHandler>()
GET("/", htmlHandler::blog)
GET("/article/{id}", htmlHandler::article)
"/api".nest {
GET("/", apiHandler::list)
POST("/", apiHandler::create)
PUT("/{id}", apiHandler::update)
DELETE("/{id}", apiHandler::delete)
}
}

Comparison with JavaConfig

Functional bean definition allows to define beans in an efficient way with minimal reflection usage, no proxy and with a concise Kotlin DSL that takes advantage of reified type parameters to avoid type erasure. The beans {} block is in fact a regular ApplicationContextInitializer.

JavaConfig

Functional bean definition

 @Configuration
classMyConfiguration {
@Bean
funfoo() =Foo()
@Bean
funbar(foo:Foo) =Bar(foo)
}
val myConfiguration = beans {
bean<Foo>()
// Implicit autowiring by constructor
bean<Bar>()
}

Comparison with @Component

Functional bean definition is explicit, does not imply any classpath scanning and supports constructor parameters autowiring.

@Component scanning

Functional bean definition

@Component
classFoo {
// ...
}
@Component
classBar(privatevalf:Foo) {
// ...
}
classFoo {
// ...
}
classBar(privatevalf:Foo) {
// ...
}
beans {
bean<Foo>()
bean<Bar>()
}

Comparison with controllers

Kotlin WebFlux router provides a simple but powerful way to implement your web application. HTTP API, streaming but also view rendering are supported.

Annotation-based controller

Kotlin WebFlux routes

@RestController
@RequestMapping("/api/article")
classMyController(privatevalr:MyRepository) {
@GetMapping("/")
funfindAll() =
r.findAll()
@GetMapping("/{id}")
funfindOne(@PathVariable id:Long) =
repository.findById(id)
}
}
routes {
val r = ref<MyRepository>()
"/api/article".nest {
GET("/") {
r.findAll()
}
GET("/{id}") {
val id = it.pathVariable("id")
r.findById(id)
}
}
}

About

Spring Fu is an experimental Kotlin micro-framework based on functional configuration intended to test new ideas for future Spring Boot releases

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Build Status

Spring Fu (for functional APIs) is an experimental Kotlin micro-framework based on functional configuration intended to test ideas for upcoming Spring Boot releases. It makes it easy to create lightweight Spring-powered applications with functional APIs instead of annotations. See the reference documentation for more details.

Overview

A simple Spring Fu web application rendering an HTML page and exposing a JSON HTTP endpoint looks like that:

funmain(args:Array<String>) = application {
bean<UserRepository>()
bean<UserHandler>()
webflux {
val port =if (profiles.contains("test")) 8181else8080
server(netty(port)) {
mustache()
codecs {
jackson()
}
routes(ref = ::routes)
}
}
}.run(await =true)
funroutes() = routes {
val userHandler = ref<UserHandler>()
GET("/", userHandler::listView)
GET("/api/user", userHandler::listApi)
}

It leverages a subset of Spring Boot, Spring Framework, Spring Data and Spring Security to provide an alternative configuration model for developing applications in Kotlin.

  • Functional bean registration instead of JavaConfig for both internals and application

  • Features are configured explicitly via expressive configuration leveraging Kotlin domain-specific languages (DSL)

  • Flexible programmatic configuration

  • Leverage a subset of Spring Boot

  • Minimal reflection usage

  • No classpath scanning

  • No annotation processing

  • Modules provide configuration DSL and dependencies for other Spring projects and JVM ecosystem

  • Reactive and coroutines web client and server based on WebFlux functional API

  • Reactive and coroutines persistence via Spring Data (MongoDB supported)

  • No blocking web/persistence support is provided since coroutines provides support for imperative programming.

Upcoming features:

In addition to the whole Spring and Reactor teams, credits to Thomas Girard for its spring-webflux-kotlin-dsl experiment that initially demonstrated this approach was possible and to Konrad Kaminski for his awesome spring-kotlin-coroutine project.

Please send us your feedback on the #spring channel of Kotlin Slack. Feel free to open issues, contribute fixes or new modules via pull requests.

Getting started

Spring Fu 0.0.1 is currently under active development so no release is available yet, but you have can try 0.0.1.BUILD-SNAPSHOT builds.

Bootstrap

A Spring Fu bootstrap is an archive containing minimal project templates designed to allow you getting started quickly and easily Spring Fu applications. To start a new project, download a bootstrap .zip archive, extract it and follow README.adoc instructions.

Documentation

To start with Spring Fu, you can read the reference documentation.

API documentation will be available shortly.

You can have a look to the sample applications:

Functional configuration

Spring Fu functional configuration is leveraging Kotlin DSL that allows you to configure your application explicitly. Each custom block like configuration, actuators or webflux is in fact a more high level beans {} block with a custom DSL provided for easy configuration. Since this configuration is code, you can use any kind of custom programmatic bean registration without having to implement your own @Conditional annotation.

Here is an example of a typical Spring Fu application functional configuration.

funmain(args:Array<String) = application {
configuration {
AppConfiguration(name = env["SYSTEM_ENV"] ?: "default")
}
actuators(beans = false, mapping = false)
logging {
level(INFO)
level("org.springframework", DEBUG)
logback {
consoleAppender()
rollingFileAppender(file =File("log.txt"))
}
}
profile("data") {
bean<UserRepository>()
bean<ArticleRepository>()
mongodb(uri = "mongodb://myserver.com/foo")
listener<ContextStartedEvent> {
ref<UserRepository>().init()
ref<ArticleRepository>().init()
}
}
profile("web") {
bean<HtmlHandler>()
bean<ApiHandler>()
webflux {
val port = if (profiles.contains("test")) 8181 else 8080
server(netty(port)) {
cors(origin = "example.com")
mustache()
codecs {
jackson()
protobuf()
}
routes(ref = ::routes)
security { // TODO }
}
client {
codecs {
jackson()
}
}
}
}
}.app.run(await = true, profiles = "data, web")
data class AppConfiguration(
val name: String,
val remoteUrl: String = "http://localhost:8080"
)
fun routes() = routes {
val htmlHandler = ref<HtmlHandler>()
val apiHandler = ref<ApiHandler>()
GET("/", htmlHandler::blog)
GET("/article/{id}", htmlHandler::article)
"/api".nest {
GET("/", apiHandler::list)
POST("/", apiHandler::create)
PUT("/{id}", apiHandler::update)
DELETE("/{id}", apiHandler::delete)
}
}

Comparison with JavaConfig

Functional bean definition allows to define beans in an efficient way with minimal reflection usage, no proxy and with a concise Kotlin DSL that takes advantage of reified type parameters to avoid type erasure. The beans {} block is in fact a regular ApplicationContextInitializer.

JavaConfig

Functional bean definition

 @Configuration
classMyConfiguration {
@Bean
funfoo() =Foo()
@Bean
funbar(foo:Foo) =Bar(foo)
}
val myConfiguration = beans {
bean<Foo>()
// Implicit autowiring by constructor
bean<Bar>()
}

Comparison with @Component

Functional bean definition is explicit, does not imply any classpath scanning and supports constructor parameters autowiring.

@Component scanning

Functional bean definition

@Component
classFoo {
// ...
}
@Component
classBar(privatevalf:Foo) {
// ...
}
classFoo {
// ...
}
classBar(privatevalf:Foo) {
// ...
}
beans {
bean<Foo>()
bean<Bar>()
}

Comparison with controllers

Kotlin WebFlux router provides a simple but powerful way to implement your web application. HTTP API, streaming but also view rendering are supported.

Annotation-based controller

Kotlin WebFlux routes

@RestController
@RequestMapping("/api/article")
classMyController(privatevalr:MyRepository) {
@GetMapping("/")
funfindAll() =
r.findAll()
@GetMapping("/{id}")
funfindOne(@PathVariable id:Long) =
repository.findById(id)
}
}
routes {
val r = ref<MyRepository>()
"/api/article".nest {
GET("/") {
r.findAll()
}
GET("/{id}") {
val id = it.pathVariable("id")
r.findById(id)
}
}
}

About

Spring Fu is an experimental Kotlin micro-framework based on functional configuration intended to test new ideas for future Spring Boot releases

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Build Status

Spring Fu (for functional APIs) is an experimental Kotlin micro-framework based on functional configuration intended to test ideas for upcoming Spring Boot releases. It makes it easy to create lightweight Spring-powered applications with functional APIs instead of annotations. See the reference documentation for more details.

Overview

A simple Spring Fu web application rendering an HTML page and exposing a JSON HTTP endpoint looks like that:

funmain(args:Array<String>) = application {
bean<UserRepository>()
bean<UserHandler>()
webflux {
val port =if (profiles.contains("test")) 8181else8080
server(netty(port)) {
mustache()
codecs {
jackson()
}
routes(ref = ::routes)
}
}
}.run(await =true)
funroutes() = routes {
val userHandler = ref<UserHandler>()
GET("/", userHandler::listView)
GET("/api/user", userHandler::listApi)
}

It leverages a subset of Spring Boot, Spring Framework, Spring Data and Spring Security to provide an alternative configuration model for developing applications in Kotlin.

  • Functional bean registration instead of JavaConfig for both internals and application

  • Features are configured explicitly via expressive configuration leveraging Kotlin domain-specific languages (DSL)

  • Flexible programmatic configuration

  • Leverage a subset of Spring Boot

  • Minimal reflection usage

  • No classpath scanning

  • No annotation processing

  • Modules provide configuration DSL and dependencies for other Spring projects and JVM ecosystem

  • Reactive and coroutines web client and server based on WebFlux functional API

  • Reactive and coroutines persistence via Spring Data (MongoDB supported)

  • No blocking web/persistence support is provided since coroutines provides support for imperative programming.

Upcoming features:

In addition to the whole Spring and Reactor teams, credits to Thomas Girard for its spring-webflux-kotlin-dsl experiment that initially demonstrated this approach was possible and to Konrad Kaminski for his awesome spring-kotlin-coroutine project.

Please send us your feedback on the #spring channel of Kotlin Slack. Feel free to open issues, contribute fixes or new modules via pull requests.

Getting started

Spring Fu 0.0.1 is currently under active development so no release is available yet, but you have can try 0.0.1.BUILD-SNAPSHOT builds.

Bootstrap

A Spring Fu bootstrap is an archive containing minimal project templates designed to allow you getting started quickly and easily Spring Fu applications. To start a new project, download a bootstrap .zip archive, extract it and follow README.adoc instructions.

Documentation

To start with Spring Fu, you can read the reference documentation.

API documentation will be available shortly.

You can have a look to the sample applications:

Functional configuration

Spring Fu functional configuration is leveraging Kotlin DSL that allows you to configure your application explicitly. Each custom block like configuration, actuators or webflux is in fact a more high level beans {} block with a custom DSL provided for easy configuration. Since this configuration is code, you can use any kind of custom programmatic bean registration without having to implement your own @Conditional annotation.

Here is an example of a typical Spring Fu application functional configuration.

funmain(args:Array<String) = application {
configuration {
AppConfiguration(name = env["SYSTEM_ENV"] ?: "default")
}
actuators(beans = false, mapping = false)
logging {
level(INFO)
level("org.springframework", DEBUG)
logback {
consoleAppender()
rollingFileAppender(file =File("log.txt"))
}
}
profile("data") {
bean<UserRepository>()
bean<ArticleRepository>()
mongodb(uri = "mongodb://myserver.com/foo")
listener<ContextStartedEvent> {
ref<UserRepository>().init()
ref<ArticleRepository>().init()
}
}
profile("web") {
bean<HtmlHandler>()
bean<ApiHandler>()
webflux {
val port = if (profiles.contains("test")) 8181 else 8080
server(netty(port)) {
cors(origin = "example.com")
mustache()
codecs {
jackson()
protobuf()
}
routes(ref = ::routes)
security { // TODO }
}
client {
codecs {
jackson()
}
}
}
}
}.app.run(await = true, profiles = "data, web")
data class AppConfiguration(
val name: String,
val remoteUrl: String = "http://localhost:8080"
)
fun routes() = routes {
val htmlHandler = ref<HtmlHandler>()
val apiHandler = ref<ApiHandler>()
GET("/", htmlHandler::blog)
GET("/article/{id}", htmlHandler::article)
"/api".nest {
GET("/", apiHandler::list)
POST("/", apiHandler::create)
PUT("/{id}", apiHandler::update)
DELETE("/{id}", apiHandler::delete)
}
}

Comparison with JavaConfig

Functional bean definition allows to define beans in an efficient way with minimal reflection usage, no proxy and with a concise Kotlin DSL that takes advantage of reified type parameters to avoid type erasure. The beans {} block is in fact a regular ApplicationContextInitializer.

JavaConfig

Functional bean definition

 @Configuration
classMyConfiguration {
@Bean
funfoo() =Foo()
@Bean
funbar(foo:Foo) =Bar(foo)
}
val myConfiguration = beans {
bean<Foo>()
// Implicit autowiring by constructor
bean<Bar>()
}

Comparison with @Component

Functional bean definition is explicit, does not imply any classpath scanning and supports constructor parameters autowiring.

@Component scanning

Functional bean definition

@Component
classFoo {
// ...
}
@Component
classBar(privatevalf:Foo) {
// ...
}
classFoo {
// ...
}
classBar(privatevalf:Foo) {
// ...
}
beans {
bean<Foo>()
bean<Bar>()
}

Comparison with controllers

Kotlin WebFlux router provides a simple but powerful way to implement your web application. HTTP API, streaming but also view rendering are supported.

Annotation-based controller

Kotlin WebFlux routes

@RestController
@RequestMapping("/api/article")
classMyController(privatevalr:MyRepository) {
@GetMapping("/")
funfindAll() =
r.findAll()
@GetMapping("/{id}")
funfindOne(@PathVariable id:Long) =
repository.findById(id)
}
}
routes {
val r = ref<MyRepository>()
"/api/article".nest {
GET("/") {
r.findAll()
}
GET("/{id}") {
val id = it.pathVariable("id")
r.findById(id)
}
}
}

About

Spring Fu is an experimental Kotlin micro-framework based on functional configuration intended to test new ideas for future Spring Boot releases

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Build Status

Spring Fu (for functional APIs) is an experimental Kotlin micro-framework based on functional configuration intended to test ideas for upcoming Spring Boot releases. It makes it easy to create lightweight Spring-powered applications with functional APIs instead of annotations. See the reference documentation for more details.

Overview

A simple Spring Fu web application rendering an HTML page and exposing a JSON HTTP endpoint looks like that:

funmain(args:Array<String>) = application {
bean<UserRepository>()
bean<UserHandler>()
webflux {
val port =if (profiles.contains("test")) 8181else8080
server(netty(port)) {
mustache()
codecs {
jackson()
}
routes(ref = ::routes)
}
}
}.run(await =true)
funroutes() = routes {
val userHandler = ref<UserHandler>()
GET("/", userHandler::listView)
GET("/api/user", userHandler::listApi)
}

It leverages a subset of Spring Boot, Spring Framework, Spring Data and Spring Security to provide an alternative configuration model for developing applications in Kotlin.

  • Functional bean registration instead of JavaConfig for both internals and application

  • Features are configured explicitly via expressive configuration leveraging Kotlin domain-specific languages (DSL)

  • Flexible programmatic configuration

  • Leverage a subset of Spring Boot

  • Minimal reflection usage

  • No classpath scanning

  • No annotation processing

  • Modules provide configuration DSL and dependencies for other Spring projects and JVM ecosystem

  • Reactive and coroutines web client and server based on WebFlux functional API

  • Reactive and coroutines persistence via Spring Data (MongoDB supported)

  • No blocking web/persistence support is provided since coroutines provides support for imperative programming.

Upcoming features:

In addition to the whole Spring and Reactor teams, credits to Thomas Girard for its spring-webflux-kotlin-dsl experiment that initially demonstrated this approach was possible and to Konrad Kaminski for his awesome spring-kotlin-coroutine project.

Please send us your feedback on the #spring channel of Kotlin Slack. Feel free to open issues, contribute fixes or new modules via pull requests.

Getting started

Spring Fu 0.0.1 is currently under active development so no release is available yet, but you have can try 0.0.1.BUILD-SNAPSHOT builds.

Bootstrap

A Spring Fu bootstrap is an archive containing minimal project templates designed to allow you getting started quickly and easily Spring Fu applications. To start a new project, download a bootstrap .zip archive, extract it and follow README.adoc instructions.

Documentation

To start with Spring Fu, you can read the reference documentation.

API documentation will be available shortly.

You can have a look to the sample applications:

Functional configuration

Spring Fu functional configuration is leveraging Kotlin DSL that allows you to configure your application explicitly. Each custom block like configuration, actuators or webflux is in fact a more high level beans {} block with a custom DSL provided for easy configuration. Since this configuration is code, you can use any kind of custom programmatic bean registration without having to implement your own @Conditional annotation.

Here is an example of a typical Spring Fu application functional configuration.

funmain(args:Array<String) = application {
configuration {
AppConfiguration(name = env["SYSTEM_ENV"] ?: "default")
}
actuators(beans = false, mapping = false)
logging {
level(INFO)
level("org.springframework", DEBUG)
logback {
consoleAppender()
rollingFileAppender(file =File("log.txt"))
}
}
profile("data") {
bean<UserRepository>()
bean<ArticleRepository>()
mongodb(uri = "mongodb://myserver.com/foo")
listener<ContextStartedEvent> {
ref<UserRepository>().init()
ref<ArticleRepository>().init()
}
}
profile("web") {
bean<HtmlHandler>()
bean<ApiHandler>()
webflux {
val port = if (profiles.contains("test")) 8181 else 8080
server(netty(port)) {
cors(origin = "example.com")
mustache()
codecs {
jackson()
protobuf()
}
routes(ref = ::routes)
security { // TODO }
}
client {
codecs {
jackson()
}
}
}
}
}.app.run(await = true, profiles = "data, web")
data class AppConfiguration(
val name: String,
val remoteUrl: String = "http://localhost:8080"
)
fun routes() = routes {
val htmlHandler = ref<HtmlHandler>()
val apiHandler = ref<ApiHandler>()
GET("/", htmlHandler::blog)
GET("/article/{id}", htmlHandler::article)
"/api".nest {
GET("/", apiHandler::list)
POST("/", apiHandler::create)
PUT("/{id}", apiHandler::update)
DELETE("/{id}", apiHandler::delete)
}
}

Comparison with JavaConfig

Functional bean definition allows to define beans in an efficient way with minimal reflection usage, no proxy and with a concise Kotlin DSL that takes advantage of reified type parameters to avoid type erasure. The beans {} block is in fact a regular ApplicationContextInitializer.

JavaConfig

Functional bean definition

 @Configuration
classMyConfiguration {
@Bean
funfoo() =Foo()
@Bean
funbar(foo:Foo) =Bar(foo)
}
val myConfiguration = beans {
bean<Foo>()
// Implicit autowiring by constructor
bean<Bar>()
}

Comparison with @Component

Functional bean definition is explicit, does not imply any classpath scanning and supports constructor parameters autowiring.

@Component scanning

Functional bean definition

@Component
classFoo {
// ...
}
@Component
classBar(privatevalf:Foo) {
// ...
}
classFoo {
// ...
}
classBar(privatevalf:Foo) {
// ...
}
beans {
bean<Foo>()
bean<Bar>()
}

Comparison with controllers

Kotlin WebFlux router provides a simple but powerful way to implement your web application. HTTP API, streaming but also view rendering are supported.

Annotation-based controller

Kotlin WebFlux routes

@RestController
@RequestMapping("/api/article")
classMyController(privatevalr:MyRepository) {
@GetMapping("/")
funfindAll() =
r.findAll()
@GetMapping("/{id}")
funfindOne(@PathVariable id:Long) =
repository.findById(id)
}
}
routes {
val r = ref<MyRepository>()
"/api/article".nest {
GET("/") {
r.findAll()
}
GET("/{id}") {
val id = it.pathVariable("id")
r.findById(id)
}
}
}

About

Spring Fu is an experimental Kotlin micro-framework based on functional configuration intended to test new ideas for future Spring Boot releases

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Build Status

Spring Fu (for functional APIs) is an experimental Kotlin micro-framework based on functional configuration intended to test ideas for upcoming Spring Boot releases. It makes it easy to create lightweight Spring-powered applications with functional APIs instead of annotations. See the reference documentation for more details.

Overview

A simple Spring Fu web application rendering an HTML page and exposing a JSON HTTP endpoint looks like that:

funmain(args:Array<String>) = application {
bean<UserRepository>()
bean<UserHandler>()
webflux {
val port =if (profiles.contains("test")) 8181else8080
server(netty(port)) {
mustache()
codecs {
jackson()
}
routes(ref = ::routes)
}
}
}.run(await =true)
funroutes() = routes {
val userHandler = ref<UserHandler>()
GET("/", userHandler::listView)
GET("/api/user", userHandler::listApi)
}

It leverages a subset of Spring Boot, Spring Framework, Spring Data and Spring Security to provide an alternative configuration model for developing applications in Kotlin.

  • Functional bean registration instead of JavaConfig for both internals and application

  • Features are configured explicitly via expressive configuration leveraging Kotlin domain-specific languages (DSL)

  • Flexible programmatic configuration

  • Leverage a subset of Spring Boot

  • Minimal reflection usage

  • No classpath scanning

  • No annotation processing

  • Modules provide configuration DSL and dependencies for other Spring projects and JVM ecosystem

  • Reactive and coroutines web client and server based on WebFlux functional API

  • Reactive and coroutines persistence via Spring Data (MongoDB supported)

  • No blocking web/persistence support is provided since coroutines provides support for imperative programming.

Upcoming features:

In addition to the whole Spring and Reactor teams, credits to Thomas Girard for its spring-webflux-kotlin-dsl experiment that initially demonstrated this approach was possible and to Konrad Kaminski for his awesome spring-kotlin-coroutine project.

Please send us your feedback on the #spring channel of Kotlin Slack. Feel free to open issues, contribute fixes or new modules via pull requests.

Getting started

Spring Fu 0.0.1 is currently under active development so no release is available yet, but you have can try 0.0.1.BUILD-SNAPSHOT builds.

Bootstrap

A Spring Fu bootstrap is an archive containing minimal project templates designed to allow you getting started quickly and easily Spring Fu applications. To start a new project, download a bootstrap .zip archive, extract it and follow README.adoc instructions.

Documentation

To start with Spring Fu, you can read the reference documentation.

API documentation will be available shortly.

You can have a look to the sample applications:

Functional configuration

Spring Fu functional configuration is leveraging Kotlin DSL that allows you to configure your application explicitly. Each custom block like configuration, actuators or webflux is in fact a more high level beans {} block with a custom DSL provided for easy configuration. Since this configuration is code, you can use any kind of custom programmatic bean registration without having to implement your own @Conditional annotation.

Here is an example of a typical Spring Fu application functional configuration.

funmain(args:Array<String) = application {
configuration {
AppConfiguration(name = env["SYSTEM_ENV"] ?: "default")
}
actuators(beans = false, mapping = false)
logging {
level(INFO)
level("org.springframework", DEBUG)
logback {
consoleAppender()
rollingFileAppender(file =File("log.txt"))
}
}
profile("data") {
bean<UserRepository>()
bean<ArticleRepository>()
mongodb(uri = "mongodb://myserver.com/foo")
listener<ContextStartedEvent> {
ref<UserRepository>().init()
ref<ArticleRepository>().init()
}
}
profile("web") {
bean<HtmlHandler>()
bean<ApiHandler>()
webflux {
val port = if (profiles.contains("test")) 8181 else 8080
server(netty(port)) {
cors(origin = "example.com")
mustache()
codecs {
jackson()
protobuf()
}
routes(ref = ::routes)
security { // TODO }
}
client {
codecs {
jackson()
}
}
}
}
}.app.run(await = true, profiles = "data, web")
data class AppConfiguration(
val name: String,
val remoteUrl: String = "http://localhost:8080"
)
fun routes() = routes {
val htmlHandler = ref<HtmlHandler>()
val apiHandler = ref<ApiHandler>()
GET("/", htmlHandler::blog)
GET("/article/{id}", htmlHandler::article)
"/api".nest {
GET("/", apiHandler::list)
POST("/", apiHandler::create)
PUT("/{id}", apiHandler::update)
DELETE("/{id}", apiHandler::delete)
}
}

Comparison with JavaConfig

Functional bean definition allows to define beans in an efficient way with minimal reflection usage, no proxy and with a concise Kotlin DSL that takes advantage of reified type parameters to avoid type erasure. The beans {} block is in fact a regular ApplicationContextInitializer.

JavaConfig

Functional bean definition

 @Configuration
classMyConfiguration {
@Bean
funfoo() =Foo()
@Bean
funbar(foo:Foo) =Bar(foo)
}
val myConfiguration = beans {
bean<Foo>()
// Implicit autowiring by constructor
bean<Bar>()
}

Comparison with @Component

Functional bean definition is explicit, does not imply any classpath scanning and supports constructor parameters autowiring.

@Component scanning

Functional bean definition

@Component
classFoo {
// ...
}
@Component
classBar(privatevalf:Foo) {
// ...
}
classFoo {
// ...
}
classBar(privatevalf:Foo) {
// ...
}
beans {
bean<Foo>()
bean<Bar>()
}

Comparison with controllers

Kotlin WebFlux router provides a simple but powerful way to implement your web application. HTTP API, streaming but also view rendering are supported.

Annotation-based controller

Kotlin WebFlux routes

@RestController
@RequestMapping("/api/article")
classMyController(privatevalr:MyRepository) {
@GetMapping("/")
funfindAll() =
r.findAll()
@GetMapping("/{id}")
funfindOne(@PathVariable id:Long) =
repository.findById(id)
}
}
routes {
val r = ref<MyRepository>()
"/api/article".nest {
GET("/") {
r.findAll()
}
GET("/{id}") {
val id = it.pathVariable("id")
r.findById(id)
}
}
}

About

Spring Fu is an experimental Kotlin micro-framework based on functional configuration intended to test new ideas for future Spring Boot releases

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Build Status

Spring Fu (for functional APIs) is an experimental Kotlin micro-framework based on functional configuration intended to test ideas for upcoming Spring Boot releases. It makes it easy to create lightweight Spring-powered applications with functional APIs instead of annotations. See the reference documentation for more details.

Overview

A simple Spring Fu web application rendering an HTML page and exposing a JSON HTTP endpoint looks like that:

funmain(args:Array<String>) = application {
bean<UserRepository>()
bean<UserHandler>()
webflux {
val port =if (profiles.contains("test")) 8181else8080
server(netty(port)) {
mustache()
codecs {
jackson()
}
routes(ref = ::routes)
}
}
}.run(await =true)
funroutes() = routes {
val userHandler = ref<UserHandler>()
GET("/", userHandler::listView)
GET("/api/user", userHandler::listApi)
}

It leverages a subset of Spring Boot, Spring Framework, Spring Data and Spring Security to provide an alternative configuration model for developing applications in Kotlin.

  • Functional bean registration instead of JavaConfig for both internals and application

  • Features are configured explicitly via expressive configuration leveraging Kotlin domain-specific languages (DSL)

  • Flexible programmatic configuration

  • Leverage a subset of Spring Boot

  • Minimal reflection usage

  • No classpath scanning

  • No annotation processing

  • Modules provide configuration DSL and dependencies for other Spring projects and JVM ecosystem

  • Reactive and coroutines web client and server based on WebFlux functional API

  • Reactive and coroutines persistence via Spring Data (MongoDB supported)

  • No blocking web/persistence support is provided since coroutines provides support for imperative programming.

Upcoming features:

In addition to the whole Spring and Reactor teams, credits to Thomas Girard for its spring-webflux-kotlin-dsl experiment that initially demonstrated this approach was possible and to Konrad Kaminski for his awesome spring-kotlin-coroutine project.

Please send us your feedback on the #spring channel of Kotlin Slack. Feel free to open issues, contribute fixes or new modules via pull requests.

Getting started

Spring Fu 0.0.1 is currently under active development so no release is available yet, but you have can try 0.0.1.BUILD-SNAPSHOT builds.

Bootstrap

A Spring Fu bootstrap is an archive containing minimal project templates designed to allow you getting started quickly and easily Spring Fu applications. To start a new project, download a bootstrap .zip archive, extract it and follow README.adoc instructions.

Documentation

To start with Spring Fu, you can read the reference documentation.

API documentation will be available shortly.

You can have a look to the sample applications:

Functional configuration

Spring Fu functional configuration is leveraging Kotlin DSL that allows you to configure your application explicitly. Each custom block like configuration, actuators or webflux is in fact a more high level beans {} block with a custom DSL provided for easy configuration. Since this configuration is code, you can use any kind of custom programmatic bean registration without having to implement your own @Conditional annotation.

Here is an example of a typical Spring Fu application functional configuration.

funmain(args:Array<String) = application {
configuration {
AppConfiguration(name = env["SYSTEM_ENV"] ?: "default")
}
actuators(beans = false, mapping = false)
logging {
level(INFO)
level("org.springframework", DEBUG)
logback {
consoleAppender()
rollingFileAppender(file =File("log.txt"))
}
}
profile("data") {
bean<UserRepository>()
bean<ArticleRepository>()
mongodb(uri = "mongodb://myserver.com/foo")
listener<ContextStartedEvent> {
ref<UserRepository>().init()
ref<ArticleRepository>().init()
}
}
profile("web") {
bean<HtmlHandler>()
bean<ApiHandler>()
webflux {
val port = if (profiles.contains("test")) 8181 else 8080
server(netty(port)) {
cors(origin = "example.com")
mustache()
codecs {
jackson()
protobuf()
}
routes(ref = ::routes)
security { // TODO }
}
client {
codecs {
jackson()
}
}
}
}
}.app.run(await = true, profiles = "data, web")
data class AppConfiguration(
val name: String,
val remoteUrl: String = "http://localhost:8080"
)
fun routes() = routes {
val htmlHandler = ref<HtmlHandler>()
val apiHandler = ref<ApiHandler>()
GET("/", htmlHandler::blog)
GET("/article/{id}", htmlHandler::article)
"/api".nest {
GET("/", apiHandler::list)
POST("/", apiHandler::create)
PUT("/{id}", apiHandler::update)
DELETE("/{id}", apiHandler::delete)
}
}

Comparison with JavaConfig

Functional bean definition allows to define beans in an efficient way with minimal reflection usage, no proxy and with a concise Kotlin DSL that takes advantage of reified type parameters to avoid type erasure. The beans {} block is in fact a regular ApplicationContextInitializer.

JavaConfig

Functional bean definition

 @Configuration
classMyConfiguration {
@Bean
funfoo() =Foo()
@Bean
funbar(foo:Foo) =Bar(foo)
}
val myConfiguration = beans {
bean<Foo>()
// Implicit autowiring by constructor
bean<Bar>()
}

Comparison with @Component

Functional bean definition is explicit, does not imply any classpath scanning and supports constructor parameters autowiring.

@Component scanning

Functional bean definition

@Component
classFoo {
// ...
}
@Component
classBar(privatevalf:Foo) {
// ...
}
classFoo {
// ...
}
classBar(privatevalf:Foo) {
// ...
}
beans {
bean<Foo>()
bean<Bar>()
}

Comparison with controllers

Kotlin WebFlux router provides a simple but powerful way to implement your web application. HTTP API, streaming but also view rendering are supported.

Annotation-based controller

Kotlin WebFlux routes

@RestController
@RequestMapping("/api/article")
classMyController(privatevalr:MyRepository) {
@GetMapping("/")
funfindAll() =
r.findAll()
@GetMapping("/{id}")
funfindOne(@PathVariable id:Long) =
repository.findById(id)
}
}
routes {
val r = ref<MyRepository>()
"/api/article".nest {
GET("/") {
r.findAll()
}
GET("/{id}") {
val id = it.pathVariable("id")
r.findById(id)
}
}
}

About

Spring Fu is an experimental Kotlin micro-framework based on functional configuration intended to test new ideas for future Spring Boot releases

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Build Status

Spring Fu (for functional APIs) is an experimental Kotlin micro-framework based on functional configuration intended to test ideas for upcoming Spring Boot releases. It makes it easy to create lightweight Spring-powered applications with functional APIs instead of annotations. See the reference documentation for more details.

Overview

A simple Spring Fu web application rendering an HTML page and exposing a JSON HTTP endpoint looks like that:

funmain(args:Array<String>) = application {
bean<UserRepository>()
bean<UserHandler>()
webflux {
val port =if (profiles.contains("test")) 8181else8080
server(netty(port)) {
mustache()
codecs {
jackson()
}
routes(ref = ::routes)
}
}
}.run(await =true)
funroutes() = routes {
val userHandler = ref<UserHandler>()
GET("/", userHandler::listView)
GET("/api/user", userHandler::listApi)
}

It leverages a subset of Spring Boot, Spring Framework, Spring Data and Spring Security to provide an alternative configuration model for developing applications in Kotlin.

  • Functional bean registration instead of JavaConfig for both internals and application

  • Features are configured explicitly via expressive configuration leveraging Kotlin domain-specific languages (DSL)

  • Flexible programmatic configuration

  • Leverage a subset of Spring Boot

  • Minimal reflection usage

  • No classpath scanning

  • No annotation processing

  • Modules provide configuration DSL and dependencies for other Spring projects and JVM ecosystem

  • Reactive and coroutines web client and server based on WebFlux functional API

  • Reactive and coroutines persistence via Spring Data (MongoDB supported)

  • No blocking web/persistence support is provided since coroutines provides support for imperative programming.

Upcoming features:

In addition to the whole Spring and Reactor teams, credits to Thomas Girard for its spring-webflux-kotlin-dsl experiment that initially demonstrated this approach was possible and to Konrad Kaminski for his awesome spring-kotlin-coroutine project.

Please send us your feedback on the #spring channel of Kotlin Slack. Feel free to open issues, contribute fixes or new modules via pull requests.

Getting started

Spring Fu 0.0.1 is currently under active development so no release is available yet, but you have can try 0.0.1.BUILD-SNAPSHOT builds.

Bootstrap

A Spring Fu bootstrap is an archive containing minimal project templates designed to allow you getting started quickly and easily Spring Fu applications. To start a new project, download a bootstrap .zip archive, extract it and follow README.adoc instructions.

Documentation

To start with Spring Fu, you can read the reference documentation.

API documentation will be available shortly.

You can have a look to the sample applications:

Functional configuration

Spring Fu functional configuration is leveraging Kotlin DSL that allows you to configure your application explicitly. Each custom block like configuration, actuators or webflux is in fact a more high level beans {} block with a custom DSL provided for easy configuration. Since this configuration is code, you can use any kind of custom programmatic bean registration without having to implement your own @Conditional annotation.

Here is an example of a typical Spring Fu application functional configuration.

funmain(args:Array<String) = application {
configuration {
AppConfiguration(name = env["SYSTEM_ENV"] ?: "default")
}
actuators(beans = false, mapping = false)
logging {
level(INFO)
level("org.springframework", DEBUG)
logback {
consoleAppender()
rollingFileAppender(file =File("log.txt"))
}
}
profile("data") {
bean<UserRepository>()
bean<ArticleRepository>()
mongodb(uri = "mongodb://myserver.com/foo")
listener<ContextStartedEvent> {
ref<UserRepository>().init()
ref<ArticleRepository>().init()
}
}
profile("web") {
bean<HtmlHandler>()
bean<ApiHandler>()
webflux {
val port = if (profiles.contains("test")) 8181 else 8080
server(netty(port)) {
cors(origin = "example.com")
mustache()
codecs {
jackson()
protobuf()
}
routes(ref = ::routes)
security { // TODO }
}
client {
codecs {
jackson()
}
}
}
}
}.app.run(await = true, profiles = "data, web")
data class AppConfiguration(
val name: String,
val remoteUrl: String = "http://localhost:8080"
)
fun routes() = routes {
val htmlHandler = ref<HtmlHandler>()
val apiHandler = ref<ApiHandler>()
GET("/", htmlHandler::blog)
GET("/article/{id}", htmlHandler::article)
"/api".nest {
GET("/", apiHandler::list)
POST("/", apiHandler::create)
PUT("/{id}", apiHandler::update)
DELETE("/{id}", apiHandler::delete)
}
}

Comparison with JavaConfig

Functional bean definition allows to define beans in an efficient way with minimal reflection usage, no proxy and with a concise Kotlin DSL that takes advantage of reified type parameters to avoid type erasure. The beans {} block is in fact a regular ApplicationContextInitializer.

JavaConfig

Functional bean definition

 @Configuration
classMyConfiguration {
@Bean
funfoo() =Foo()
@Bean
funbar(foo:Foo) =Bar(foo)
}
val myConfiguration = beans {
bean<Foo>()
// Implicit autowiring by constructor
bean<Bar>()
}

Comparison with @Component

Functional bean definition is explicit, does not imply any classpath scanning and supports constructor parameters autowiring.

@Component scanning

Functional bean definition

@Component
classFoo {
// ...
}
@Component
classBar(privatevalf:Foo) {
// ...
}
classFoo {
// ...
}
classBar(privatevalf:Foo) {
// ...
}
beans {
bean<Foo>()
bean<Bar>()
}

Comparison with controllers

Kotlin WebFlux router provides a simple but powerful way to implement your web application. HTTP API, streaming but also view rendering are supported.

Annotation-based controller

Kotlin WebFlux routes

@RestController
@RequestMapping("/api/article")
classMyController(privatevalr:MyRepository) {
@GetMapping("/")
funfindAll() =
r.findAll()
@GetMapping("/{id}")
funfindOne(@PathVariable id:Long) =
repository.findById(id)
}
}
routes {
val r = ref<MyRepository>()
"/api/article".nest {
GET("/") {
r.findAll()
}
GET("/{id}") {
val id = it.pathVariable("id")
r.findById(id)
}
}
}

About

Spring Fu is an experimental Kotlin micro-framework based on functional configuration intended to test new ideas for future Spring Boot releases

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Build Status

Spring Fu (for functional APIs) is an experimental Kotlin micro-framework based on functional configuration intended to test ideas for upcoming Spring Boot releases. It makes it easy to create lightweight Spring-powered applications with functional APIs instead of annotations. See the reference documentation for more details.

Overview

A simple Spring Fu web application rendering an HTML page and exposing a JSON HTTP endpoint looks like that:

funmain(args:Array<String>) = application {
bean<UserRepository>()
bean<UserHandler>()
webflux {
val port =if (profiles.contains("test")) 8181else8080
server(netty(port)) {
mustache()
codecs {
jackson()
}
routes(ref = ::routes)
}
}
}.run(await =true)
funroutes() = routes {
val userHandler = ref<UserHandler>()
GET("/", userHandler::listView)
GET("/api/user", userHandler::listApi)
}

It leverages a subset of Spring Boot, Spring Framework, Spring Data and Spring Security to provide an alternative configuration model for developing applications in Kotlin.

  • Functional bean registration instead of JavaConfig for both internals and application

  • Features are configured explicitly via expressive configuration leveraging Kotlin domain-specific languages (DSL)

  • Flexible programmatic configuration

  • Leverage a subset of Spring Boot

  • Minimal reflection usage

  • No classpath scanning

  • No annotation processing

  • Modules provide configuration DSL and dependencies for other Spring projects and JVM ecosystem

  • Reactive and coroutines web client and server based on WebFlux functional API

  • Reactive and coroutines persistence via Spring Data (MongoDB supported)

  • No blocking web/persistence support is provided since coroutines provides support for imperative programming.

Upcoming features:

In addition to the whole Spring and Reactor teams, credits to Thomas Girard for its spring-webflux-kotlin-dsl experiment that initially demonstrated this approach was possible and to Konrad Kaminski for his awesome spring-kotlin-coroutine project.

Please send us your feedback on the #spring channel of Kotlin Slack. Feel free to open issues, contribute fixes or new modules via pull requests.

Getting started

Spring Fu 0.0.1 is currently under active development so no release is available yet, but you have can try 0.0.1.BUILD-SNAPSHOT builds.

Bootstrap

A Spring Fu bootstrap is an archive containing minimal project templates designed to allow you getting started quickly and easily Spring Fu applications. To start a new project, download a bootstrap .zip archive, extract it and follow README.adoc instructions.

Documentation

To start with Spring Fu, you can read the reference documentation.

API documentation will be available shortly.

You can have a look to the sample applications:

Functional configuration

Spring Fu functional configuration is leveraging Kotlin DSL that allows you to configure your application explicitly. Each custom block like configuration, actuators or webflux is in fact a more high level beans {} block with a custom DSL provided for easy configuration. Since this configuration is code, you can use any kind of custom programmatic bean registration without having to implement your own @Conditional annotation.

Here is an example of a typical Spring Fu application functional configuration.

funmain(args:Array<String) = application {
configuration {
AppConfiguration(name = env["SYSTEM_ENV"] ?: "default")
}
actuators(beans = false, mapping = false)
logging {
level(INFO)
level("org.springframework", DEBUG)
logback {
consoleAppender()
rollingFileAppender(file =File("log.txt"))
}
}
profile("data") {
bean<UserRepository>()
bean<ArticleRepository>()
mongodb(uri = "mongodb://myserver.com/foo")
listener<ContextStartedEvent> {
ref<UserRepository>().init()
ref<ArticleRepository>().init()
}
}
profile("web") {
bean<HtmlHandler>()
bean<ApiHandler>()
webflux {
val port = if (profiles.contains("test")) 8181 else 8080
server(netty(port)) {
cors(origin = "example.com")
mustache()
codecs {
jackson()
protobuf()
}
routes(ref = ::routes)
security { // TODO }
}
client {
codecs {
jackson()
}
}
}
}
}.app.run(await = true, profiles = "data, web")
data class AppConfiguration(
val name: String,
val remoteUrl: String = "http://localhost:8080"
)
fun routes() = routes {
val htmlHandler = ref<HtmlHandler>()
val apiHandler = ref<ApiHandler>()
GET("/", htmlHandler::blog)
GET("/article/{id}", htmlHandler::article)
"/api".nest {
GET("/", apiHandler::list)
POST("/", apiHandler::create)
PUT("/{id}", apiHandler::update)
DELETE("/{id}", apiHandler::delete)
}
}

Comparison with JavaConfig

Functional bean definition allows to define beans in an efficient way with minimal reflection usage, no proxy and with a concise Kotlin DSL that takes advantage of reified type parameters to avoid type erasure. The beans {} block is in fact a regular ApplicationContextInitializer.

JavaConfig

Functional bean definition

 @Configuration
classMyConfiguration {
@Bean
funfoo() =Foo()
@Bean
funbar(foo:Foo) =Bar(foo)
}
val myConfiguration = beans {
bean<Foo>()
// Implicit autowiring by constructor
bean<Bar>()
}

Comparison with @Component

Functional bean definition is explicit, does not imply any classpath scanning and supports constructor parameters autowiring.

@Component scanning

Functional bean definition

@Component
classFoo {
// ...
}
@Component
classBar(privatevalf:Foo) {
// ...
}
classFoo {
// ...
}
classBar(privatevalf:Foo) {
// ...
}
beans {
bean<Foo>()
bean<Bar>()
}

Comparison with controllers

Kotlin WebFlux router provides a simple but powerful way to implement your web application. HTTP API, streaming but also view rendering are supported.

Annotation-based controller

Kotlin WebFlux routes

@RestController
@RequestMapping("/api/article")
classMyController(privatevalr:MyRepository) {
@GetMapping("/")
funfindAll() =
r.findAll()
@GetMapping("/{id}")
funfindOne(@PathVariable id:Long) =
repository.findById(id)
}
}
routes {
val r = ref<MyRepository>()
"/api/article".nest {
GET("/") {
r.findAll()
}
GET("/{id}") {
val id = it.pathVariable("id")
r.findById(id)
}
}
}

About

Spring Fu is an experimental Kotlin micro-framework based on functional configuration intended to test new ideas for future Spring Boot releases

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages