When the client told us they wanted to replace their JSF frontend with a “modern single-page application”, we had mixed feelings. JavaScript in enterprise? But after a year with AngularJS 1.3, I have to admit: Google built a framework that enterprise Java developers can truly embrace.
Why AngularJS (and Not Backbone or Ember)¶
In 2014, you have three serious candidates for enterprise SPA: Backbone.js, Ember.js, and AngularJS. Backbone is minimalist — it gives you freedom, but also responsibility for every architectural decision. Ember is opinionated and excellent, but the community in the Czech Republic is small. AngularJS won with a combination of factors: strong Google backing, two-way data binding, dependency injection (Java developers know it from Spring), and a huge community.
The key argument for our team: AngularJS is conceptually similar to what Java developers already know. Modules, services, dependency injection, testing with Jasmine — all of this has parallels in the Java world. The learning curve was surprisingly gentle.
Application Architecture¶
We were building an internal CRM system for a mid-sized company — about 200 users, dozens of screens, complex forms, real-time notifications. Architecture:
Frontend: AngularJS 1.3 + UI-Router + Bootstrap 3
Backend: Java EE 7, JAX-RS (Jersey), JPA (Hibernate)
API: RESTful JSON, JWT authentication
Build: Grunt + Bower (frontend), Maven (backend)
Tests: Karma + Jasmine (unit), Protractor (E2E)
We decided on a strict separation of frontend and backend. The frontend is a static application served from Nginx, the backend is a pure REST API on WildFly. No JSP, no server-side rendering. A clean contract via JSON API.
What AngularJS Taught Us¶
Two-way data binding is great — until it isn’t. For forms with ten fields, it’s magic. For a table with a thousand rows, it’s a disaster. Every $digest cycle traverses all watchers. With 2000+ watchers on a page, the application starts to lag. Solutions: virtual scrolling, one-time binding ({{ ::value }}), and track by in ng-repeat.
Directives are the power of the framework. We built a library of reusable directives — datepicker, autocomplete, data table with filtering and sorting, form validators. After three months of work, we had a component system from which new screens can be assembled like building blocks.
Services and dependency injection. Angular services are exactly what a Java developer expects. Singleton instances, injected via constructor (or function parameters). AuthService, ApiService, NotificationService — the code structure is readable even to a colleague who wasn’t on the project.
Integration with the Java Backend¶
REST API designed according to pragmatic principles — not strict HATEOAS, but not chaos either. Conventions: nouns in URLs, HTTP methods for operations, pagination via query parameters, error responses in a standard format.
// Angular service for working with contacts
angular.module('crm').factory('ContactService', function($http) {
var api = '/api/v1/contacts';
return {
list: function(params) { return $http.get(api, {params: params}); },
get: function(id) { return $http.get(api + '/' + id); },
create: function(data) { return $http.post(api, data); },
update: function(id, d) { return $http.put(api + '/' + id, d); },
remove: function(id) { return $http.delete(api + '/' + id); }
};
});
JWT tokens for authentication — an Angular interceptor adds the Authorization header to every request. A refresh token mechanism handles expiration. CORS correctly configured on the backend. No session cookies, no server-side state. A stateless architecture that scales beautifully.
Testing — Surprisingly Good¶
Karma runner + Jasmine for unit tests. Angular is designed with testability as a priority — $httpBackend for mocking the API, $provide for replacing dependencies. We have 78% coverage — more than our Java backend.
Protractor for end-to-end tests. Selenium under the hood, but with an Angular-aware API. It automatically waits for the $digest cycle to complete and for pending $http requests. E2E tests run in CI on Jenkins — headless Firefox via Xvfb.
Pain Points and Lessons Learned¶
- IE 8 support — the client required it. AngularJS 1.3 officially dropped it. Compromise: IE 9+ with polyfills. It took weeks to convince stakeholders.
- SEO — not relevant for an internal application, but for future public-facing projects, SPA is a problem. We’ll need to address Prerender.io or server-side rendering.
- Build tooling — Grunt + Bower works, but the ecosystem is moving fast. Gulp is taking over, Browserify and Webpack are knocking at the door. Investment in the build pipeline is necessary.
- Angular 2.0 — Google announced Angular 2.0, which will not be backward-compatible. That’s concerning for an enterprise project. We’re watching the situation.
AngularJS Works in Enterprise¶
After a year in production, we have a stable, maintainable, and well-tested application. AngularJS gave the Java team the structure and conventions they know. It’s not without problems — performance with large datasets requires care, and the future of the framework is uncertain. But for 2014, it’s the best choice for enterprise SPA that we have.
Need help with implementation?
Our experts can help with design, implementation, and operations. From architecture to production.
Contact us