days
-4
-1
hours
-2
-1
minutes
-3
-9
seconds
-1
-6
search
JAX Developers Puzzle deadline approaching: Play for a chance to win a complimentary JAX London 2018 ticket!
It’s the client!

AngularBeans: A fresh new take on AngularJS and JavaEE

Bessem Hmidi
AngularBeans

Coffee beans in frame image via shutterstock

AngularBeans is a fresh, new approach integrating AngularJS with a JavaEE backend and has stirred some attraction in the JavaEE world recently.

The Java ecosystem doesn’t lack of web frameworks. There’s a framework for every taste. No matter if you prefer an action based, component driven, request driven… there’s a framework for everyone. But at a closer look on what happened those few last years in web development, we will be driven to accept the evidence: it’s the era of single page applications, of client side rendering and of the realtime web. Users have become much more demanding. They don’t put up with a single black-and-white terminal screen any more. They’re familiar with highly responsive, interactive user interfaces which are both more fun and more efficient to use. Those needs are the sources of countless modern client side JavaScript frameworks such as Ember.js, react.js, meteor.js and of course AngularJS. They all consider the server a “pure” service provider, only responsible for processing and providing data, as opposed to the the classic “dynamic views generator” server. Most – maybe even most – developers consider server-side rendering a thing of the past. From a technical point of view, server-side rendering was inevitable in earlier times, but nowadays browser technology has evolved to a point that allows us to shift both rendering and business logic to the client side.

It’s the client!

In other words, when we talk about MVC or MV*, it’s hard to deny that the architecture should be deployed on the client side, especially given the performance of current client machines. JavaScript interpreters are so much faster than few years ago, and the client side web development toolchain has become mature. Today, it supports tasks like dependency management, testing, debugging and build automation. Just think of Bower, Grunt, Yeoman, etc.

So, a modern server side web framework should be “aware” of the fact that on the other side of the network adapter there’s powerful and intelligent client. On the long run, the classical paradigm – a thin (or dumb) client served by a stateful server – is going to be replaced by another architectural pattern, consisting of a stateful client and a more-or-less stateless server.

Choosing a client framework playing nicely with a JavaEE server

AngularJS is clearly leading the market of JavaScript single page applications frameworks, so it’s well aligned with what we need today. But what about the server side part? As things go, the majority of current Java web framework projects have been started in a time when JavaScript was just used for animations or form validations. Do you remember the idea of progressive enhancement? It has fallen into oblivion these days, but it was en vogue when most current Java web frameworks were conceived. So when a JS framework like AngularJS is involved, those Java web frameworks are a bad match. As a more clean alternative we can adopt an AngularJS/JaxRS solution. Or an NG + SpringMVC or an NG + Ozark – JSR 371, aka MVC 1.0, approach. It’s ok but those solutions are too HTTP centric. Which is to say we loose the nice and useful abstraction layer offered by frameworks like JSF or GWT/Vaadin. But what if we could have both the level of abstraction offered by JavaEE and the power of AngularJS? The idea being that we’ve got a seamless integration of a full-blown JavaEE backend with an AngularJS client which renders the page and cares about the user interactions. Just imagine: no more XHTML, no more JSP, and no more complex lifecycle. Just pure HTML5 and JavaScript on the client side but, like JSF, without any boiler plate code for the integration! Wouldn’t that be nice?

AngularBeans

Enter AngularBeans. This framework exposes Java-EE 7 CDI beans as AngularJS services. The idea is simple: write your Java beans, inject them on the AngularJS side, and what happens in between is the job of AngularBeans.

AngularBeansArchitecture

Getting started with AngularBeans

All you need to get started with AngularBeans is a JavaEE7 web profile or full profile application server and your favorite IDE. There’s even a Maven archetype on Maven Central to give you a head start.

In case you haven’t the Maven Central archetypes catalog installed yet, you need to add the catalog URL http://repo.maven.apache.org/maven/archetype-catalog.xml. Those are the details you need to start a new project from the “helloWorld” archetype:

groupId: com.github.bessemHmidi
artifactId: angularBeans-helloWorld-archetype
version: 1.3-RELEASE

The resulting project contains a pom.xml that points to the SNAPSHOT version of AngularBeans. Most likely you’ll prefer the stable version, so just before testing it change the pom.xml as follows:

<dependency>
    <groupId>com.github.bessemHmidi</groupId>
    <artifactId>angularBeans</artifactId>
    <version>1.0.2-RELEASE</version>
</dependency>

Explaining the project structure

AngularBeansFolders

In this project structure, the webapp folder contains two JavaScript dependencies: the AngularJS lib (V 1.4.5) and SockJS lib (0.3.4). On the CSS side, Bootstrap 3.1.1 is used.

Actually, both Bootstrap and SockJS are optional. The only mandatory tool is AngularJS. SockJS comes in handy if you want to support older browsers. This library is detected by AngularBeans.

If it’s present, it’s used instead of raw web sockets default usage in all real time behaviors of the framework. So you can use web sockets with legacy browsers that don’t support web sockets natively.

By the way, the folder layout is just a default structure. With AngularBeans you can use any folder structure you like. Note that angular-beans.js is an empty file. At runtime, accessing the file from the browser doesn’t return the file’s content.

Instead, the true content is provided by a servlet. The file is optional. It is just used to stop some IDE validator from complaining about the missing “angular beans.js” file.

Now let’s take a look at the “HelloAngularBeans” class on the server side:

import angularBeans.api.AngularBean;
import angularBeans.api.NGReturn;
import angularBeans.api.http.Get;

@AngularBean
public class HelloAngularBeans {
	@Get
	@NGReturn(model = "message")
	public String sayHello(String name) {
		return "hello " + name + " from AngularBeans !";

	}
}

And the controller on the JavaScript side:

function MyCtrl(helloAngularBeans){
 var vm=this;

 vm.helloAngularBeans=helloAngularBeans;
}

Finally the HTML:

<!DOCTYPE html>
<html data-ng-app="myApp">
<head>

<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="css/app.css" />

<script type="text/javascript"
	src="bower_components/angularjs/angular.min.js"></script>
<script type="text/javascript"
	src="bower_components/sockjs/sockjs.min.js"></script>

<script type="text/javascript" src="angular-beans.js"></script>

<script type="text/javascript" src="js/filters.js"></script>
<script type="text/javascript" src="js/services.js"></script>
<script type="text/javascript" src="js/controllers.js"></script>
<script type="text/javascript" src="js/directives.js"></script>
<script type="text/javascript" src="js/module.js"></script>

<meta charset="ISO-8859-1">
<title>hello world</title>
</head>

<body ng-app="myApp">
…
    <div ng-controller="MyCtrl as vm">
       <div class="form-group">
           <fieldset>
		<label>your name: </label> <input ng-model="name" class="form-control">
	    </fieldset>
	</div>

	<button ng-click="vm.helloAngularBeans.sayHello(name)" class="btn btn-primary">click me</button>
	<span color="blue">message {{vm.helloAngularBeans.message}}</span>
    </div>
…
</html>

I think it’s easy to understand what happens here: you declare your @AngularBean annotated CDI bean, and you inject it in the AngularJS controller as any regular AngularJS service. But what about the annotations in sayHello()? Let’s examine them, one by one:

  • @CORS: Cross-origin resource sharing (CORS). Tells AngularBeans that the method is allowed to becalled from a different domain (without using a CORS servlet filter). For example, this can be very useful for CORDOVA or IONIC applications.
  • @RealTime: A method annotated with @RealTime follows this logic:
    • If no SockJS used, AngularBeans will use WebSockets to call it remotely.
    • if SockJS is present, AngularBeans will let SockJS decide which real-time mechanism will be used (WebSockets/ polling/ long polling…..).
  • @NGReturn(model=”message”):This annotation tells AngularBeans that the return value of the method is to be injected into the AngularJS model as the attribute message. In other words, the return value of the Java method is going to be available as « helloAngularBeans.message » on the AngularJS service side. In this case the « helloAngularBeans.message » value is directly rendered in the view, and as it is an asynchronous behavior the view will be updated as soon as the promise is resolved.

Sometimes injecting the value from the Java bean directly into the AngularJS model is not enough. Every once in a while, you need to call a JavaScript function to process the return value of the Java bean method. In this case, you can simply remove the @NGReturn annotation and add a promise to the controller as follows:

vm.sayHello=function(name){

    helloAngularBeans.sayHello(name).then(function(message){
		 console.log(message);
		 vm.message=message;
});

And in the HTML:

<button ng-click="vm.sayHello(name)"
        class="btn btn-primary">click me
</button>
<span color="blue">message {{vm.message}}</span>

This way, we use the controller as an abstraction between the view and the “helloAngularBeans” service.

There’s more in store for you!

There is still a lot to discover. Suffice it to simply enumerate them in order to keep this blog post short:

  • AngularBeans supports method overloading. You can define and use several methods with identical name, but different parameter signatures. Of course, this only works within the limits imposed by JavaScript. JavaScript is a dynamically typed language, so basically only the number of parameters is distinguished. Methods with different parameter types are considered identical if the number of parameters is identical, regardless of the actual type.
  • The @NGSessionScoped scope annotation provides a shared context between the current HTTP session and all the WebSocket sessions opened in the browser. For instance, that comes in handy to support multiple tabs within the same application.
  • Bean validations API annotations are translated to HTML5 form validations. You only have to add a @NGModel annotated property and add BeanValidation needed annotations:
    @NGModel
    @NotNull
    @Size(min = 4, max = 10)
    // Bean Validation
    public String getFirstName() {
    		return firstName;
    }
    

    And in the HTML just wrap your ng-form with a div with bean-validate directive:

    <div ng-controller="FormCtrl">
      <div class="panel-body" bean-validate>
        <!-- needed to activate bean validation (it must wrap the form) -->
        <div name="registerForm" ng-form>
          <fieldset>
            <label>FirstName </label>
            <input ng-model="firstName" name="firstName" type="text" autofocus />
            <p ng-show="registerForm.firstName.$error.required">required field</p>
            <p ng-show="registerForm.firstName.$error.minlength">min number of characters not respected</p>
            <p ng-show="registerForm.firstName.$error.maxlength">max number of characters not respected</p>
          </fieldset>
        </div>
      </div>
    </div>
    
  • File uploads trigger methods annotated with @FileUpload (and inject the parts as parameters).
  • There’s a built-in service to support internationalization via properties files (like JSF).
  • The ModelQuery concept.
  • Handle byte array return (like image) and using it with ng-src.
  • You can fire events from the AngularJS side and catch then on the server side, via the @Observe annotation of CDI.
  • Events fired or broadcasted on the server side can be intercepted with $scope.$on(…)

Wrapping it up

AngularBeans is a fresh, new take on professional application development. It combines the best of two worlds: a native AngularJS 1.4 client which is powered by a full-blown JavaEE backend.

Dig deeper

There’s a step-by-step tutorial at: https://bessemhmidi.github.io/AngularBeans/Step-by-Step-Tutorial.html
The Github repository https://github.com/bessemHmidi/AngularBeans provides a demo app using all the power of AngularBeans.

This article was originally published at Beyond Java and edited by Stephan Rauh.


[1] There are exceptions. Client-side rendering is bad when you’re concerned about your mobile device’s battery life.

Author
Bessem Hmidi
Bessem works at “Business & Decision” as a Technical Architect. He is also founder and leader of the “Esprit Tunisian Java user Group”. Bringing over 9 years of working with Java related technologies especially Java EE, he is also a professional course instructor, an educator and an international speaker.

Leave a Reply

Be the First to Comment!

avatar
400
  Subscribe  
Notify of