Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Vinna, Reinventing the wheel

Vinna, Reinventing the wheel

Les slides de la présentation de Vinna, un mini-framework MVC web écrit en Java lors de la technozaure du 22/05/2013 à Zenika

F338eea2c0d517d29cf99865b831d3af?s=128

Jawher Moussa

May 22, 2013
Tweet

Transcript

  1. Vinna Reinventing  the  wheel™ or is it really ? Thursday,

    23 May, 13
  2. Kesako ? Thursday, 23 May, 13

  3. Encore un autre framework web Java MVC Thursday, 23 May,

    13
  4. Thursday, 23 May, 13

  5. Oui. Sérieux ! Parce que ... Thursday, 23 May, 13

  6. Parlons de JSF Thursday, 23 May, 13

  7. Standard Java Design by Committee Thursday, 23 May, 13

  8. Orienté composants Thursday, 23 May, 13

  9. Modèle de dev: on accède à des pages qui font

    des callbacks vers du Java Thursday, 23 May, 13
  10. Framework conçu pour être stateful Thursday, 23 May, 13

  11. C’est pas mauvais en soi, mais y’a des cas où

    on veut du stateless: site web public par exemple Thursday, 23 May, 13
  12. Cycle de vie complexe Thursday, 23 May, 13

  13. Ça impacte les performances Thursday, 23 May, 13

  14. (lancement de free mobile) Thursday, 23 May, 13

  15. Les créateurs de JSF 1 avaient complètement oublié le verbe

    GET ainsi que la possibilité de répéter un bloc HTML LOL Thursday, 23 May, 13
  16. Jeux de composants “prêt à porter”: Primefaces, Richfaces, etc. Thursday,

    23 May, 13
  17. Pratique juste pour du backoffice/prototypage Thursday, 23 May, 13

  18. Besoin de contrôler finement son HTML/CSS dans un vrai site/appli

    Thursday, 23 May, 13
  19. Modèle de dev un peu tordu car piloté par la

    vue Thursday, 23 May, 13
  20. Impossible de faire des URLs propres (faut que ça pointe

    vers un fichier de page) sans url rewriting LOL x 2 Thursday, 23 May, 13
  21. Et Wicket alors ? D ésolé N ico ! Thursday,

    23 May, 13
  22. Orienté composants, Swing-like Thursday, 23 May, 13

  23. Très puissant une fois maitrisé Thursday, 23 May, 13

  24. Les vues c’est juste du <HTML>*, on contrôle tout avec

    du Java *: Avec quand même des ids pour binder Thursday, 23 May, 13
  25. Mais idem, conçu pour être stateful Thursday, 23 May, 13

  26. On peut faire du stateless, mais on passe notre temps

    à se battre contre le framework Thursday, 23 May, 13
  27. Très facile de finir avec toute sa base de données

    dans la session Thursday, 23 May, 13
  28. Verbeux Complexe Thursday, 23 May, 13

  29. Mais 10 fois mieux que JSF quand même Thursday, 23

    May, 13
  30. Struts 2 Thursday, 23 May, 13

  31. Thursday, 23 May, 13

  32. Trop de config: interceptors Thursday, 23 May, 13

  33. Contrôleurs ne sont pas des POJO. Enfin si mais non

    ... Thursday, 23 May, 13
  34. e.g. ParamAware, etc. Thursday, 23 May, 13

  35. Lourd: e.g. un setter par paramètre à récupérer + configurer

    l’interceptor qu’il faut Thursday, 23 May, 13
  36. Pas de façon “portable” pour passer le modèle à la

    vue Thursday, 23 May, 13
  37. Les taglibs <s:*> qui réinventent HTML Thursday, 23 May, 13

  38. Et puis y’a Struts dans le nom ... Thursday, 23

    May, 13
  39. Spring MVC Thursday, 23 May, 13

  40. Un pas dans la bonne direction Thursday, 23 May, 13

  41. Mais trop flexible Thursday, 23 May, 13

  42. Trop de manières différentes de faire la même chose Thursday,

    23 May, 13
  43. On peut retourner void, String, ModelAndView, View, prendre un OutputStream

    ou ServletResponse, etc. Thursday, 23 May, 13
  44. Difficile à mettre en place dès que developpers.count()  >  1

    Thursday, 23 May, 13
  45. GWT Thursday, 23 May, 13

  46. Ça résout pas du tout la même problématique Thursday, 23

    May, 13
  47. Le JS n’est pas la réponse à tout (42) Thursday,

    23 May, 13
  48. e.g. Twitter Thursday, 23 May, 13

  49. En plus d’autres problèmes (verbosité, taille du code généré, etc.)

    Thursday, 23 May, 13
  50. Et les autres frameworks JS ? Thursday, 23 May, 13

  51. Idem que pour GWT Thursday, 23 May, 13

  52. Grails Thursday, 23 May, 13

  53. est là ou pas ? Thursday, 23 May, 13

  54. Non sérieusement Thursday, 23 May, 13

  55. Magie Thursday, 23 May, 13

  56. Magie noire Thursday, 23 May, 13

  57. Perfs Thursday, 23 May, 13

  58. Full-stack Thursday, 23 May, 13

  59. Play ? Thursday, 23 May, 13

  60. Les idées sont très bonnes Thursday, 23 May, 13

  61. C’est pas révolutionnaire non plus: c’est Rails sur JVM Thursday,

    23 May, 13
  62. Mais l’exécution ... Thursday, 23 May, 13

  63. Contrôleurs statiques (TU, DI) Thursday, 23 May, 13

  64. Magie (manipulation du bytecode) Thursday, 23 May, 13

  65. Pas basé sur les servlets ... dudes, really ? Thursday,

    23 May, 13
  66. Non blocking, real time, bla bla bla, et pourtant, les

    perfs ne suivent pas Thursday, 23 May, 13
  67. Play 2 Thursday, 23 May, 13

  68. LOL Thursday, 23 May, 13

  69. D’où Vinna Thursday, 23 May, 13

  70. On pense vraiment que le super framework MVC/Action sur JVM

    n’existe pas encore Thursday, 23 May, 13
  71. Ainsi que Thursday, 23 May, 13

  72. Vinna = Travail (en islandais) Et gagner (en suédois) Thursday,

    23 May, 13
  73. Les 4 commandements Thursday, 23 May, 13

  74. 1. de la magie tu ne feras point Thursday, 23

    May, 13
  75. 2. Simple tu seras Thursday, 23 May, 13

  76. 3. Les standards tu ré-utiliseras* *: On aime bien ré-inventer

    la roue mais faut pas abuser non plus Thursday, 23 May, 13
  77. Features Thursday, 23 May, 13

  78. MVC: Java first Thursday, 23 May, 13

  79. Centraliser la déclaration des routes Thursday, 23 May, 13

  80. Stateless Thursday, 23 May, 13

  81. Basé sur les servlets Thursday, 23 May, 13

  82. Validation (avec support de la JSR 303) Thursday, 23 May,

    13
  83. Intégration avec Spring Thursday, 23 May, 13

  84. REST Thursday, 23 May, 13

  85. G¼stï¢on du i18n Thursday, 23 May, 13

  86. Facile à étendre Thursday, 23 May, 13

  87. Templating: JSP (beurk) et Liquirods (whoa) Thursday, 23 May, 13

  88. Etc. (upload, cookies, session, ...) Thursday, 23 May, 13

  89. Quickstart Thursday, 23 May, 13

  90. Créer projet web maven Thursday, 23 May, 13

  91. Ou utiliser les archetypes Vinna Thursday, 23 May, 13

  92. 2 modes: déclaratif et programmatique Thursday, 23 May, 13

  93. Déclaratif Thursday, 23 May, 13

  94. Structure Contrôleur Déclaration des  routes Déclaration du  filtre  Vinna Thursday,

    23 May, 13
  95. web.xml        <filter>          

         <filter-­‐name>vinnaFilter</filter-­‐name>                <filter-­‐class>vinna.VinnaFilter</filter-­‐class>                <init-­‐param>                        <param-­‐name>base-­‐package</param-­‐name>                        <param-­‐value>vinna</param-­‐value>                </init-­‐param>        </filter>        <filter-­‐mapping>              <filter-­‐name>vinnaFilter</filter-­‐name>              <url-­‐pattern>/*</url-­‐pattern>        </filter-­‐mapping> Thursday, 23 May, 13
  96. Déclaration des routes GET  /  HelloController.index() GET  /hello/{name}  HelloController.sayHello({name},  {req.param.ohai})

    Thursday, 23 May, 13
  97. Ze contrôleur package  vinna.controllers; import  vinna.response.Response; import  vinna.response.StringResponse; public  class

     HelloController  {        public  Response  index()  {                return  new  StringResponse("Go  to  /hello/{your  name}  for  a  free  hug  !");        }        public  Response  sayHello(String  name,  String  ohai)  {                return  new  StringResponse(String.format("%s  %s  !",  (ohai  ==  null  ?  "Ohai"  :  ohai),  name));        } } Thursday, 23 May, 13
  98. Et c’est tout ! mvn jetty:run Thursday, 23 May, 13

  99. Programmatique Thursday, 23 May, 13

  100. Structure Déclaration des  routes Déclaration du  filtre  Vinna Contrôleur Thursday,

    23 May, 13
  101. web.xml        <filter>          

         <filter-­‐name>vinnaFilter</filter-­‐name>                <filter-­‐class>vinna.VinnaFilter</filter-­‐class>                <init-­‐param>                        <param-­‐name>application-­‐class</param-­‐name>                        <param-­‐value>vinna.VinnApp</param-­‐value>                </init-­‐param>        </filter>        <filter-­‐mapping>              <filter-­‐name>vinnaFilter</filter-­‐name>              <url-­‐pattern>/*</url-­‐pattern>        </filter-­‐mapping> Thursday, 23 May, 13
  102. Déclaration des routes package  vinna; import  java.util.Map; import  vinna.controllers.HelloController; import

     vinna.Vinna; public  class  VinnApp  extends  Vinna  {        @Override        protected  void  routes(Map<String,  Object>  config)  {                get("/").withController(HelloController.class).index();                get("/hello/{name}").withController(HelloController.class).sayHello(                                param("name").asString(),                                req.param("ohai").asString()                );        } } Thursday, 23 May, 13
  103. Ze même contrôleur package  vinna.controllers; import  vinna.response.Response; import  vinna.response.StringResponse; public

     class  HelloController  {        public  Response  index()  {                return  new  StringResponse("Go  to  /hello/{your  name}  for  a  free  hug  !");        }        public  Response  sayHello(String  name,  String  ohai)  {                return  new  StringResponse(String.format("%s  %s  !",  (ohai  ==  null  ?  "Ohai"  :  ohai),  name));        } } Thursday, 23 May, 13
  104. Les réponses Thursday, 23 May, 13

  105. Une simple interface package  vinna.response; import  vinna.http.VinnaRequestWrapper; import  vinna.http.VinnaResponseWrapper; import

     javax.servlet.ServletException; import  java.io.IOException; public  interface  Response  {        public  void  execute(VinnaRequestWrapper  request,                                                VinnaResponseWrapper  response)                        throws  IOException,  ServletException; } Thursday, 23 May, 13
  106. Vinna fournit un builder ResponseBuilder.withStatus(404)        .addHeader("X-­‐Where",  "Zlocalhost")

           .cookie(new  Cookie("zcookie",  "zvalue"))        .etag("24674U75I8673")        .type("application/technozaure"); Thursday, 23 May, 13
  107. Et d’autres implems Thursday, 23 May, 13

  108. Success.* •  Success.created() •  Success.ok() •  Success.noContent() •  ... Thursday,

    23 May, 13
  109. ClientError.* •  ClientError.notFound() •  ClientError.badRequest() •  ... Thursday, 23 May,

    13
  110. ServerError.* •  ServerError.internalError() •  ServerError.unavailable() •  ... Thursday, 23 May,

    13
  111. Redirect.* •  Redirect.moved() •  Redirect.permanently() •  ... Thursday, 23 May,

    13
  112. Forward Pour  renvoyer  une  JSP  par  exemple Thursday, 23 May,

    13
  113. LiquidrodsView Pour  renvoyer  une  vue  liquidrods Thursday, 23 May, 13

  114. Liquidrods Thursday, 23 May, 13

  115. Langage de templating inspirée de Mustache/ Handlebars et de Liquid/Jinja2

    Thursday, 23 May, 13
  116. exemple: base.html <html> <head>        <meta  charset="utf-­‐8">  

         <title>Todorods</title>        <link  href="{{contextPath}}/css/bootstrap.min.css"  rel="stylesheet"> </head> <body> <div  class="container">        {%  block  content  %}        {%  end  %} </div> </body> </html> Thursday, 23 May, 13
  117. exemple : list.html {%  extends  base.html  %} {%  block  content

     %} <h1>TODO  list</h1> <table  class="table  table-­‐bordered  table-­‐striped">        <thead>        <tr>                <th>Title</th>                <th>Description</th>        </tr>        </thead>        <tbody>        {%  for  todos  %}        <tr>                <td>{{  title  }}</td>                <td>{{  description  }}</td>        </tr>        {%  end  %}        </tbody> </table> <hr/> <a  class="btn  btn-­‐primary"  href="new">Create</a> {%  end  %} Thursday, 23 May, 13
  118. exemple : create.html {%  extends  base.html  %} {%  block  content

     %} <h1>TODO</h1> <form  class="form-­‐horizontal"  method="post"  action="new">        <legend>Create  a  new  todo:</legend>        <fieldset>                <div  class="control-­‐group  {%  if  firstErrors.title  %}  error{%  end  %}">                        <label  class="control-­‐label"  for="title">Title</label>                        <div  class="controls">                                <input  type="text"  class="input-­‐xlarge"  id="title"  name="title"  value="{{title}}"/>                                {%  if  firstErrors.title  %}                                <span  class="help-­‐inline">{{firstErrors.title}}</span>                                {%  end  %}                        </div>                </div>                ...                <div  class="control-­‐group">                        <div  class="controls">                                <button  type="submit"  class="btn  btn-­‐primary">Create</button>                        </div>                </div>        </fieldset> </form> {%  end  %} Thursday, 23 May, 13
  119. Et bien plus de fonctionnalités, mais on a plus le

    temps là ... Thursday, 23 May, 13
  120. Routes Thursday, 23 May, 13

  121. Exemples (déclaratif) GET    /css/bootstrap.min.css  pass GET    /**/*.js  pass

    GET    /        TodoController.list() GET    /new  TodoController.create() POST  /new  TodoController.create({req.param.title},  {req.param.debug}) req.param.debug:  true|false GET  /api/{id}  ApiTodoController.show({id})        id:  \d+ POST  /api  ApiTodoController.create(JacksonArgument) GET  /create  TodoController.create(TodoParameter) GET  /resource  Controller.get({req.header.ETag}) Thursday, 23 May, 13
  122. Exemples (programmatique) get("/css/bootstrap.min.css").pass(); get("/").withController(TodoController.class).list(); get("/new").withController(TodoController.class).create(); post("/new").withController(TodoController.class).create(        

           req.param("title").asString(),   req.param("description").asString()); get("/api").withController(ApiTodoController.class).list(); get("/api/{id:  \\d+}").withController(ApiTodoController.class)                .show(param("id").asLong()); post("/api").withController(ApiTodoController.class)                .create(custom(JacksonArgument.class).<Todo>asT()); get("/create").withController(TodoController.class).                create(custom(TodoParameter.class).asTodo()); Thursday, 23 May, 13
  123. Validation Thursday, 23 May, 13

  124. De base Validation  validation  =  new  Validation(); validation.required(title,  "title").required(description,  "description");

    if  (validation.hasErrors())  {        return  new  CreateView(title,  description,  validation); } Thursday, 23 May, 13
  125. Avec JSR-303 public  class  Todo  {        private

     Long  id;        @NotNull        @Size(min  =  2,  max  =  128)        private  String  title;        @NotNull        @Size(max  =  512)        private  String  description; : : Validation  validation  =  new  Validation().validate(todo); if  (!validation.hasErrors())  {        :        : } Thursday, 23 May, 13
  126. Road map Thursday, 23 May, 13

  127. Reverse routing Thursday, 23 May, 13

  128. Compatibilité Java 6 Thursday, 23 May, 13

  129. Un vrai parseur de routes Thursday, 23 May, 13

  130. Négociation de contenu Thursday, 23 May, 13

  131. Quelques APIs en pleine crise d’adolescence (validation, conversion des arguments,

    syntaxe des routes, etc.) Thursday, 23 May, 13
  132. That’s all folks Et merci ! Thursday, 23 May, 13

  133. Projet sur GitHub github.com/jawher/vinna • haklop, aka Éric • lpereir4,

    aka Lucien • jawher, aka Jawher Starring Thursday, 23 May, 13