If AngularJS is what should have been HTML, if CDI is what should have been JavaEE, AngularBeans is what should be JSF!
Agenda • “web applications”, new needs (frameworks view) • AngularBeans • Q&A
“web applications”, new needs
Single page web application (SPA) & Thin server concept Real-time & fall back Json & JsonRPC
Client Server Initial Req GET,POST… Classic approach HTML Rendrering Page reloading Sometes req resource (via ajax ) Service Backend HTML Generation UI logic MVC Validations… Sessions care
Client Server Initial Req GET,POST… SPA approach HTML Rendrering Page reloading HTML Rendrering Data updates UI logic Validation Session data Simulated naviguation (via #) Thin Server Backend Rest JsonRPC Wsocket Comet ……
RT –WebAPP : WebSockets
SocketIO /SockJS: • Abstracts WebSocket communications to automatically fall back to flash streaming or long-polling when necessary (on either server or client) • Adds features like heartbeats, timeouts, and disconnection support not provided in WebSocket API
JSON/JSON RPC { { "is": ["compact", "readable"] "web_service": "JS native object" "enough" : "for majority of needs" } }
REST (Representational State Transfer) Restfull HTTP / Restfull Architectures HTTP Methods (GET/POST/DELETE…) as CRUD BookMarking  Stateless By Design  scalability+
JSF
JSF /But Life cycle -> good extentions points but give us a more complex and errors-prone framework Scalability (-) HTML5 (-) even with passthrow. Facelets -> xhtml Server Side validation(-) bookMarking (-) Server Side UI-Logic (-) Performances 
JS framework MVC/MVVM/MV* 2 Ways DataBinding Modules Services Controllers Events
What we need ? Single framework that care about: SPA & Thin Server concepts Pure HTML5 support (not a sever side generated HTML5)  we can use tools as bower, grunt, yeoman generators… Real Time support + fall back when needed “clear and cleans” url’s
JavaEE7 (+)
AngularBeans AngularJS  JavaEE (CDI) Backend Json RPC Bean Validation URL Based File Upload CDI Bean  Angular Services CDI EventsAngular Event Real Time @RealTime & Broadcasting System ModelQuery (server->client) SockJs auto detection and Native support!
AngularBeans : Requirements JDK 7 (or+) JavaEE7 (or+) Web profile or full profile AS. AngularJS lib -------------------- First production-ready release: 1.0.1  sept 2015
AngularBeans: principle @AngularBean 1 @AngularBean 2 NG Service 1 NG Service 2 NG ctrl NG ctrl NG ctrl @ Other CDI Bean « Singleton » « Singleton » Dependency injectionDependency injection
AngularBeans CDI scopes : @RequestScoped @ApplicationScoped @NGSesionScoped : classic @SessionScoped is bound only to the classic HTTP session or the websocket session but only one will be active  we cannot open a conversation with the same CDI bean that include a http Get request and after that a websocket call for example. But with @NGSessionScoped  shared context between websocket calls and classic http methods calls. we can have many websockets sessions (if many browser tabs open for example ) + 1 http session  all grouped in a single NG Session)
AngularBeans : HTML head & fallback feature Angulars beans will auto detect that and will use a sockJS server end point to exploit sockJS features/ else it will use a JSR356 raw Websocket for real time interactions (no fall back feature then) angular-beans.js will be generated dynamically
AngularBeans : my first bean (style 1) @AngularBean @RequestScoped public class CalcBean { private int a, b; private int result; @NGModel public int getA() { return a; } @NGModel public int getB() { return b; } @NGModel public int getResult() { return result; } @GET @NGSubmit(backEndModels = { "a", "b" }) @NGReturn(model = "result") public int add() { result = a + b; return result; } public void setA(int a) { this.a = a; } public void setB(int b) { this.b = b; } } Get method (can be @Post, @Put, @Delete or @RealTime If any: dfault->: @Get Array of the server side models to be synchronused with the js proxy state, if «*» all properties marqued @Model will be updated (before method call ofc) Front ent Model to be synchronied with the return of the method Additional attribute -> ,updates=« » : array of other front end models to be updated too
<!DOCTYPE html> <html> <head> <script type="text/javascript" src="bower_components/angularjs/angular.js"></script> <script type="text/javascript" src="angular-beans.js"></script> <script type="text/javascript"> var myApp = angular.module("myApp", [ "angularBeans" ]); myApp.controller('calcCtrl', function($scope, calcBean) { $scope.clacBean = calcBean; }); </script> </head> AngularBeans : my first bean (style 1) :HTML module generated by AngularBeans CalcBean is now an injectable service
<body ng-app="myApp"> <div ng-controller="calcCtrl"> <label>a:</label> <input type="text" ng-model="clacBean.a"> <label>b:</label> <input type="text" ng-model="clacBean.b"> <button ng-click="clacBean.add()">send</button> <br /> <h2>Result: {{clacBean.result}}</h2> </div> </body> </html> AngularBeans : my first bean (style 1) :HTML Diect bean call
AngularBeans : my first bean (style 1) : result
@AngularBean @RequestScoped public class CalcBean { @GET public int add(int a, int b){ return a + b; } } AngularBeans : my first bean (style 2) Args passed via RPC style (can be primitves, objects, arrays or var args)
AngularBeans : my first bean (style 2) :HTML <script type="text/javascript"> var myApp = angular.module("myApp", [ "angularBeans" ]); myApp.controller('calcCtrl', function($scope, calcBean) { $scope.add = function(a,b) { calcBean.add(a,b).then(function(data){ $scope.result=data; } ); } }); </script>
AngularBeans : my first bean (style 2) :HTML <body ng-app="myApp"> <div ng-controller="calcCtrl"> <label>a:</label> <input type="text" ng-model="a"> <label>b:</label> <input type="text" ng-model="b"> <button ng-click="add(a,b)">send</button> <br /> <h2>Result: {{result}}</h2> </div> </body>
AngularBeans : my first bean (with binding) :HTML <script type="text/javascript"> var myApp = angular.module("myApp", [ "angularBeans" ]); myApp.controller('calcCtrl', function($scope, calcBean) { angularBeans.bind($scope,calcBean,["result"]); }); </script> Scope will be auto synchronized with the bean proxy (the service) state, this function take as argument an array of the properties to be bound, in this case « result » is the main return so we must add @NGReturn(model="result") on the add() method of the bean
AngularBeans : my first bean (adding log) import angularBeans.log.NGLogger; import angularBeans.log.NGLogger.Level; @AngularBean @RequestScoped public class CalcBean { @Inject NGLogger logger; @GET @NGReturn(model = "result") public int add(int a, int b) { logger.log(Level.WARN, "a=%s , b=%s , a+b= %s", a, b, a + b); return a + b; } }
AngularBeans : my first bean (adding log)
AngularBeans : my first bean (@NGPostconstruct) @Inject NGLogger logger; @NGPostConstruct public void init(){ logger.log (Level.INFO, "this method will be called at the service creation"); }
AngularBeans : my first bean (ModelQuey) package org.angularbeans.example; public class Message { private String summary; private String detail; public Message(String summary, String detail) { super(); this.summary = summary; this.detail = detail; } }
AngularBeans : my first bean (ModelQuey) @AngularBean @RequestScoped public class CalcBean { @Inject NGLogger logger; @Inject ModelQuery modelQuery; @NGPostConstruct public void init() { logger.log(Level.INFO, "this method will be called at the service creation"); } @GET @NGReturn(model = "result") public int add(int a, int b) { logger.log(Level.WARN, "a=%s , b=%s , a+b= %s", a, b, a + b); modelQuery.pushTo("messages", new Message("attention", "calculation...")).setProperty("ti me", new Date()); ; return a + b; } }
AngularBeans : my first bean (ModelQuey) :HTML myApp.controller('calcCtrl', function($scope, calcBean) { angularBeans.bind($scope,calcBean,["result","messages","time"]) ; }); <h2>Result: {{result}}</h2> <ul ng-repeat="m in messages"> <li>{{m.summary}} - {{m.detail}}</li> </ul> {{time}}
AngularBeans : my first bean (ModelQuey) ModelQuery’s are simply a query’s from back end to front end to update their models
AngularBeans : my first bean real time & events @Inject RealTimeClient client; @RealTime public void notifyOthers(){ RealTimeMessage rtMessage=new RealTimeMessage().set("notification", "someData"); client.broadcast("calculationEvent",rtMessage, false); } This method will be called via websocket (or fall back strategy) Broadcast the message to all connected sessions (can also broadcast a QueryModel) If false the sender will also receive the event
myApp.controller('calcCtrl', function($scope, calcBean) { angularBeans.bind($scope,calcBean,["result","messages" ,"time"]); $scope.$on("calculationEvent",function(event,data){ alert(data.notification); }); }); AngularBeans : my first bean real time & events
AngularBeans : others examples Form validation : https://gist.github.com/bessemHmidi/408438a2eae5 24f0348f Files upload & LobWrapper (binary data like images): https://gist.github.com/bessemHmidi/5d13d6216923 6bc17a32
http://bessemhmidi.github.io/AngularBeans/
THANK YOU!

Angular beans

  • 1.
    If AngularJS iswhat should have been HTML, if CDI is what should have been JavaEE, AngularBeans is what should be JSF!
  • 2.
    Agenda • “web applications”,new needs (frameworks view) • AngularBeans • Q&A
  • 3.
  • 4.
    Single page webapplication (SPA) & Thin server concept Real-time & fall back Json & JsonRPC
  • 5.
    Client Server Initial Req GET,POST… Classicapproach HTML Rendrering Page reloading Sometes req resource (via ajax ) Service Backend HTML Generation UI logic MVC Validations… Sessions care
  • 6.
    Client Server Initial Req GET,POST… SPAapproach HTML Rendrering Page reloading HTML Rendrering Data updates UI logic Validation Session data Simulated naviguation (via #) Thin Server Backend Rest JsonRPC Wsocket Comet ……
  • 7.
    RT –WebAPP :WebSockets
  • 8.
    SocketIO /SockJS: • AbstractsWebSocket communications to automatically fall back to flash streaming or long-polling when necessary (on either server or client) • Adds features like heartbeats, timeouts, and disconnection support not provided in WebSocket API
  • 9.
    JSON/JSON RPC { { "is": ["compact","readable"] "web_service": "JS native object" "enough" : "for majority of needs" } }
  • 10.
    REST (Representational State Transfer) RestfullHTTP / Restfull Architectures HTTP Methods (GET/POST/DELETE…) as CRUD BookMarking  Stateless By Design  scalability+
  • 11.
  • 12.
    JSF /But Life cycle-> good extentions points but give us a more complex and errors-prone framework Scalability (-) HTML5 (-) even with passthrow. Facelets -> xhtml Server Side validation(-) bookMarking (-) Server Side UI-Logic (-) Performances 
  • 13.
    JS framework MVC/MVVM/MV* 2 WaysDataBinding Modules Services Controllers Events
  • 14.
    What we need? Single framework that care about: SPA & Thin Server concepts Pure HTML5 support (not a sever side generated HTML5)  we can use tools as bower, grunt, yeoman generators… Real Time support + fall back when needed “clear and cleans” url’s
  • 15.
  • 17.
    AngularBeans AngularJS  JavaEE(CDI) Backend Json RPC Bean Validation URL Based File Upload CDI Bean  Angular Services CDI EventsAngular Event Real Time @RealTime & Broadcasting System ModelQuery (server->client) SockJs auto detection and Native support!
  • 18.
    AngularBeans : Requirements JDK7 (or+) JavaEE7 (or+) Web profile or full profile AS. AngularJS lib -------------------- First production-ready release: 1.0.1  sept 2015
  • 19.
    AngularBeans: principle @AngularBean 1 @AngularBean 2 NG Service 1 NG Service2 NG ctrl NG ctrl NG ctrl @ Other CDI Bean « Singleton » « Singleton » Dependency injectionDependency injection
  • 20.
    AngularBeans CDI scopes: @RequestScoped @ApplicationScoped @NGSesionScoped : classic @SessionScoped is bound only to the classic HTTP session or the websocket session but only one will be active  we cannot open a conversation with the same CDI bean that include a http Get request and after that a websocket call for example. But with @NGSessionScoped  shared context between websocket calls and classic http methods calls. we can have many websockets sessions (if many browser tabs open for example ) + 1 http session  all grouped in a single NG Session)
  • 21.
    AngularBeans : HTMLhead & fallback feature Angulars beans will auto detect that and will use a sockJS server end point to exploit sockJS features/ else it will use a JSR356 raw Websocket for real time interactions (no fall back feature then) angular-beans.js will be generated dynamically
  • 22.
    AngularBeans : myfirst bean (style 1) @AngularBean @RequestScoped public class CalcBean { private int a, b; private int result; @NGModel public int getA() { return a; } @NGModel public int getB() { return b; } @NGModel public int getResult() { return result; } @GET @NGSubmit(backEndModels = { "a", "b" }) @NGReturn(model = "result") public int add() { result = a + b; return result; } public void setA(int a) { this.a = a; } public void setB(int b) { this.b = b; } } Get method (can be @Post, @Put, @Delete or @RealTime If any: dfault->: @Get Array of the server side models to be synchronused with the js proxy state, if «*» all properties marqued @Model will be updated (before method call ofc) Front ent Model to be synchronied with the return of the method Additional attribute -> ,updates=« » : array of other front end models to be updated too
  • 23.
    <!DOCTYPE html> <html> <head> <script type="text/javascript" src="bower_components/angularjs/angular.js"></script> <scripttype="text/javascript" src="angular-beans.js"></script> <script type="text/javascript"> var myApp = angular.module("myApp", [ "angularBeans" ]); myApp.controller('calcCtrl', function($scope, calcBean) { $scope.clacBean = calcBean; }); </script> </head> AngularBeans : my first bean (style 1) :HTML module generated by AngularBeans CalcBean is now an injectable service
  • 24.
    <body ng-app="myApp"> <div ng-controller="calcCtrl"> <label>a:</label> <inputtype="text" ng-model="clacBean.a"> <label>b:</label> <input type="text" ng-model="clacBean.b"> <button ng-click="clacBean.add()">send</button> <br /> <h2>Result: {{clacBean.result}}</h2> </div> </body> </html> AngularBeans : my first bean (style 1) :HTML Diect bean call
  • 25.
    AngularBeans : myfirst bean (style 1) : result
  • 26.
    @AngularBean @RequestScoped public class CalcBean{ @GET public int add(int a, int b){ return a + b; } } AngularBeans : my first bean (style 2) Args passed via RPC style (can be primitves, objects, arrays or var args)
  • 27.
    AngularBeans : myfirst bean (style 2) :HTML <script type="text/javascript"> var myApp = angular.module("myApp", [ "angularBeans" ]); myApp.controller('calcCtrl', function($scope, calcBean) { $scope.add = function(a,b) { calcBean.add(a,b).then(function(data){ $scope.result=data; } ); } }); </script>
  • 28.
    AngularBeans : myfirst bean (style 2) :HTML <body ng-app="myApp"> <div ng-controller="calcCtrl"> <label>a:</label> <input type="text" ng-model="a"> <label>b:</label> <input type="text" ng-model="b"> <button ng-click="add(a,b)">send</button> <br /> <h2>Result: {{result}}</h2> </div> </body>
  • 29.
    AngularBeans : myfirst bean (with binding) :HTML <script type="text/javascript"> var myApp = angular.module("myApp", [ "angularBeans" ]); myApp.controller('calcCtrl', function($scope, calcBean) { angularBeans.bind($scope,calcBean,["result"]); }); </script> Scope will be auto synchronized with the bean proxy (the service) state, this function take as argument an array of the properties to be bound, in this case « result » is the main return so we must add @NGReturn(model="result") on the add() method of the bean
  • 30.
    AngularBeans : myfirst bean (adding log) import angularBeans.log.NGLogger; import angularBeans.log.NGLogger.Level; @AngularBean @RequestScoped public class CalcBean { @Inject NGLogger logger; @GET @NGReturn(model = "result") public int add(int a, int b) { logger.log(Level.WARN, "a=%s , b=%s , a+b= %s", a, b, a + b); return a + b; } }
  • 31.
    AngularBeans : myfirst bean (adding log)
  • 32.
    AngularBeans : myfirst bean (@NGPostconstruct) @Inject NGLogger logger; @NGPostConstruct public void init(){ logger.log (Level.INFO, "this method will be called at the service creation"); }
  • 33.
    AngularBeans : myfirst bean (ModelQuey) package org.angularbeans.example; public class Message { private String summary; private String detail; public Message(String summary, String detail) { super(); this.summary = summary; this.detail = detail; } }
  • 34.
    AngularBeans : myfirst bean (ModelQuey) @AngularBean @RequestScoped public class CalcBean { @Inject NGLogger logger; @Inject ModelQuery modelQuery; @NGPostConstruct public void init() { logger.log(Level.INFO, "this method will be called at the service creation"); } @GET @NGReturn(model = "result") public int add(int a, int b) { logger.log(Level.WARN, "a=%s , b=%s , a+b= %s", a, b, a + b); modelQuery.pushTo("messages", new Message("attention", "calculation...")).setProperty("ti me", new Date()); ; return a + b; } }
  • 35.
    AngularBeans : myfirst bean (ModelQuey) :HTML myApp.controller('calcCtrl', function($scope, calcBean) { angularBeans.bind($scope,calcBean,["result","messages","time"]) ; }); <h2>Result: {{result}}</h2> <ul ng-repeat="m in messages"> <li>{{m.summary}} - {{m.detail}}</li> </ul> {{time}}
  • 36.
    AngularBeans : myfirst bean (ModelQuey) ModelQuery’s are simply a query’s from back end to front end to update their models
  • 37.
    AngularBeans : myfirst bean real time & events @Inject RealTimeClient client; @RealTime public void notifyOthers(){ RealTimeMessage rtMessage=new RealTimeMessage().set("notification", "someData"); client.broadcast("calculationEvent",rtMessage, false); } This method will be called via websocket (or fall back strategy) Broadcast the message to all connected sessions (can also broadcast a QueryModel) If false the sender will also receive the event
  • 38.
  • 39.
    AngularBeans : othersexamples Form validation : https://gist.github.com/bessemHmidi/408438a2eae5 24f0348f Files upload & LobWrapper (binary data like images): https://gist.github.com/bessemHmidi/5d13d6216923 6bc17a32
  • 40.
  • 41.