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

5 Pillars of a Successful Java Web Application

5 Pillars of a Successful Java Web Application

Swamped by new JavaScript frameworks that are born every six months? What about maintaining your enterprise application for longer than the two-year lifecycle of these frameworks? This session can provide you with insightful answers. It shares challenges and solutions through the five pillars of a successful Java web application, extracted directly from the development of jBPM and Drools web workbenches. The speaker how his team is able to keep a seven-year-old Java application that combines modern techniques with a legacy codebase of more than one million lines of code up to date with an agile, sustainable, and evolutionary web approach.

Eder Ignatowicz

October 01, 2017
Tweet

More Decks by Eder Ignatowicz

Other Decks in Technology

Transcript

  1. 5 Pillars of a Successful Java Web Application Eder Ignatowicz

    Sr. Software Engineer @ Red Hat Alex Porcelli Principal Software Engineer @ Red Hat
  2. s 5 pillars: Large scale application Full stack Developers UX

    Integration 5~10 years Life-Span Interoperability
  3. 1mi+ lines of web code 5 projects ~150 subprojects ~30

    devs Code base of 7+ years Large Scale Application
  4. 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");
  5. 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()); }
  6. CDI no Browser @ApplicationScoped 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;
  7. CDI no Browser if (!filter.doFilter(event)) { ... if (event.kind().equals(StandardWatchEventKind.ENTRY_ADD)) {

    resourceAddedEvent.fire(buildEvent(ResourceAddedEvent.class, event).getK2()); } ... }
  8. <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> <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>
  9. ERRAI UI @Dependent @Templated public class ProjectsView { @Inject @DataField(

    "projects-view" ) Div view; @Inject @DataField( "new-project" ) Button newProject; @Inject @DataField( "projects-list" ) UnorderedList projectsList; }
  10. <!-- 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"> ...
  11. Hexagonal Architecture - Alistair Cockburn Onion Architecture - Jeffrey Palermo

    DCI - James Coplien e Trygve Reenskaug. BCE - Ivar Jacobson Clean Architecture - Robert C. Martin Architecture
  12. JS framework choice Years 1 2 3 4 5 6

    First Release Danger 0
  13. 1 2 3 4 5 6 Years Deliver JS Framework

    Choice Learning Curve Project Canceled or new version is incompatible Rewrite on the new JS framework Learning Curve Project Canceled or new version is incompatible Rewrite on the new JS framework Learning Curve
  14. Perspectives Lookup AppFormer 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
  15. 5~10 years Life-Span The Web architecture should be treated with

    the same respect as you treat your backend.
  16. @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(); }
  17. 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!"); } });
  18. Perspectives 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 AppFormer Lookup Perspective ERRAI CDI BEAN MANAGER Scan all Perspective Activity Implementations
  19. Thank you. Eder Ignatowicz Sr. Software Engineer @ Red Hat

    Alex Porcelli Principal Software Engineer @ Red Hat