JSF versus AngularJS client-server 2.0 in samenwerking met HowITsDone Geschiedenis JSF • • • • • • Java Servlet specificatie: HTML in code JSP: HTML template Struts: MVC framework JSF: verbeterde Struts Facelets: verbeterde JSP JSF 2.0: facelets de default Geschiedenis gebruik JavaScript • Browser HTML redelijk browser onafhankelijk • Browser JavaScript niet echt browser onafhankelijk • JavaScript DOM API browser onafhankelijk • JQuery 2006 • Desktop like GUI • Dojo 2004, Backbase, … • MVC/ MVVM/ MVP • Backbone, Knockout, GWT, AngularJS, … • RESTful JSON client-server protocol JSF voorbeeld (1) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" > <h:head> <title>Boeken</title> <h:outputStylesheet name=“boek.css" library="css" /> </h:head> <h:body> <div id="header"> <ui:insert name="header" > <ui:include src="/template/common/commonHeader.xhtml" /> </ui:insert> </div> <div id="content"> <ui:insert name="content" > <ui:include src="/template/common/commonContent.xhtml" /> </ui:insert> </div> <div id="footer"> <ui:insert name="footer" > <ui:include src="/template/common/commonFooter.xhtml" /> </ui:insert> </div> </h:body> </html> JSF voorbeeld (2) <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" > <body> ALL TAGS ABOVE THIS LINE AND THIS LINE WILL BE REMOVED BY JSF <ui:composition> <h1>This is default header</h1> </ui:composition> ALL TAGS BELOW THIS LINE AND THSI LINE WILL BE REMOVED BY JSF </body> </html> JSF voorbeeld (3) <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" > <body> <ui:composition template="/template/common/commonLayout.xhtml"> <ui:define name="content"> <h2>Voeg boek toe</h2> <h:form> <div class="veld"> <h:outputLabel value="Titel"/> <h:inputText value="#{boekHandler.boek.titel}"/> </div> <h:commandButton action="#{boekHandler.voegToe}“ value=“Voeg toe”/> </h:form> </ui:define> </ui:composition> </body> </html> JSF voorbeeld (4) @Named @RequestScoped public class BoekHandler { @Inject BoekRepository boekRepository; @TransactionAttribute(REQUIRES_NEW) @RolesAllowed(“klant") public void voegToe() { ... } public Boek getBoek() { … } } JSF voorbeeld (5) web.xml <context-param> <param-name>javax.faces.PROJECT_STAGE</param-name> <!-- <param-value>Production</param-value> --> <param-value>Development</param-value> </context-param> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param> <context-param> <param-name>com.sun.faces.writeStateAtFormEnd</param-name> <!-- workaround bug JSF --> <param-value>false</param-value> </context-param> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.xhtml</url-pattern> </servlet-mapping> <session-config> <session-timeout>30</session-timeout> </session-config> JSF architectuur Pagina (HTTP GET) • (kies en bewaar view) Facelet -> HTML Submit (HTTP POST) • Bouw view op (uit serialized string) • Verwerk submitted data • Valideer submitted data • Copieer submitted data naar Backing Bean • Call action methode in Backing Bean • (kies en bewaar volgende view) Facelet -> HTML AngularJS Waarom AngularJS? • Open Source • Google (kennis, kunde, commitment) • Samenwerking met W3C • Volledig en duidelijk • • • • • Single page (AJAX) + deep linking Rich widgets Simpele concepten en code Goede documentatie Stabiel • Populair • Zelf HTML tags maken (is dit wel handig?) AngularJS voorbeeld (1) <!doctype html> <html ng-app=“boekMVC”> <head> <meta charset="utf-8"> <title>Boeken</title> <link rel="stylesheet" href=“css/boek.css"> </head> <body> <section ng-controller=“boekController"> <header> <h1>Voeg boek toe</h1> <form ng-submit="addBoek()"> <label>Titel</label> <input placeholder=“Titel" ng-model=“boekTitel"> <input type=“submit” value=“Voeg toe”/> </form> </header> </section> <script src="js/libs/angular/angular.js"></script> <script src="js/boek.js"></script> </body> </html> AngularJS voorbeeld (2) // boek.js var boekMVC = angular.module(‘boekMVC', []); boekMVC.controller(‘boekController', function boekController( $scope ) { $scope.boekTitel = ""; $scope.voegToe = function() { … HTTP POST $scope als json op url /json/voegtoe } } AngularJS voorbeeld (3) web.xml <servlet> <servlet-name>spring-json</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/spring-json-servlet.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>spring-json</servlet-name> <url-pattern>/json/*</url-pattern> </servlet-mapping> AngularJS voorbeeld (4) spring-json-servlet.xml <!-- Configures support for @Controllers --> <context:component-scan base-package="nl.mycompany.myapp.web.json" /> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <property name="order" value="1" /> <property name="mediaTypes"> <map> <entry key="json" value="application/json" /> </map> </property> <property name="defaultViews"> <list> <ref bean="jsonView" /> </list> </property> </bean> <bean id="jsonView“ class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" /> <mvc:annotation-driven /> AngularJS voorbeeld (5) @Controller public class BoekController { @RequestMapping(value = "/voegtoe") public void voegToe( @RequestParam(“boekTitel") String boekTitel) { … } } AngularJS architectuur http://code.angularjs.org/1.0.5/doc s/guide/concepts The browser loads the HTML and parses it into a DOM The browser loads angular.js script Angular waits for DOMContentLoaded event Angular looks for ng-app directive, which designates the application boundary The Module specified in ng-app (if any) is used to configure the $injector The $injector is used to create the $compileservice as well as $rootScope The $compile service is used to compile the DOM and link it with $rootScope The {{name}} interpolates the expression toHello World! Vergelijking JSF - AngularJS • Runtime architectuur • JSF: UI verdeeld over client en server • AngularJS: client-server 2.0 • zero install (initieel komt UI van server) • UI draait op client device; data interface met server • Ontwikkelarchitectuur UI • JSF UI: heterogeen • ‘server-talen’: Java, HTML, Facelet • browser-talen: HTML, JavaScript, CSS • AngularJS UI: eenduidig • alleen browser talen: HTML5, JavaScript, CSS, Angular API • Ontwikkelarchitectuur server-side • JSF: JSF (in combi met andere JEE API’s of Spring) • AngularJS: Servlet + JSON framework + SpringMVC (in combi met andere JEE API’s of Spring) Keuze criteria • • • • • • • • • • • Andere devices Browser independent Performance client Performance server (JSF: view save/restore; HTML gen.) Schaalbaar (JSF: session state: sticky session LB) Cloud (aantal opties; client / server ontkoppeling) Bestaande kennis en kunde ontwikkelteam Ease of development, learning curve Build-Test-Package-Deploy (hotfix) Continuus Integration & Delivery Onderhoudbaarheid (SMART maken) Nogmaals vergelijking criterium andere devices weging JSF 2 3 Angular toelichting JS 5 Beide geen native support (IOS/ Android) JS zit dichter op HTML5 mogelijkheden