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

Aplicações web que permanecem: uma abordagem ar...

Aplicações web que permanecem: uma abordagem arquitetural Java que vai além do último framework JS da moda

Incomodado com a velocidade das mudanças e obsolescência em frameworks JavaScript? E se você precisa construir uma aplicação corporativa que precisa durar mais que a vida curta destes frameworks? Nessa palestra vamos discutir uma abordagem arquitetural web com Java utilizada no desenvolvimento dos projetos Drools e jBPM da Red Hat. Entre os principais pontos explorados:

- Vantagens de uma arquitetura baseada em contratos e não baseada na arquitetura de um framework específico;
- A importância da construção de uma API poliglota;
- Como utilizar o modelo de programação Java EE no seu browser;
- A Importância de tipagem estática em grande bases de código;
- Vantagens de utilizar um framework de UX unificado em uma arquitetura corporativa.
Serão compartilhadas essas e outras técnicas, para manter uma aplicação web desenvolvida ao longo dos últimos sete anos, aplicando as tecnologias mais recentes do desenvolvimento web a uma base de código legada de mais de 1 milhão de linhas – de maneira sustentável, ágil e evolutiva.

Eder Ignatowicz

April 24, 2017
Tweet

More Decks by Eder Ignatowicz

Other Decks in Programming

Transcript

  1. Aplicações web que permanecem: uma abordagem arquitetural Java que vai

    além do último framework JS da moda Eder Ignatowicz Sr. Software Engineer Red Hat
  2. Aplicação de Larga Escala 1mi+ de linhas código web 5

    produtos ~150 sub-projetos ~30 devs 7+ anos de base de código
  3. JS INTEROP - CONSUME Java @JsType(isNative = true) public abstract

    class JQuery { @JsMethod(namespace=GLOBAL) public native static JQuery $(String selector); public native JQuery css(String prop, String val); public native JQuery attr(String name, String val); } Java import static jquery.JQuery.$; // ... $("ul > li").css("color", "red").attr("data-level", "first");
  4. JS INTEROP - EXPOSE Java package foo; @JsType public class

    Dora { public boolean late = true; public Dora() {} public String auAu() { return "Hello QCon!";} } JavaScript var dora = new foo.Dora(); if (dora.late) { alert(dora.auAu()); }
  5. @Dependent public class ProjectsView { @Inject Document document; @Inject @DataField(

    "projects-view" ) Div view; @Inject @DataField( "new-project" ) Button newProject; @Inject @DataField( "projects-list" ) UnorderedList projectsList; @Inject Instance<ProjectItem> projects; CDI NO BROWSER
  6. <form action="orderResult.jsp" method="POST"> <h3>Pizza Types</h3> <div> <ul> <% for (

    Pizza pizza : pizzaTypes ) { %> <li> <input type="radio" name="pizzaTypeOptions" value="<%=pizza.getName()%>" checked /> <span class="pizzaType"><%=pizza.getName()%></span> <span class="pizzaPrice"><%=pizza.getPrice()%>$</span> </li> <% } %> </ul> </div> <h3>Size</h3> <ul> <li id="li_1"> <input id="pizza_size1" type="radio" name="pizzaSizeOptions" value="Small" checked/> <span class="pizzaSize">Small</span> <input id="pizza_size2" type="radio" name="pizzaSizeOptions" value="Medium"/> <span class="pizzaSize">Medium ( + 2$ )</span> <input id="pizza_size3" type="radio" name="pizzaSizeOptions" value="Large"/> <span class="pizzaSize">Large ( + 3$ )</span> </li> </ul> <h3>Extra Toppings</h3> <div class="section group"> <% for ( int j = 0; j < 3; j++ ) { %> <div class="col span_1_of_3"> <ul class="ul_2"> <% for ( int i = sliceSize * j; i < ( j + 1 ) * sliceSize; i++ ) { %> <li class="li_2"> <input type="checkbox" name="pizzaToppings" value="<%=pizzaToppings.get( i )%>"/> <%=pizzaToppings.get( i )%> </li> <% } if ( j == 0 && remainder > 0 ) { %> <li class="li_2"> <input type="checkbox" name="pizzaToppings" value="<%=pizzaToppings.get( pizzaToppings.size() - 2 )%>"/> <%=pizzaToppings.get( pizzaToppings.size() - 2 ) </li> <% } else if ( j == 1 && remainder > 1 ) { %> <li class="li_2"> <input type="checkbox" name="pizzaToppings" value="<%=pizzaToppings.get( pizzaToppings.size() - 1 )%>"/> <%=pizzaToppings.get( pizzaToppings.size() - 1 )%> </li> <% } %> </ul> </div> <% } %> </div> <h4>Each extra topping is 0.65$</h4> <input type="submit" value="Order"/> </form> ...
  7. @Dependent @Templated public class ProjectsView { @Inject @DataField( "projects-view" )

    Div view; @Inject @DataField( "new-project" ) Button newProject; @Inject @DataField( "projects-list" ) UnorderedList projectsList; } ERRAI UI
  8. <!-- Masthead --> <nav class="navbar navbar-default navbar-pf "> <div class="navbar-header

    "> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse-2"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a href="/" class="navbar-brand"> <img src="images/BPMSuite.svg" alt="JBoss BPM Suite" /> </a> </div> <div class="collapse navbar-collapse navbar-collapse-2"> <ul class="nav navbar-nav "><!-- navbar-iconic --> <li class="dropdown"> <a class="dropdown-toggle nav-item-iconic" id="dropdownMenu2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true"> Home <span class="caret"></span> </a> <ul class="dropdown-menu" aria-labelledby="dropdownMenu2"> <li><a href="#">Design</a></li> <li><a href="#">Processes &amp; Tasks</a></li> <li><a href="#">Runtime</a></li> <li><a href="#">Settings</a></li> </ul> </li> </ul> <ul class="nav navbar-nav navbar-right"> <li class="dropdown"> <a class="dropdown-toggle nav-item-iconic" id="notifications" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true"> <span title="Notifications" class="fa pficon-warning-triangle-o"></span> Messages: 0 </a> <div class="dropdown-menu infotip bottom-right"> <div class="arrow"></div> <ul class="list-group"> <li class="list-group-item"> <span class="i pficon pficon-info"></span> Modified Datasources ExampleDS </li> <li class="list-group-item"> <span class="i pficon pficon-info"></span> Error: System Failure </li> </ul> <div class="footer"> <a>Clear Messages</a> </div> </div> </li> <li class="dropdown"> <a class="dropdown-toggle nav-item-iconic" id="dropdownMenu2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true"> <span title="Username" class="fa pficon-user"></span> Brian Johnson <span class="caret"></span> </a> <ul class="dropdown-menu" aria-labelledby="dropdownMenu2"> <li><a href="#">Preferences</a></li> <li><a href="#">Logout</a></li> </ul> </li> </ul> </div> </nav> <div class="container-fluid kie-blank-slate"> <!-- blank state content --> <div class="blank-slate-pf row"> <div class="col-xs-12 col-lg-9" style="text-align:right;"><a href=""><span class="fa fa-gear"></span> Settings</a></div> <h1 id="welcome"> <!--<div style="float:right;"><a href=""><span class="fa fa-gear"></span> Settings</a></div>--> Welcome to <b>BPM Suite</b> </h1> <p> Business Process Management (BPM) Suite offers a set of flexible, process management tools that support the way you need to work. Select a BPM tool below to get started. </p> <div class="blank-slate-pf-secondary-action">
  9. Arquitetura Hexagonal Architecture - Alistair Cockburn Onion Architecture - Jeffrey

    Palermo DCI - James Coplien e Trygve Reenskaug. BCE - Ivar Jacobson Clean Architecture - Robert C. Martin
  10. Escolha do framework JS Anos 1 2 3 4 5

    6 Primeiro Release Perigo 0
  11. What’s next for Angular 1.x? "In all honesty, no one

    really knows what will happen" https://toddmotto.com/future-of-angular-1-x
  12. 1 2 3 4 5 6 Anos Entrega Escolha do

    Framework JS Curva de Aprendizado Projeto Encerrado ou a nova versão não tem retrocompatibilidade Reescrita novo Framework JS Curva de Aprendizado Projeto Encerrado ou a nova versão não tem retrocompatibilidade Reescrita novo Framework JS Curva de Aprendizado
  13. Modelo de Programação LifeCycle: - OnStart - OnSave - IsDirty

    - OnClose - OnFocus - OnLostFocus - OnMayClose - OnReveal
  14. Baseado em Contratos Screen -> Interface WorkbenchScreenActivity Editor -> Interface

    WorkbenchEditorActivity Perspective -> Interface PerspectiveActivity
  15. Perspectives Uberfire Lookup Perspective ERRAI CDI BEAN MANAGER Scan all

    Perspective Activity Implementations GWT Perspective Adapter OLD GWT WIDGET ERRAI UI Perspective Adapter Plain HTML Errai UI
  16. Live-Span de 5~10 anos Trate a arquitetura Web com o

    mesmo respeito que você trata seu backend.
  17. @WorkbenchPerspective(identifier = "HomePerspective", isDefault = true) @Templated public class HomePerspective

    implements IsElement { @Inject @DataField @WorkbenchPanel(parts = "MoodScreen?uber=fire&uber1=fire1") Div moodScreen; @Inject @DataField @WorkbenchPanel(parts = "HomeScreen?uber=fire") Div homeScreen; @Inject @DataField @WorkbenchPanel(parts = "AnotherScreen") Div anotherScreen; } @JsType public interface PerspectiveActivity{ PerspectiveDefinition getDefaultPerspectiveLayout(); @Override default String getName() { return getDefaultPerspectiveLayout().getName(); } boolean isDefault(); Menus getMenus(); ToolBar getToolBar(); }
  18. function TodoCtrl($scope) { $scope.placeText = "MiscellaneousFeatures"; $scope.todos = [ {text:

    'learn angular', done: true}, {text: 'build an angular app', done: false} ]; $scope.addTodo = function () { $scope.todos.push({text: $scope.todoText, done: false}); $scope.todoText = ''; }; $scope.remaining = function () { var count = 0; angular.forEach($scope.todos, function (todo) { count += todo.done ? 0 : 1; }); return count; }; $scope.archive = function () { var oldTodos = $scope.todos; $scope.todos = []; angular.forEach(oldTodos, function (todo) { if (!todo.done) { $scope.todos.push(todo); } }); }; $scope["goto"] = function () { $goToPlace($scope.placeText); }; } <div class="container-fluid" ng-controller="TodoCtrl"> <div class="row"> <div class="col-md-12"> <p class="pull-right" style="margin-top: 10px;">{{remaining()}} of {{todos.length}} remaining [ <a href="" ng-click="archive()">archive</a> ] </p> <h4>Todos</h4> <ul class="list-group"> <li class="list-group-item" ng-repeat="todo in todos"> <span class="done-{{todo.done}}">{{todo.text}}</span> <input class="pull-right" type="checkbox" ng-model="todo.done"> </li> </ul> </div> </div> <div class="row"> <div class="col-md-6"> <form class="form-inline" ng-submit="goto()"> <div class="form-group"> <input type="text" ng-model="placeText" size="30" class="form-control" placeholder="place to go"> <input class="btn btn-primary" type="submit" value="GoTo"> </div> </form> </div> <div class="col-md-6"> <form class="form-inline pull-right" ng-submit="addTodo()"> <div class="form-group"> <input type="text" ng-model="todoText" size="30" class="form-control" placeholder="add new todo here"> <input class="btn btn-primary" type="submit" value="Add"> </div> </form> </div> </div> </div> $registerPlugin({ id: "my_angular_js", type: "angularjs", templateUrl: "angular.sample.html", title: function () { return "angular " + Math.floor(Math.random() * 10); }, on_close: function () { alert("this is a pure JS alert!"); } });
  19. Perspectives Uberfire Lookup Perspective ERRAI CDI BEAN MANAGER Scan all

    Perspective Activity Implementations GWT Perspective Adapter OLD GWT WIDGET ERRAI UI Perspective Adapter Plain HTML Errai UI Angular Perspective Adapter Angular native Perspective Any JS Perspective Adapter Any JS Framework