XTend Rest Mini-Framework: create REST HTTP JSON API's with the power of Xtend language.
It's based on Sven Efftinge's jettyxtension (https://github.com/svenefftinge/jettyxtension). But it extends it in order to fully support all HTTP methods.
Originally it was designed in order to create just REST API's, but eventually it could evolve into a full MVC "action-based" web frameworks, once template engines are included.
I will then get similar to Padrino, Sinatra, Play2, etc.
The following example controller implements a REST JSON webservice for books.
/**
* Ejemplo de controller REST/JSON en xtrest
*
* @author jfernandes
*/
@Controller
class LibrosController {
extension JSONUtils = new JSONUtils
@Get("/libros")
def libros() {
response.contentType = ContentType.APPLICATION_JSON
val libros = Biblioteca.instance.todasLasInstancias
ok(libros.toJson)
}
@Get('/libros/:id')
def libro() {
response.contentType = ContentType.APPLICATION_JSON
val iId = Integer.valueOf(id)
try {
ok(Biblioteca.instance.getLibro(iId).toJson)
}
catch (UserException e) {
notFound("No existe libro con id '" + id + "'");
}
}
@Delete('/libros/:id')
def eliminarLibro() {
try {
response.contentType = ContentType.APPLICATION_JSON
val iId = Integer.valueOf(id)
Biblioteca.instance.eliminarLibro(iId)
ok("{ status : 'ok' }");
}
catch (UserException e) {
return notFound("No existe libro con id '" + id + "'");
}
}
def static void main(String[] args) {
XTRest.start(9000, LibrosController)
}
}
To test it:
curl http://localhost:9000/libros
Should give you an output like the following:
[
{
"id": 0,
"titulo" : "Las venas abiertas de America Latina",
"autor": "Eduardo Galeano"
},
{
"id":1,
"titulo" : "Guerra y Paz",
"autor":"Leon Tolstoi"
}
]
Since 1.0.0 version you can add define several controllers and use it when starting jetty server:
class App {
def static void main(String[] args) {
XTRest.start(9000, TareasController, UsuariosController, AnyOtherController)
}
}
This example shows that xtrest can even be used for whole MVC "server-centered" apps, where the server generates HTML using JMustache templating engine
@Controller
class ConversorController {
@Get("/conversor")
def index() {
val data = #{
"millas" -> "0",
"kilometros" -> "<< introducir millas >>"
}
render('conversor.html', data)
}
@Get("/convertir")
def convertir(String millas) {
render('conversor.html', #{
"millas" -> millas,
"kilometros" -> Integer.valueOf(millas) * 1.609344
})
}
def static void main(String[] args) {
XTRest.start(9000, ConversorController)
}
}
And then the template:
<html>
<body>
<h2>Convertir</h2>
<form action="/convertir" method="get">
<fieldset>
<label for="titulo">Millas</label>
<input
required="true"
name="millas" class="form-control"
placeholder="23"
autofocus="autofocus" value="{{millas}}">
<label for="kilometros">Kilometros</label>
<p class="lead">{{kilometros}}</p>
<button type="submit" class="btn btn-primary">Convertir</button>
</fieldset>
</form>
You need to add the following maven dependency:
<dependency>
<groupId>org.uqbar</groupId>
<artifactId>xtrest</artifactId>
<version>1.1.4</version>
</dependency>
You can see here a list of issues fixed in 1.1.0 version (released in March 2018)
-
New CORS handler added by default
-
Response content is application/json by default
You can see here a list of issues fixed in 1.0.0 version (released in August 2017)
-
Now XTRest server supports a list of controllers (as many as you want)
-
Controllers are validated: they should have an empty constructor
-
JsonIgnoreProperties is no longer required for classes when serializing from JSON
-
New conversion from JSON to a map, and also new conversion methods for integers, decimals and dates
-
Services with JSON responses are prettyfied
-
Enhanced and internationalized html page when a service is not found
-
Internationalization of error messages
-
You can configure where is your application client located (eg: "src/main/webapp" or "src/main/resources"). See resourcePath static accessors on XTRest class.
-
Using last jetty version (9.2.22.v20170606), upgraded dependencies
// TODO:
- HttpHandler
- Http Methods as annotations: Get, Delete
- URL Variables
- Parameters
- Results
- Directly using the request / response / session.
- Filters
- JSON
- View: Templating
- @Body parameter
- notfound page
There's a list of things that are still not supported but we will implement soon:
- Filters
- Variable type conversions (only string supported. Also as it's not explicitely declared as a method param, there no place to declare the type. Proposed solution "/libros/:(id|int)"
- Default values for parameters / variables