--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
import com.jetdrone.vertx.yoke.*import com.jetdrone.vertx.yoke.middleware.*def yoke = new GYoke(vertx)yoke.use(new ErrorHandler(true))yoke.use() { request, next ->if (request.path() == '/hello') {request.response().end('Hi there!')} else {next.handle('You did not say hello! go to /hello')}}yoke.listen(8080)
import com.jetdrone.vertx.yoke.*import com.jetdrone.vertx.yoke.middleware.*def yoke = new GYoke(vertx)yoke.use( new ErrorHandler(true) )
yoke.use { request, next ->if (request.path == '/hello') {request.response.end( 'Hi there!' )
--
You received this message because you are subscribed to a topic in the Google Groups "vert.x" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/vertx/2DrXx-E8Zso/unsubscribe?hl=en-GB.
To unsubscribe from this group and all of its topics, send an email to vertx+un...@googlegroups.com.
import com.jetdrone.vertx.yoke.middleware.*import com.jetdrone.vertx.yoke.GYokeimport com.jetdrone.vertx.yoke.engine.GroovyTemplateEngine
def yoke = new GYoke(vertx)
yoke.engine('html', new GroovyTemplateEngine())yoke.chain(new ErrorHandler(true))yoke.chain {request ->request.put('session', [id: '1'])request.response.render 'template.html'}yoke.listen(8080)
<!DOCTYPE html><html><body><% 3.times { %>Hello World!<% } %><br><% if (session != null) { %>My session id is ${session.id}<% } else println "No session created." %></body></html>
import com.jetdrone.vertx.yoke.middleware.*import com.jetdrone.vertx.yoke.GYokeimport com.jetdrone.vertx.yoke.engine.GroovyTemplateEnginedef yoke = new GYoke(vertx)yoke.engine('html', new GroovyTemplateEngine())yoke.chain(new ErrorHandler(true))
yoke.chain(new GRouter() {{get("/hello") { request ->request.response.end "Hello World!"}get("/template") { request ->
request.put('session', [id: '1'])request.response.render 'template.html'}
}})yoke.chain {request ->request.response.end "maybe you should go to /hello or /template!"}yoke.listen(8080)
If you are on Groovy I've created a render engine based on the Groovy template engine API.
To unsubscribe from this group and all of its topics, send an email to vertx+unsubscribe@googlegroups.com.
To unsubscribe from this group and all of its topics, send an email to vertx+un...@googlegroups.com.
Yoke
Yoke is a project that I've been working on for the last couple of weeks.The purpose of Yoke is to provide a easy way to build web applications or web frameworks on top of Vert.x with a simple API.Yoke has no external dependencies, however it is meant to be extended.
Yoke is a chain executor framework for Vert.x, it was modeled after Connect (see http://www.senchalabs.org/connect/) and right now is bundled with 12 middleware components and if you are interested you can write 3rd party middlewares to be added to the project.Usage
The usage at the moment is Java only and I am planning to create bindings for other languages that run on Vert.x.
import com.jetdrone.vertx.yoke.middleware.*;import org.vertx.java.core.Handler;import org.vertx.java.core.http.HttpServerRequest;import org.vertx.java.platform.Verticle;
public class Tester extends Verticle {@Overridepublic void start() {Yoke yoke = new Yoke(vertx);yoke.use(new Static("public"));yoke.use(new Router() {{all("/hello", new Handler<HttpServerRequest>() {@Overridepublic void handle(HttpServerRequest request) {request.response().end("Hello World!");}});}});yoke.listen(3000);}}The API is quite simple, you start a chain (Yoke) with the Vertx instance. This Vertx instance is the shared by all middleware (Yoke will make sure of this) you you don't need to pass it to all middleware constructors.Then you chain Middleware with the method use(), in this case I chain the static file server and a the custom router middleware (which works in a similar way to the RouteMatcher).When running this verticle all requests will first try to find a matching file on the file system under the "public" directory if that fails the router will try to match the request path to "/hello" and run that handler, if that fails and error is raised.
Installation
Just pull the jar to your module lib. I am in the process of uploading the artifact to maven central.
About Templating. It would be nice to have choices. There are so many Templating engines out there and opinions on them. For instance, Thymeleaf has been briought up and it is fantastic, but not everyone wants to use it, or subscribes to how they do their templating. For instance, I like ICanHaz.js built on top of Mustache. Groovy's templating is also just as amazing. So I was just hoping it would end up being a choose whichever templating engine you want.
var Yoke = require('com/jetdrone/vertx/yoke/Yoke');var Router = require('com/jetdrone/vertx/yoke/middleware/Router');var yoke = new Yoke();var router = new Router();yoke.use(router);router.get('/hello', function (req) {req.response().end('Hello there!');});// all other resources are forbiddenyoke.use(function (req, next) {next(401);});// start serveryoke.listen(8080);
Hi Paulo,
the whole project looks quite nice to build webapps with.
I don't really understand it though, probably since I haven't worked with Connect or anything similar before. When I have Middleware objects, they are structured / ordered by my code, right? So if I use a Middleware before another one, the second will have access to stuff that happened in the first Middleware?
I'm also trying to grasp, how/what you do with the session middleware, especially since I've written that session manager module... I can only see you set/get a session id - there is no storage for anything else in the session? How can I share data between the Middleware objects then?
I use thd Idea12 of the ide, the ide don't report error.
--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+un...@googlegroups.com.
Hi Paulo,
I'm very new in the thema vert.x and I'm actually searching for a "understandable", "clean codeable" framework to create relatively complex web application with many views, complex business logic, multiple databases/sources and reporting with it. The framework should support internalizations/localization, templating with controller-binding like "managed beans", transaction management and so on..., that performs very well and that doing not so much byte code manipulations.
Now I found, that you have started a middleware projekt for vert.x and actually I'm trying to create a little example application with it, in groovy. I'm now at the point with many questions about how to do some things, started on execution with IDE (eclipse with groovy/gradle plugins), how to combine templating with business logic/routing, how to add websocket/cometD to it, what is the best approach for the understandable architecture without too much "spagetty callback hole"...
As an example, i want an app that sums 2 numbers, I start a middleware object that implements the handle method and there gets 2 request parameters and outputs their sum. Later I bind all together by creating a Yoke object and use the Router middleware, where i set the path "/sum/:arg1/:arg2" to a object reference of the middleware class i just described.
But basically this is how you integrate it with Yoke, you create a HttpServer like you would on vert.x:
HttpServer server = vertx.createHttpServer();
You then set up the websocket handler:
server.websocketHandler(new Handler<ServerWebSocket>() { public void handle(ServerWebSocket ws) { // A WebSocket has connected! } });
Its many questions, maybe it make sense to create a separate group for Yoke?
But back to your benchmark: your example has very extreme deflection by Yoke around 8.000 requests, in all tests. What is the reason for that?
--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
tim, do you have any estimation when v3 will make it into a release?
--
You received this message because you are subscribed to a topic in the Google Groups "vert.x" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/vertx/2DrXx-E8Zso/unsubscribe.
To unsubscribe from this group and all its topics, send an email to vertx+un...@googlegroups.com.
router.put("foo/bar/order", ctx -> { ... })I've been reading the example and the code and my opinion is that it is quite verbose, in order to define a PUT to foo/bar/order that consumes json you need:I know this is the builder pattern but personally i find it quite verbose and would prefer the old school:
router.route().path("foo/bar/order").method(HttpMethod.PUT).consumes("application/json").handler(ctx -> {
"put into the context key wibble the value 123"I think it should read:"from the context, get me the context data and put at wibble the value 123"But this is my opinion...
Now to the important part :)
Assuming that i am ok with the builder pattern, there are some inconsistencies that i think should be fixed:
# Context API
ctx.contextData().put("wibble", 123);if ctx is a context assuming the duck typing, why a need for contextData(), i read it like:
ctx.put("wibble", 123);
Although it makes the API sort of complete, it can introduce problems, and if you use JMX then you really want to tweak your app at runtime and you should know what are you doing...In Yoke i solve this by using JMX since I asked myself how often do i at runtime need to enable and disable routes? and if i do that, most of the times i introduce unexpected behaviour which might break my application.# Route management
route.disable();
route.enable();
# Rely on exceptions for reporting errors
One of the issues I face with exceptions is that throwing it requires it to be thrown at the same thread the router is running otherwise you loose the context and the exception handler is not called. So if your handler is doing some async stuff:
router.route().path("/foo/bar").handler(ctx -> {
someAsyncCall(cb -> {
if (err) throw new RuntimeException()
...
in this case the router will probably not catch it and there is no way to specify the error, that is why yoke has the argument to the next() call.
Also exceptions like this will force crawl of the stack to generate the stacktrace and some times you don't need that even...
# Integrate with Yoke
In theory it could be done, however this is a quite limited version of Yoke Router, Yoke router does parse path parameters: /api/:arg1, it also does arg validation before calling the handler, so if you register a param "arg1" it can be validated against a regex or even a handler before calling the handler.
It exposes control of all routes in JMX
and can also use POJOs with annotations like:
class MyRoutes {
@RegExParam("arg1")
final Pattern validator = Pattern.compile("\d+);
@Produces("application/json")
@Consumes("application/json")
@PUT("/api/:arg1)
void apiPut(YokeRequest request, Handler next) {
...
}
}
So in order to use it in yoke either it needs some extension on Yoke side to support all yoke features...
# Rely on exceptions for reporting errors
One of the issues I face with exceptions is that throwing it requires it to be thrown at the same thread the router is running otherwise you loose the context and the exception handler is not called. So if your handler is doing some async stuff:
router.route().path("/foo/bar").handler(ctx -> {
someAsyncCall(cb -> {
if (err) throw new RuntimeException()
...
in this case the router will probably not catch it and there is no way to specify the error, that is why yoke has the argument to the next() call.
Also exceptions like this will force crawl of the stack to generate the stacktrace and some times you don't need that even...
In my opinion the exception handling is all about handling *Unhandled exceptions*, i.e. RuntimeExceptions that are thrown unexpectedly from handler code. Anything else you can deal with yourself.
# Integrate with Yoke
In theory it could be done, however this is a quite limited version of Yoke Router, Yoke router does parse path parameters: /api/:arg1, it also does arg validation before calling the handler, so if you register a param "arg1" it can be validated against a regex or even a handler before calling the handler.
None of that will go away. The current routematcher does that too, so you can assume by the time you get the request that will have happened.
It exposes control of all routes in JMX
We can do that too.
and can also use POJOs with annotations like:
class MyRoutes {
@RegExParam("arg1")
final Pattern validator = Pattern.compile("\d+);
@Produces("application/json")
@Consumes("application/json")
@PUT("/api/:arg1)
void apiPut(YokeRequest request, Handler next) {
...
}
}
So in order to use it in yoke either it needs some extension on Yoke side to support all yoke features...
Can you elaborate on "extension"?
maybe JMX should be more related to perform this kind of actions that code everything... Yes JMX is kind of ugly but monitoring tools use it, it is in the JVM itself so i think it should handle this task.
# Rely on exceptions for reporting errors
One of the issues I face with exceptions is that throwing it requires it to be thrown at the same thread the router is running otherwise you loose the context and the exception handler is not called. So if your handler is doing some async stuff:
router.route().path("/foo/bar").handler(ctx -> {
someAsyncCall(cb -> {
if (err) throw new RuntimeException()
...
in this case the router will probably not catch it and there is no way to specify the error, that is why yoke has the argument to the next() call.
Also exceptions like this will force crawl of the stack to generate the stacktrace and some times you don't need that even...
In my opinion the exception handling is all about handling *Unhandled exceptions*, i.e. RuntimeExceptions that are thrown unexpectedly from handler code. Anything else you can deal with yourself.
That is fine until you call some library and you don't know what is happening inside, then you need to put guards "try catch" everywhere which just hurts me in the eyes :) the catch code would start to be a bunch of copy paste of stuff like if error then send status code 500 plus message, or a external method that does that... and then you notice that you have an exception handler that does exactly the same so why not allow bubbling the error from your handle to the exception handler...
# Integrate with Yoke
In theory it could be done, however this is a quite limited version of Yoke Router, Yoke router does parse path parameters: /api/:arg1, it also does arg validation before calling the handler, so if you register a param "arg1" it can be validated against a regex or even a handler before calling the handler.
None of that will go away. The current routematcher does that too, so you can assume by the time you get the request that will have happened.
What i meant was that yoke router does more that the route matcher, besides side JMX stuff it does validation not just of parameters /api/:id but it can also verify if the id argument is a number or uuid or whatever you wanted and returns status 400 even before reaching your handler if does not pass the validation.
It exposes control of all routes in JMX
We can do that too.
and can also use POJOs with annotations like:
class MyRoutes {
@RegExParam("arg1")
final Pattern validator = Pattern.compile("\d+);
@Produces("application/json")
@Consumes("application/json")
@PUT("/api/:arg1)
void apiPut(YokeRequest request, Handler next) {
...
}
}
So in order to use it in yoke either it needs some extension on Yoke side to support all yoke features...
Can you elaborate on "extension"?
In order to support the routematcher++ i need to get atleast the same features i've right now so i would probably need to extend the routematcher interface...
Also if you now introduce the ctx that contains the request and other objects why not use an API like undertow HttpServerExchange where request and response are blended together?