Git Product home page Git Product logo

spring-fu's Introduction

Spring Fu is an experimental Kotlin micro-framework that makes it easy to create lightweight Spring-powered applications with functional APIs instead of annotations. See the reference documentation for more details.

Fu is for functional API, but that’s also a wordplay with the -fu suffix which means skill, the chinese character which means "good luck" and the chinese poetry.

Overview

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

fun main(args: Array<String>) = application {
	bean<UserRepository>()
	bean<UserHandler>()
	webflux {
		val port = if (profiles.contains("test")) 8181 else 8080
		server(netty(port)) {
			mustache()
			codecs {
				jackson()
			}
			routes(ref = ::routes)
		}
	}
}.run(await = true)

fun routes() = routes {
	val userHandler = ref<UserHandler>()
	GET("/", userHandler::listView)
	GET("/api/user", userHandler::listApi)
}

It is a thin but opinionated layer on top of a subset of Spring Framework, Spring Data, Spring Security and other Spring projects that provides an alternative configuration model to Spring Boot 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

  • 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:

Note

Some features experimented in Spring Fu, like Coroutines support, might be integrated later in other Spring projects.

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 1.0.0.M1 is currently under active development so no release is available yet, but you have can try 1.0.0.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.

fun main(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
 class MyConfiguration {

  @Bean
  fun foo() = Foo()

  @Bean
  fun bar(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
class Foo {
  // ...
}

@Component
class Bar(private val f: Foo) {
  // ...
}
class Foo {
  // ...
}
class Bar(private val f: 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")
class MyController(private val r: MyRepository) {

  @GetMapping("/")
  fun findAll() =
    r.findAll()

  @GetMapping("/{id}")
  fun findOne(@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)
    }
  }
}

spring-fu's People

Contributors

sdeleuze avatar tgirard12 avatar alek-sys avatar jnizet avatar alexczar avatar irus avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.