for a simpler orm go to simpler-orm repo
- a router supporting named parameters and wild cards.
- a convenient wrapper for ServletContextObject, to ease your work with incoming parameters/forms/uploaded files (including hash format forms the way it is understood outside of Java world).
- primitive cookies wrapper
- a base controller (that you just can simply not use), that gives you ability for convenient accessors to the stuff above plus templating.
- non obtrusive non opinionated. Do what you want, EE provides you with just alright stuff.
Most of the stuff is coded against an interface and you can write your own adapters. for Json parameters wrapper there is simpler-jacksonadapter for Freemarker there is simpler-freemarker-adapter for embedded server there's simpler-embedded jetty
//build.gradle
repositories {
mavenCentral()
maven {
url "https://dl.bintray.com/wavywalk/maven" //add this repo
}
}
dependencies {
compile 'at.wavywalk.simpler:simpler:0.1.0:sources'
compile 'at.wavywalk.simpler:simpler:0.1.0'
}
- create your bootstrapper class and inherits from
SimplerApplicationBootstrapper
. Annotate your bootstrapper with@WebListener
implementrunOnBootstrap
andrunOnShutDown
functions. InrunOnBootstrap
or via your fave dependecy injector provide a "simpler" with it's dependencies as follows (simplified):
SimplerDependencyManager.provider = SimplerDependenciesProvider(
servletRequestParametersWrapper = ServletRequestParametersWrapper(
jsonParametersParser = JacksonParametersParser(ObjectMapper()) // [simpler-jacksonadapter](https://github.com/WavyWalk/simpler-jackson-adapter)
),
assetsPathProvider = AssetsPathProvider(PublicFolderConfig()), // default is /src/main/webapp/public.
templateProcessor = FreemarkerTemplateProcessor(configuration) //an only one fro now adapter [simpler-freemarker-adapter](https://github.com/WavyWalk/simpler-freemarker-adapter)
)
- Configure routing:
create your routing class that inherits from
RoutesDrawer(Router)
for example,
object RoutesConfig: RoutesDrawer(Router) {
override fun run() {
get("/*") {
BaseController(it).renderPlain("Hello")
}
}
}
in your runOnBootstrap()
call RoutesConfig.run()
use gretty or simpler-embedded-jetty (separate repo, create main.kt and run it from there) or drop it in to your container.
Routing will look familiar to you, all you can use example is below: as said it supports named arguments and wild cards. It doesn't use regex, so it should be fast (it implements sort of Radix Tree)
object RoutesConfig: RoutesDrawer(Router) {
override fun run() {
namespace("/api") { // route namespaces
namespace("/user") { // namespaces in namespaces
get("/:id") { //named route parameters
//yielded `it` is a context wrapper
UserController(it).show() //calling a controller inheriting from BaseController
}
namespace("/:userId/account") { // named route parameters in namespaces
get("/:accountId") {
AccountOfUserController(it).show()
}
}
get("") {
UserController(it).index()
}
put("/:id") { // all rest terms
UserController(it).update()
}
post("") {
UserController(it).create()
}
delete("/:id") {
UserController(it).delete()
}
get("/:id/hello") {
UserController(it).sayhi()
}
}
}
get("/public/*") { //catch all routes. you can add routes after it and it will resolve correectly. eg. \/* will not consume \/*/hello/:id
ToDefaultServletForwarder().forward(it) //forward servlet request to containers default servlet (e.g. for file serving) // just example implied that you'd just use stuff like nginx for that
}
get("/favicon.ico") {
PrimitiveFileServer().serveFile(it) // just for dev purposes serve a file
}
get("/*") {
BaseController(it).renderTemplate("index.ftl", mutableMapOf()) // render template
}
get("/*") {
BaseController(it).requestParams().get("user")?.get("name")?.string //process a form without implementing a controller
}
get("/getMeAstandartRequestResponse") { //access standart request objects
it.request.requestURI
it.response.writer.print(it.request.requestURI)
it.response.writer.close()
}
}
}
For a convenient use there is provided a SimplerBaseController from which you can inherit. Just inspect code in it. Main features are:
fun routeParams(): Map<String, String> // e.g for route /user/:userId / routeParams().getOrDefault(":userId", null)
fun renderTemplate(templateName: String, dataModel: Any) //would render template through provided adapter
fun requestQueryStringParams(): Map<String,String>
fun sendError(errorCode: Int)
fun head(statusCode: Int)
fun renderJson(body: String)
fun requestParams() //info below
//etc
//you can use standart request response objects there as well accessed via context.request / reponse
On of the best things simpler has - a convenient wrapper for your request params passed from client
be it a encoded form or a json it just get's what you need, without boilerplate. For forms it uses the hash format e.g. user[account][phone] in html form. So you just treat forms like map/list objects.
just call requestParams()
, and it will parse the encoded form (including uploaded file) or a Json (depending on content type), and you just get a unified access to it.
for example you get a post request of:
user:
name: joe
id: 10
friends:
- user:
name: foo
id: 10
- user:
name: bar
avatar:
file: an uploaded file
it may come as a encoded form (user[name]="joe", user[friends][0][name]="foo" and etc.) or as a json: and you just simply use your request params without writing parsers or anything (well you can if you want to):
requestParams().get("user")?.get("joe").string
requestParams().get("user")?.get("id").long
requestParams().get("user")?.get("friends")?.paramList()?.first()?.get("name")?.string
requestParams().get("user")?.get("avatar")?.get("file")?.fileItem
File uploads are handled with Apache Commons FileUpload. To get a FileItem look at the example above. to limit max file body call requestParams(maxContentLenght: Long). Encoded form wrapper is coded against an interface so you can provide your own adapter (e.g. use Servlet > 3.0 spec for file handling). I remained on Apache's because I believe it is used as default for file uploads.
that's basically it
All code written by me in this repo is under MIT or WTFPL licenses, whatever you wish. For dependencies, see their respective licenses.