alt text

This post is about basic authentification with AngularJs, Satellizer and JAX-RS Jersey.

Warning: it only covers auth and token. For a production-ready app, you need to add Keystore, back-end URL filtering, encryption.

Note: a lot of examples are on Satellizer’s GitHub

https://github.com/sahat/satellizer/tree/master/examples/client https://github.com/sahat/satellizer/tree/master/examples/client

https://github.com/sahat/satellizer/tree/master/examples/server/java https://github.com/sahat/satellizer/tree/master/examples/server/java

Demo

Start Tomcat and open your Internet Browser at :

http://localhost:8080/20151119-javaee-angularjs-bootstrap-auth_basic/#/ http://localhost:8080/20151119-javaee-angularjs-bootstrap-auth_basic/#/

alt text

Only Login and Home menu’s buttons are visible.

alt text

Login redirect to the Login page ([email protected], password=pass1).

alt text

The login view call the Java backend, and as a response there’ll be a token. After login, the Home page is displayed.

alt text

And the navbar now contains a “Datas” button. Also, Login is now more visible, but Logout is.

alt text

This secured page by route authent and navbar is now displayed with a message from the REST backend server.

alt text

On Logout, the app’s first state is restored (no auth, need to login).

alt text

It’s no longer possible to access #/datas page (route url is also secured).

alt text

Source

alt text

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.damienfremont.blog</groupId>
  <artifactId>20151119-javaee-angularjs-bootstrap-auth_basic</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
 
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!-- JAVAEE -->
    <java.version>7</java.version>
    <javaee.version>7.0</javaee.version>
    <jersey.version>2.22.1</jersey.version>
    <!-- WEB -->
    <jquery.version>2.1.4</jquery.version>
    <bootstrap.version>3.3.5</bootstrap.version>
    <angularjs.version>1.4.7</angularjs.version>
    <satellizer.version>0.12.5</satellizer.version>
    <ui-router.version>0.2.9</ui-router.version>
  </properties>
 
  <dependencies>
 
    <!-- JAVA -->
 
    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>${javaee.version}</version>
      <scope>provided</scope>
    </dependency>
 
    <dependency>
      <groupId>org.glassfish.jersey.containers</groupId>
      <artifactId>jersey-container-servlet</artifactId>
      <version>${jersey.version}</version>
    </dependency>
    <dependency>
      <groupId>org.glassfish.jersey.media</groupId>
      <artifactId>jersey-media-json-jackson</artifactId>
      <version>${jersey.version}</version>
    </dependency>
 
    <dependency>
      <groupId>com.nimbusds</groupId>
      <artifactId>nimbus-jose-jwt</artifactId>
      <version>3.1.1</version>
    </dependency>
 
    <!-- JAVA LANGUAGE EXTENSION -->
    <dependency>
      <groupId>joda-time</groupId>
      <artifactId>joda-time</artifactId>
      <version>2.7</version>
    </dependency>
    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>18.0</version>
    </dependency>
 
    <!-- WEB -->
 
    <dependency>
      <groupId>org.webjars</groupId>
      <artifactId>webjars-servlet-2.x</artifactId>
      <version>1.1</version>
    </dependency>
 
    <dependency>
      <groupId>org.webjars</groupId>
      <artifactId>jquery</artifactId>
      <version>${jquery.version}</version>
    </dependency>
    <dependency>
      <groupId>org.webjars</groupId>
      <artifactId>bootstrap</artifactId>
      <version>${bootstrap.version}</version>
    </dependency>
    <dependency>
      <groupId>org.webjars</groupId>
      <artifactId>angularjs</artifactId>
      <version>${angularjs.version}</version>
    </dependency>
    <dependency>
      <groupId>org.webjars.bower</groupId>
      <artifactId>ui-router</artifactId>
      <version>${ui-router.version}</version>
    </dependency>
    <dependency>
      <groupId>org.webjars</groupId>
      <artifactId>satellizer</artifactId>
      <version>${satellizer.version}</version>
    </dependency>
 
  </dependencies>
  <build>
    <resources>
      <resource>
        <directory>src/main/webapp</directory>
        <filtering>true</filtering>
        <targetPath>${project.basedir}/target/m2e-wtp/web-resources</targetPath>
        <includes>
          <include>*.jsp</include>
        </includes>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.6</version>
        <configuration>
          <webResources>
            <resource>
              <directory>src/main/webapp</directory>
              <filtering>true</filtering>
              <includes>
                <include>index.html</include>
              </includes>
            </resource>
          </webResources>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <source>1.${java.version}</source>
          <target>1.${java.version}</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

AuthUtils.java

package com.damienfremont.blog;
 
import java.text.ParseException;
 
import org.joda.time.DateTime;
 
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.ReadOnlyJWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
 
 
/**
 * @see https://github.com/sahat/satellizer/blob/master/examples/server/java/src/main/java/com/example/helloworld/auth/AuthUtils.java
 */
public class AuthUtils {
  private static final JWSHeader JWT_HEADER = new JWSHeader(JWSAlgorithm.HS256);
  private static final String TOKEN_SECRET = "aliceinwonderland";
  public static final String AUTH_HEADER_KEY = "Authorization";
 
  public static String getSubject(String authHeader) throws ParseException, JOSEException {
    return decodeToken(authHeader).getSubject();
  }
 
  public static ReadOnlyJWTClaimsSet decodeToken(String authHeader) throws ParseException, JOSEException {
    SignedJWT signedJWT = SignedJWT.parse(getSerializedToken(authHeader));
    if (signedJWT.verify(new MACVerifier(TOKEN_SECRET))) {
      return signedJWT.getJWTClaimsSet();
    } else {
      throw new JOSEException("Signature verification failed");
    }
  }
 
  public static Token createToken(String host, long sub) throws JOSEException {
    JWTClaimsSet claim = new JWTClaimsSet();
    claim.setSubject(Long.toString(sub));
    claim.setIssuer(host);
    claim.setIssueTime(DateTime.now().toDate());
    claim.setExpirationTime(DateTime.now().plusDays(14).toDate());
 
    JWSSigner signer = new MACSigner(TOKEN_SECRET);
    SignedJWT jwt = new SignedJWT(JWT_HEADER, claim);
    jwt.sign(signer);
 
    return new Token(jwt.serialize());
  }
 
  public static String getSerializedToken(String authHeader) {
    return authHeader.split(" ")[1];
  }
}

MyAppCONFIG.java

package com.damienfremont.blog;
 
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
 
public class MyAppCONFIG extends Application {
 
  @Override
  public Set<Class<?>> getClasses() {
    Set<Class<?>> s = new HashSet<Class<?>>();
    s.add(ServiceJAXRS.class);
    s.add(ServiceAuth.class);
    return s;
  }
}

ServiceAuth.java

package com.damienfremont.blog;
 
import java.util.HashMap;
import java.util.Map;
 
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
 
import com.damienfremont.blog.ServiceJAXRS.Content;
import com.google.common.base.Optional;
import com.nimbusds.jose.JOSEException;
 
/**
 * @see https://github.com/sahat/satellizer/blob/master/examples/server/java/src/main/java/com/example/helloworld/resources/AuthResource.java
 */
@Path("/auth")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ServiceAuth {
 
  static Map<String, User> users = new HashMap<>();
 
  static {
    users.put("[email protected]", new User(1L, "[email protected]", "pass1"));
    users.put("[email protected]", new User(2L, "[email protected]", "pass2"));
  }
 
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public Content get() {
    Content res = new Content();
    res.content = "this is from backend!!!";
    return res;
  }
 
  @Path("/login")
  @POST
  public Response login(@Valid final User user, @Context final HttpServletRequest request) throws JOSEException {
    final Optional<User> foundUser = findByEmail(user.email);
    if (foundUser.isPresent() && checkPassword(user.password, foundUser.get().password)) {
      final Token token = AuthUtils.createToken(request.getRemoteHost(), foundUser.get().id);
      return Response.ok().entity(token).build();
    }
    return Response.status(Status.UNAUTHORIZED).entity("LOGING_ERROR_MSG").build();
  }
 
  private boolean checkPassword(String password, String password2) {
    // TODO BUILD YOUR OWN ENCRYPT PASSWORD CHECKER
    return password.equals(password2);
  }
 
  private Optional<User> findByEmail(String email) {
    // TODO BUILD YOUR OWN DAO
    return Optional.fromNullable(users.get(email));
  }
 
  static class User {
    public Long id;
    public String email;
    public String password;
 
    public User() {
    }
 
    public User(Long id, String email, String password) {
      this.id = id;
      this.email = email;
      this.password = password;
    }
 
  }
 
}

ServiceJAXRS.java

package com.damienfremont.blog;
 
import java.io.Serializable;
 
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
 
@Path("/data")
public class ServiceJAXRS {
 
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public Content get() {
    Content res = new Content();
    res.content = "this is from backend!!!";
    return res;
  }
   
  static class Content implements Serializable {
    private static final long serialVersionUID = 611255415996442390L;
    public String content;
  }
 
}

Token.java

package com.damienfremont.blog;
 
import com.fasterxml.jackson.annotation.JsonProperty;
 
/**
 * @see https://github.com/sahat/satellizer/blob/master/examples/server/java/src/main/java/com/example/helloworld/core/Token.java
 */
public class Token {
  String token;
 
  public Token(@JsonProperty("token") String token) {
    this.token = token;
  }
 
  public String getToken() {
    return token;
  }
}

app.js

'use strict';
 
var app = angular.module('app', [ 'ngResource', 'ngRoute',  'ui.router', 'satellizer' ]);
 
// CONFIG
app.config(function($routeProvider, $authProvider) {
     
  // ROUTE
  $routeProvider
    .when('/', {
      templateUrl: 'views/home.html',
      controller: 'HomeCtrl'
    })
    .when('/login', {
      templateUrl: 'views/login.html',
      controller: 'LoginCtrl'
    })
    .when('/logout', {
      templateUrl: 'views/home.html',
      controller: 'LogoutCtrl'
    })
    .when('/datas', {
      templateUrl: 'views/datas.html',
      controller: 'DatasCtrl',
      resolve: {
          loginRequired: loginRequired
        }
    })
    .otherwise('/');
 
  // SECURITY
  $authProvider.withCredentials = true;
  $authProvider.tokenRoot = null;
  $authProvider.cordova = false;
  $authProvider.baseUrl = './api/';
  $authProvider.loginUrl = '/auth/login';
  $authProvider.signupUrl = '/auth/signup';
  $authProvider.unlinkUrl = '/auth/unlink/';
  $authProvider.tokenName = 'token';
  $authProvider.tokenPrefix = 'satellizer';
  $authProvider.authHeader = 'Authorization';
  $authProvider.authToken = 'Bearer';
  $authProvider.storageType = 'localStorage';
   
});
 
function skipIfLoggedIn($q, $auth) {
    var deferred = $q.defer();
    if ($auth.isAuthenticated()) {
      deferred.reject();
    } else {
      deferred.resolve();
    }
    return deferred.promise;
  }
 
  function loginRequired($q, $location, $auth) {
    var deferred = $q.defer();
    if ($auth.isAuthenticated()) {
      deferred.resolve();
    } else {
      $location.path('/login');
    }
    return deferred.promise;
  }
 
app.factory('Service', function($resource) {
  return $resource('api/data');
});
 
// COMMON CTRL
 
app.controller('ParentCtrl', function($scope, $auth) {
  $scope.isAuthenticated = function() {
    return $auth.isAuthenticated();
  };
});
 
app.controller('NavbarCtrl', function($scope, $auth) {
   
});

datas.js

'use strict';
 
app.controller('DatasCtrl', function($scope, $auth, Service) {
 
    // GET DATAS IF AUTH OK
  if ($auth.isAuthenticated()) {
    Service.get(function(obj) {
      $scope.content = obj.content;
    });
  }
});

home.js

'use strict';
 
app.controller('HomeCtrl', function($scope, $auth, Service) {
 
    // GET DATAS IF AUTH OK
  if ($auth.isAuthenticated()) {
    $scope.message = "You are logged in!";
  } else {
    $scope.message = "You must login to access Datas.";  
  }
});

login.js

'use strict';
 
app.controller('LoginCtrl', function($scope, $auth, $location, $route) {
 
  $scope.emailLogin = function() {
  $auth.login({email: $scope.email, password: $scope.password})
      .then(function() {
//        toastr.success('You have successfully signed in!');
        $location.path('/');
        $route.reload();
      })
      .catch(function(error) {
//        toastr.error(error.data.message, error.status);
      });
  };
});

logout.js

'use strict';
 
app.controller('LogoutCtrl', function($location, $auth) {
  if (!$auth.isAuthenticated()) { return; }
  $auth.logout()
  .then(function() {
//  toastr.info('You have been logged out');
    $location.path('/');
  });
});

index.html

<!DOCTYPE html>
<html>
<head>
<!-- YOU NEED THIS TAG TO PREVENT D3JS CHARACTER ERROR!!! -->
<meta charset="utf-8">
 
<!-- LIBS CSS -->
<link rel="stylesheet" href="webjars/bootstrap/${bootstrap.version}/css/bootstrap.css">
</head>
<body ng-app="app">
<div class="container" ng-controller="ParentCtrl">
<h1>Auth</h1>
 
  <!-- MENU -->
  <div class="slide-animate"
  ng-include="'menu.html'" ></div>
 
  <!-- MAIN CONTENT -->
  <div class="view-animate"
  ng-view ></div>
 
</div>
 
<!-- LIBS JS -->
<script src="webjars/jquery/${jquery.version}/jquery.js"></script>
<script src="webjars/bootstrap/${bootstrap.version}/js/bootstrap.js"></script>
<script src="webjars/angularjs/${angularjs.version}/angular.js"></script>
<script src="webjars/angularjs/${angularjs.version}/angular-resource.js"></script>
<script src="webjars/angularjs/${angularjs.version}/angular-route.js"></script>
<script src="webjars/angularjs/${angularjs.version}/angular-animate.js"></script>
<script src="webjars/satellizer/${satellizer.version}/satellizer.js"></script>
<script src="webjars/ui-router/${ui-router.version}/release/angular-ui-router.js"></script>
 
<!-- YOUR JS -->
<script src="app.js"></script>
<script src="controllers/home.js"></script>
<script src="controllers/datas.js"></script>
<script src="controllers/login.js"></script>
<script src="controllers/logout.js"></script>
</body>
</html>

menu.html

<!-- MENU -->
<nav class="navbar navbar-default" >
<div class="container-fluid" ng-controller="NavbarCtrl">
 
<!-- HEADER AND MOBILE BUTTON -->
<div class="navbar-header">
  <button type="button" class="navbar-toggle"
    data-toggle="collapse"
    data-target="#bs-example-navbar-collapse-1"
    aria-expanded="true">
    <span class="sr-only">Toggle navigation</span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
  </button>
     
  <!-- LOGO -->
  <a class="navbar-brand" href="#/">
    MyApp</a>
</div>
   
<!-- MENU ITEMS -->
<div class="navbar-collapse collapse"
  id="bs-example-navbar-collapse-1"
  aria-expanded="true">
<ul class="nav navbar-nav">
  <li><a href="#/">Home</a></li>
  <li ng-if="isAuthenticated()"><a href="#/datas">Datas</a></li>
</ul>
  <ul ng-if="!isAuthenticated()" class="nav navbar-nav navbar-right">
    <li><a href="#/login">Login</a></li>
  </ul>
  <ul ng-if="isAuthenticated()" class="nav navbar-nav navbar-right">
    <li><a href="#/logout">Logout</a></li>
  </ul>
</div>
</div>
</nav>

datas.html

<h2>Datas</h2>
<!-- SECURED CONTENT FROM BACKEND-->
<div ng-if="isAuthenticated()">
  Content: 
<!-- Github ribbon-->
<a href="https://github.com/DamienFremont/blog" target="_blank">
    <img style="position: absolute; top: 50px; right: 0; border: 0;"
        src="/assets/img/forkme_right_green_007200.png" alt="Fork me on GitHub">
</a>

<div class="container-fluid">

    <div class="row p-3 p-md-5 p-xl-3 p-xxl-5">
        <div class="d-none d-sm-none d-md-none d-lg-block col-lg-2 offset-0">

            <div class="bg-body-tertiary p-4">

<div class="px-3">
    <ul class="list-unstyled site-tag-list">
        <li>
            <a class="text-reset text-decoration-none my-3" rel="tag" href="/posts/">
                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-tags" viewBox="0 0 16 16">
  <path d="M3 2v4.586l7 7L14.586 9l-7-7zM2 2a1 1 0 0 1 1-1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 2 6.586z"/>
  <path d="M5.5 5a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1m0 1a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3M1 7.086a1 1 0 0 0 .293.707L8.75 15.25l-.043.043a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 0 7.586V3a1 1 0 0 1 1-1z"/>
</svg> All Tutorials (96)
            </a>
        </li>
    </ul>
</div>

<hr/>

<h3 class="pt-0">Popular Topics</h3>
    <div class="px-3">
        <ul class="list-unstyled site-tag-list">
            <li class="my-2"><a class="text-reset text-decoration-none my-3" rel="tag" href="/tag/?query=java">
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-tag" viewBox="0 0 16 16">
  <path d="M6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m-1 0a.5.5 0 1 0-1 0 .5.5 0 0 0 1 0"/>
  <path d="M2 1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 1 6.586V2a1 1 0 0 1 1-1m0 5.586 7 7L13.586 9l-7-7H2z"/>
</svg> java (46)
</a></li>
            <li class="my-2"><a class="text-reset text-decoration-none my-3" rel="tag" href="/tag/?query=cucumber">
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-tag" viewBox="0 0 16 16">
  <path d="M6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m-1 0a.5.5 0 1 0-1 0 .5.5 0 0 0 1 0"/>
  <path d="M2 1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 1 6.586V2a1 1 0 0 1 1-1m0 5.586 7 7L13.586 9l-7-7H2z"/>
</svg> cucumber (7)
</a> BDD</li>
            <li class="my-2"><a class="text-reset text-decoration-none my-3" rel="tag" href="/tag/?query=javascript">
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-tag" viewBox="0 0 16 16">
  <path d="M6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m-1 0a.5.5 0 1 0-1 0 .5.5 0 0 0 1 0"/>
  <path d="M2 1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 1 6.586V2a1 1 0 0 1 1-1m0 5.586 7 7L13.586 9l-7-7H2z"/>
</svg> javascript (29)
</a></li>
            <li class="my-2"><a class="text-reset text-decoration-none my-3" rel="tag" href="/tag/?query=angularjs">
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-tag" viewBox="0 0 16 16">
  <path d="M6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m-1 0a.5.5 0 1 0-1 0 .5.5 0 0 0 1 0"/>
  <path d="M2 1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 1 6.586V2a1 1 0 0 1 1-1m0 5.586 7 7L13.586 9l-7-7H2z"/>
</svg> angularjs (21)
</a></li>
            <li class="my-2"><a class="text-reset text-decoration-none my-3" rel="tag" href="/tag/?query=bootstrap">
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-tag" viewBox="0 0 16 16">
  <path d="M6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m-1 0a.5.5 0 1 0-1 0 .5.5 0 0 0 1 0"/>
  <path d="M2 1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 1 6.586V2a1 1 0 0 1 1-1m0 5.586 7 7L13.586 9l-7-7H2z"/>
</svg> bootstrap (19)
</a></li>
            <li class="my-2"><a class="text-reset text-decoration-none my-3" rel="tag" href="/tag/?query=unity3d">
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-tag" viewBox="0 0 16 16">
  <path d="M6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m-1 0a.5.5 0 1 0-1 0 .5.5 0 0 0 1 0"/>
  <path d="M2 1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 1 6.586V2a1 1 0 0 1 1-1m0 5.586 7 7L13.586 9l-7-7H2z"/>
</svg> unity3d (11)
</a></li>
            <li class="my-2"><a class="text-reset text-decoration-none my-3" rel="tag" href="/tag/?query=junit">
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-tag" viewBox="0 0 16 16">
  <path d="M6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m-1 0a.5.5 0 1 0-1 0 .5.5 0 0 0 1 0"/>
  <path d="M2 1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 1 6.586V2a1 1 0 0 1 1-1m0 5.586 7 7L13.586 9l-7-7H2z"/>
</svg> junit (7)
</a></li>
            <li class="my-2"><a class="text-reset text-decoration-none my-3" rel="tag" href="/tag/?query=agile">
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-tag" viewBox="0 0 16 16">
  <path d="M6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m-1 0a.5.5 0 1 0-1 0 .5.5 0 0 0 1 0"/>
  <path d="M2 1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 1 6.586V2a1 1 0 0 1 1-1m0 5.586 7 7L13.586 9l-7-7H2z"/>
</svg> agile (4)
</a></li>
            <li class="my-2"><a class="text-reset text-decoration-none my-3" rel="tag" href="/tag/?query=rest">
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-tag" viewBox="0 0 16 16">
  <path d="M6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m-1 0a.5.5 0 1 0-1 0 .5.5 0 0 0 1 0"/>
  <path d="M2 1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 1 6.586V2a1 1 0 0 1 1-1m0 5.586 7 7L13.586 9l-7-7H2z"/>
</svg> rest (5)
</a> API</li>
            <li class="my-2"><a class="text-reset text-decoration-none my-3" rel="tag" href="/tag/?query=git">
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-tag" viewBox="0 0 16 16">
  <path d="M6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m-1 0a.5.5 0 1 0-1 0 .5.5 0 0 0 1 0"/>
  <path d="M2 1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 1 6.586V2a1 1 0 0 1 1-1m0 5.586 7 7L13.586 9l-7-7H2z"/>
</svg> git (8)
</a></li>
            <li class="my-2"><a class="text-reset text-decoration-none my-3" rel="tag" href="/tag/?query=spring">
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-tag" viewBox="0 0 16 16">
  <path d="M6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m-1 0a.5.5 0 1 0-1 0 .5.5 0 0 0 1 0"/>
  <path d="M2 1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 1 6.586V2a1 1 0 0 1 1-1m0 5.586 7 7L13.586 9l-7-7H2z"/>
</svg> spring (4)
</a></li>
            <li class="my-2"><a class="text-reset text-decoration-none my-3" rel="tag" href="/tag/?query=design">
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-tag" viewBox="0 0 16 16">
  <path d="M6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m-1 0a.5.5 0 1 0-1 0 .5.5 0 0 0 1 0"/>
  <path d="M2 1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 1 6.586V2a1 1 0 0 1 1-1m0 5.586 7 7L13.586 9l-7-7H2z"/>
</svg> design (3)
</a></li>
            <li class="my-2"><a class="text-reset text-decoration-none my-3" rel="tag" href="/tag/?query=photoshop">
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-tag" viewBox="0 0 16 16">
  <path d="M6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m-1 0a.5.5 0 1 0-1 0 .5.5 0 0 0 1 0"/>
  <path d="M2 1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 1 6.586V2a1 1 0 0 1 1-1m0 5.586 7 7L13.586 9l-7-7H2z"/>
</svg> photoshop (2)
</a></li>
            <li class="my-2"><a class="text-reset text-decoration-none my-3" rel="tag" href="/tag/?query=nodejs">
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-tag" viewBox="0 0 16 16">
  <path d="M6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m-1 0a.5.5 0 1 0-1 0 .5.5 0 0 0 1 0"/>
  <path d="M2 1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 1 6.586V2a1 1 0 0 1 1-1m0 5.586 7 7L13.586 9l-7-7H2z"/>
</svg> nodejs (4)
</a></li>
            <li class="my-2"><a class="text-reset text-decoration-none my-3" rel="tag" href="/tag/?query=selenium">
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-tag" viewBox="0 0 16 16">
  <path d="M6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m-1 0a.5.5 0 1 0-1 0 .5.5 0 0 0 1 0"/>
  <path d="M2 1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 1 6.586V2a1 1 0 0 1 1-1m0 5.586 7 7L13.586 9l-7-7H2z"/>
</svg> selenium (3)
</a></li>
        </ul>
    </div>
</div>


        </div>
        <div class="col-sm-12 col-md-8 col-lg-7 offset-0 px-xxl-5">

            <div class="article-header wp-block-group mb-3">

    <h2 class="article-title wp-block-post-title fw-bold">
        <span class="site-strapline">Dev.</span>
        Javaee Angularjs Bootstrap Howto Charts With D3js
    </h2>

    <div class="post-meta taxonomy-category d-flex flex-wrap">

        <div class="">
            <small>By <a class="text-reset wp-block-heading" href="/about">Damien</a></small>
            ·
            <small class="date wp-block-post-date">2015-11-08</small>
            &nbsp;
        </div>

        <div class="flex-grow-1">
            
            <a href="/tag/?query=angularjs"
                class="badge rounded-pill bg-secondary text-decoration-none" rel="tag">angularjs</a>
            
            <a href="/tag/?query=java"
                class="badge rounded-pill bg-secondary text-decoration-none" rel="tag">java</a>
            
            <a href="/tag/?query=javascript"
                class="badge rounded-pill bg-secondary text-decoration-none" rel="tag">javascript</a>
            
            <a href="/tag/?query=bootstrap"
                class="badge rounded-pill bg-secondary text-decoration-none" rel="tag">bootstrap</a>
            
        </div>

    </div>

</div>

<div class="post-content wp-block-post-content"><p><img src="/upload/post-thumbnail-angularjs.png" alt="alt text" /></p>

<p>Here simple use cases: a static Bar chart and a dynamic Line chart. It’s build with d3js and nvd3 for angularjs integration and java jersey for backend datas.</p>

<p>Note: for more advanced use cases, you’ll need to create your own angularjs directive working directly with d3js.</p>

<h1 id="demo">Demo</h1>

<p><a href="http://localhost:8080/20151108-javaee-angularjs-bootstrap-charts_d3js/">http://localhost:8080/20151108-javaee-angularjs-bootstrap-charts_d3js/</a>
http://localhost:8080/20151108-javaee-angularjs-bootstrap-charts_d3js/</p>

<p>Here the two uses cases: bar charts and line charts.</p>

<p><img src="/upload/160523003625912.png" alt="alt text" /></p>

<p>There is a tooltip for each datas in charts.</p>

<p><img src="/upload/160523003626367.png" alt="alt text" /></p>

<p>There are two instances of Line chart:</p>

<ul>
  <li>static (unique update at loading time)</li>
  <li>dynamic (refreshing every second)</li>
</ul>

<p><img src="/upload/160523003626513.gif" alt="alt text" /></p>

<p>Caution: for each refresh you’ll ended with a backend request. Pay attention to performance and load (bigger refresh interval, or replace only with new datas)</p>

<p><img src="/upload/160523003627210.png" alt="alt text" /></p>

<p>Java Data back-end response (build with Jersey JAX-RS impl).</p>

<p><img src="/upload/160523003627446.png" alt="alt text" /></p>

<h1 id="source">Source</h1>

<p><img src="/upload/160523003627906.png" alt="alt text" /></p>

<p>MyAppCONFIG.java</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">com.damienfremont.blog</span><span class="o">;</span>
 
<span class="kn">import</span> <span class="nn">java.util.HashSet</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Set</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">javax.ws.rs.core.Application</span><span class="o">;</span>
 
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">MyAppCONFIG</span> <span class="kd">extends</span> <span class="nc">Application</span> <span class="o">{</span>
 
  <span class="nd">@Override</span>
  <span class="kd">public</span> <span class="nc">Set</span><span class="o">&lt;</span><span class="nc">Class</span><span class="o">&lt;?&gt;&gt;</span> <span class="n">getClasses</span><span class="o">()</span> <span class="o">{</span>
    <span class="nc">Set</span><span class="o">&lt;</span><span class="nc">Class</span><span class="o">&lt;?&gt;&gt;</span> <span class="n">s</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashSet</span><span class="o">&lt;</span><span class="nc">Class</span><span class="o">&lt;?&gt;&gt;();</span>
    <span class="n">s</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="nc">ServiceJAXRS</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
    <span class="k">return</span> <span class="n">s</span><span class="o">;</span>
  <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>ServiceJAXRS.java</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">com.damienfremont.blog</span><span class="o">;</span>
 
<span class="kn">import</span> <span class="nn">java.util.ArrayList</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.List</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Random</span><span class="o">;</span>
 
<span class="kn">import</span> <span class="nn">javax.ws.rs.GET</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">javax.ws.rs.Path</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">javax.ws.rs.Produces</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">javax.ws.rs.core.MediaType</span><span class="o">;</span>
 
 
<span class="nd">@Path</span><span class="o">(</span><span class="s">"/datas"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ServiceJAXRS</span> <span class="o">{</span>
 
  <span class="nd">@Path</span><span class="o">(</span><span class="s">"/values"</span><span class="o">)</span>
  <span class="nd">@GET</span>
  <span class="nd">@Produces</span><span class="o">(</span><span class="nc">MediaType</span><span class="o">.</span><span class="na">APPLICATION_JSON</span><span class="o">)</span>
  <span class="kd">public</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">List</span><span class="o">&gt;</span> <span class="nf">getAll</span><span class="o">()</span> <span class="o">{</span>
    <span class="k">return</span> <span class="n">mockDatas</span><span class="o">;</span>
  <span class="o">}</span>
   
  <span class="nd">@Path</span><span class="o">(</span><span class="s">"/values-big"</span><span class="o">)</span>
  <span class="nd">@GET</span>
  <span class="nd">@Produces</span><span class="o">(</span><span class="nc">MediaType</span><span class="o">.</span><span class="na">APPLICATION_JSON</span><span class="o">)</span>
  <span class="kd">public</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">List</span><span class="o">&gt;</span> <span class="nf">getAllReal</span><span class="o">()</span> <span class="o">{</span>
    <span class="c1">// MOCK: UPDATE FOR REAL TIME</span>
    <span class="n">mockDatasReal</span><span class="o">.</span><span class="na">remove</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
    <span class="n">mockStart</span> <span class="o">=</span> <span class="n">mockStart</span> <span class="o">+</span> <span class="n">mockInterval</span><span class="o">;</span>
    <span class="n">mockDatasReal</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">newValue</span><span class="o">(</span><span class="n">mockStart</span><span class="o">));</span>
    <span class="k">return</span> <span class="n">mockDatasReal</span><span class="o">;</span>
  <span class="o">}</span>
   
  <span class="c1">// MOCK</span>
  <span class="c1">// MOCK: INIT</span>
  <span class="kd">static</span> <span class="nc">ArrayList</span><span class="o">&lt;</span><span class="nc">List</span><span class="o">&gt;</span> <span class="n">mockDatas</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ArrayList</span><span class="o">&lt;&gt;();</span>
  <span class="kd">static</span> <span class="o">{</span>
    <span class="kt">long</span> <span class="n">mockStart</span> <span class="o">=</span> <span class="mi">1025409600000L</span><span class="o">;</span>
    <span class="kt">long</span> <span class="n">mockInterval</span> <span class="o">=</span> <span class="mi">2592000000L</span><span class="o">;</span>
    <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
      <span class="n">mockStart</span> <span class="o">=</span> <span class="n">mockStart</span> <span class="o">+</span> <span class="n">mockInterval</span><span class="o">;</span>
      <span class="n">mockDatas</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">newValue</span><span class="o">(</span><span class="n">mockStart</span><span class="o">));</span>
    <span class="o">}</span>
  <span class="o">}</span>
   
  <span class="kd">static</span> <span class="nc">ArrayList</span><span class="o">&lt;</span><span class="nc">List</span><span class="o">&gt;</span> <span class="n">mockDatasReal</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ArrayList</span><span class="o">&lt;&gt;();</span>
  <span class="kd">static</span> <span class="kt">long</span> <span class="n">mockStart</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
  <span class="kd">static</span> <span class="kt">long</span> <span class="n">mockInterval</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
  <span class="kd">static</span> <span class="o">{</span>
    <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">50</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
      <span class="n">mockStart</span> <span class="o">=</span> <span class="n">mockStart</span> <span class="o">+</span> <span class="n">mockInterval</span><span class="o">;</span>
      <span class="n">mockDatasReal</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">newValue</span><span class="o">(</span><span class="n">mockStart</span><span class="o">));</span>
    <span class="o">}</span>
  <span class="o">}</span>
  <span class="kd">private</span> <span class="kd">static</span> <span class="nc">ArrayList</span><span class="o">&lt;</span><span class="nc">Long</span><span class="o">&gt;</span> <span class="nf">newValue</span><span class="o">(</span><span class="kt">long</span> <span class="n">start</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">long</span> <span class="n">randomNum</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Random</span><span class="o">().</span><span class="na">nextInt</span><span class="o">(</span><span class="mi">50</span><span class="o">)</span> <span class="o">+</span> <span class="mi">1</span><span class="o">;</span>
    <span class="nc">ArrayList</span><span class="o">&lt;</span><span class="nc">Long</span><span class="o">&gt;</span> <span class="n">value</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ArrayList</span><span class="o">&lt;&gt;();</span>
    <span class="n">value</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">start</span><span class="o">);</span>
    <span class="n">value</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">randomNum</span><span class="o">);</span>
    <span class="k">return</span> <span class="n">value</span><span class="o">;</span>
  <span class="o">}</span>
 
<span class="o">}</span>
</code></pre></div></div>

<p>web.xml</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;web-app</span> <span class="na">xmlns=</span><span class="s">"http://xmlns.jcp.org/xml/ns/javaee"</span> <span class="na">xmlns:xsi=</span><span class="s">"http://www.w3.org/2001/XMLSchema-instance"</span> <span class="na">xsi:schemaLocation=</span><span class="s">"http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"</span> <span class="na">version=</span><span class="s">"3.1"</span><span class="nt">&gt;</span>
 
  <span class="nt">&lt;servlet&gt;</span>
    <span class="nt">&lt;servlet-name&gt;</span>REST<span class="nt">&lt;/servlet-name&gt;</span>
    <span class="nt">&lt;servlet-class&gt;</span>org.glassfish.jersey.servlet.ServletContainer<span class="nt">&lt;/servlet-class&gt;</span>
    <span class="nt">&lt;init-param&gt;</span>
      <span class="nt">&lt;param-name&gt;</span>javax.ws.rs.Application<span class="nt">&lt;/param-name&gt;</span>
      <span class="nt">&lt;param-value&gt;</span>com.damienfremont.blog.MyAppCONFIG<span class="nt">&lt;/param-value&gt;</span>
    <span class="nt">&lt;/init-param&gt;</span>
    <span class="nt">&lt;init-param&gt;</span>
      <span class="nt">&lt;param-name&gt;</span>jersey.config.server.provider.classnames<span class="nt">&lt;/param-name&gt;</span>
      <span class="nt">&lt;param-value&gt;</span>org.glassfish.jersey.media.multipart.MultiPartFeature<span class="nt">&lt;/param-value&gt;</span>
    <span class="nt">&lt;/init-param&gt;</span>
    <span class="nt">&lt;load-on-startup&gt;</span>1<span class="nt">&lt;/load-on-startup&gt;</span>
  <span class="nt">&lt;/servlet&gt;</span>
  <span class="nt">&lt;servlet-mapping&gt;</span>
    <span class="nt">&lt;servlet-name&gt;</span>REST<span class="nt">&lt;/servlet-name&gt;</span>
    <span class="nt">&lt;url-pattern&gt;</span>/api/*<span class="nt">&lt;/url-pattern&gt;</span>
  <span class="nt">&lt;/servlet-mapping&gt;</span>
 
  <span class="nt">&lt;servlet&gt;</span>
    <span class="nt">&lt;servlet-name&gt;</span>WEBJARS<span class="nt">&lt;/servlet-name&gt;</span>
    <span class="nt">&lt;servlet-class&gt;</span>org.webjars.servlet.WebjarsServlet<span class="nt">&lt;/servlet-class&gt;</span>
    <span class="nt">&lt;init-param&gt;</span>
      <span class="nt">&lt;param-name&gt;</span>disableCache<span class="nt">&lt;/param-name&gt;</span>
      <span class="nt">&lt;param-value&gt;</span>true<span class="nt">&lt;/param-value&gt;</span>
    <span class="nt">&lt;/init-param&gt;</span>
    <span class="nt">&lt;load-on-startup&gt;</span>2<span class="nt">&lt;/load-on-startup&gt;</span>
  <span class="nt">&lt;/servlet&gt;</span>
  <span class="nt">&lt;servlet-mapping&gt;</span>
    <span class="nt">&lt;servlet-name&gt;</span>WEBJARS<span class="nt">&lt;/servlet-name&gt;</span>
    <span class="nt">&lt;url-pattern&gt;</span>/webjars/*<span class="nt">&lt;/url-pattern&gt;</span>
  <span class="nt">&lt;/servlet-mapping&gt;</span>
 
<span class="nt">&lt;/web-app&gt;</span>
</code></pre></div></div>

<p>app.js</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="dl">'</span><span class="s1">use strict</span><span class="dl">'</span><span class="p">;</span>
 
<span class="kd">var</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">app</span><span class="dl">'</span><span class="p">,</span> <span class="p">[</span> <span class="dl">'</span><span class="s1">ngResource</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">nvd3ChartDirectives</span><span class="dl">'</span> <span class="p">]);</span>
 
<span class="c1">// BAR *************</span>
 
<span class="nx">app</span><span class="p">.</span><span class="nx">factory</span><span class="p">(</span><span class="dl">'</span><span class="s1">Service</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">$resource</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">return</span> <span class="nx">$resource</span><span class="p">(</span><span class="dl">'</span><span class="s1">api/datas/values</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>
 
<span class="nx">app</span><span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">BarCtrl</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">$scope</span><span class="p">,</span> <span class="nx">Service</span><span class="p">)</span> <span class="p">{</span>
 
  <span class="c1">// FORMATTING FUNCTION (OPTIONNAL)</span>
  <span class="nx">$scope</span><span class="p">.</span><span class="nx">xAxisTickFormatFunction</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="kd">function</span><span class="p">(</span><span class="nx">d</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="nx">d3</span><span class="p">.</span><span class="nx">time</span><span class="p">.</span><span class="nx">format</span><span class="p">(</span><span class="dl">'</span><span class="s1">%b</span><span class="dl">'</span><span class="p">)(</span><span class="k">new</span> <span class="nb">Date</span><span class="p">(</span><span class="nx">d</span><span class="p">));</span>
    <span class="p">}</span>
  <span class="p">}</span>
   
  <span class="c1">// INIT</span>
  <span class="nx">Service</span><span class="p">.</span><span class="nx">query</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">datas</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">$scope</span><span class="p">.</span><span class="nx">exampleData</span> <span class="o">=</span> <span class="p">[</span> <span class="p">{</span>
      <span class="dl">"</span><span class="s2">key</span><span class="dl">"</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">Series 1</span><span class="dl">"</span><span class="p">,</span>
      <span class="dl">"</span><span class="s2">values</span><span class="dl">"</span> <span class="p">:</span> <span class="nx">datas</span>
    <span class="p">}</span> <span class="p">];</span>
  <span class="p">});</span>
<span class="p">});</span>
 
<span class="c1">// LINE IN REAL TIME ******</span>
 
<span class="nx">app</span><span class="p">.</span><span class="nx">factory</span><span class="p">(</span><span class="dl">'</span><span class="s1">ServiceReal</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">$resource</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">return</span> <span class="nx">$resource</span><span class="p">(</span><span class="dl">'</span><span class="s1">api/datas/values-big</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>
 
<span class="nx">app</span><span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">RealTimeCtrl</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">$scope</span><span class="p">,</span> <span class="nx">Service</span><span class="p">,</span> <span class="nx">ServiceReal</span><span class="p">)</span> <span class="p">{</span>
     
  <span class="c1">// REFRESH VALUE:  0.1 SEC</span>
  <span class="kd">var</span> <span class="nx">refreshInterval</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">;</span>
   
  <span class="c1">// UPDATE</span>
  <span class="nx">$scope</span><span class="p">.</span><span class="nx">fetchData</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
      <span class="nx">ServiceReal</span>
    <span class="p">.</span><span class="nx">query</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">datas</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">$scope</span><span class="p">.</span><span class="nx">exampleData</span> <span class="o">=</span> <span class="p">[</span> <span class="p">{</span>
          <span class="na">key</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">Series 1</span><span class="dl">'</span><span class="p">,</span>
          <span class="na">values</span> <span class="p">:</span> <span class="nx">datas</span><span class="p">,</span>
          <span class="na">color</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">#ff7f0e</span><span class="dl">'</span>
        <span class="p">}</span> <span class="p">];</span>
      <span class="p">});</span>
  <span class="p">}</span>
  <span class="nx">$scope</span><span class="p">.</span><span class="nx">fetchData2</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
      <span class="nx">ServiceReal</span>
        <span class="p">.</span><span class="nx">query</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">datas</span><span class="p">)</span> <span class="p">{</span>
            <span class="nx">$scope</span><span class="p">.</span><span class="nx">exampleData2</span> <span class="o">=</span> <span class="p">[</span> <span class="p">{</span>
              <span class="na">key</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">Series 1</span><span class="dl">'</span><span class="p">,</span>
              <span class="na">values</span> <span class="p">:</span> <span class="nx">datas</span><span class="p">,</span>
              <span class="na">color</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">#ff7f0e</span><span class="dl">'</span>
            <span class="p">}</span> <span class="p">];</span>
          <span class="p">});</span>
      <span class="p">}</span>
     
  <span class="c1">// EVERY X TIME</span>
  <span class="nx">setInterval</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">$scope</span><span class="p">.</span><span class="nx">$apply</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
        <span class="nx">$scope</span><span class="p">.</span><span class="nx">fetchData2</span><span class="p">();</span>
    <span class="p">})</span>
  <span class="p">},</span> <span class="nx">refreshInterval</span><span class="p">);</span>
   
  <span class="c1">// INIT</span>
  <span class="nx">$scope</span><span class="p">.</span><span class="nx">fetchData</span><span class="p">();</span>
  <span class="nx">$scope</span><span class="p">.</span><span class="nx">fetchData2</span><span class="p">();</span>
<span class="p">});</span>
</code></pre></div></div>

<p>index.html</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;!DOCTYPE html&gt;</span>
<span class="nt">&lt;html&gt;</span>
<span class="nt">&lt;head&gt;</span>
<span class="c">&lt;!-- YOU NEED THIS TAG TO PREVENT D3JS CHARACTER ERROR!!! --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span><span class="nt">&gt;</span>
 
<span class="c">&lt;!-- LIBS CSS --&gt;</span>
<span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">href=</span><span class="s">"webjars/bootstrap/${bootstrap.version}/css/bootstrap.css"</span><span class="nt">&gt;</span>
<span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">href=</span><span class="s">"webjars/nvd3/${nvd3.version}/nv.d3.css"</span><span class="nt">&gt;</span>
<span class="nt">&lt;/head&gt;</span>
<span class="nt">&lt;body</span> <span class="na">ng-app=</span><span class="s">"app"</span><span class="nt">&gt;</span>
<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"container"</span><span class="nt">&gt;</span>
<span class="nt">&lt;h1&gt;</span>Charts<span class="nt">&lt;/h1&gt;</span>
 
<span class="c">&lt;!-- BARS --&gt;</span>
<span class="nt">&lt;h4&gt;</span>Bar Charts<span class="nt">&lt;/h4&gt;</span>
<span class="nt">&lt;div</span> <span class="na">ng-controller=</span><span class="s">"BarCtrl"</span><span class="nt">&gt;</span>
<span class="nt">&lt;nvd3-discrete-bar-chart</span>
        <span class="na">data=</span><span class="s">"exampleData"</span>
        <span class="na">showXAxis=</span><span class="s">"true"</span>
        <span class="na">showYAxis=</span><span class="s">"true"</span>
        <span class="na">xAxisTickFormat=</span><span class="s">"xAxisTickFormatFunction()"</span><span class="nt">&gt;</span>
            <span class="nt">&lt;svg&gt;&lt;/svg&gt;</span>
    <span class="nt">&lt;/nvd3-discrete-bar-chart&gt;</span>
<span class="nt">&lt;/div&gt;</span>
 
<span class="c">&lt;!-- REAL TIME --&gt;</span>
<span class="nt">&lt;h4&gt;</span>Real Time Charts<span class="nt">&lt;/h4&gt;</span>
<span class="nt">&lt;div</span> <span class="na">ng-controller=</span><span class="s">"RealTimeCtrl"</span><span class="nt">&gt;</span>
   <span class="nt">&lt;h5&gt;</span>Static<span class="nt">&lt;/h5&gt;</span>
   <span class="nt">&lt;nvd3-line-chart</span>
     <span class="na">data=</span><span class="s">"exampleData"</span>
     <span class="na">showXAxis=</span><span class="s">"true"</span>
     <span class="na">showYAxis=</span><span class="s">"true"</span>
     <span class="na">tooltips=</span><span class="s">"true"</span>
     <span class="na">interactive=</span><span class="s">"true"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;svg&gt;&lt;/svg&gt;</span>
    <span class="nt">&lt;/nvd3-line-chart&gt;</span>
 
 
    <span class="nt">&lt;h5&gt;</span>Real<span class="nt">&lt;/h5&gt;</span>
    <span class="nt">&lt;nvd3-line-chart</span>
     <span class="na">data=</span><span class="s">"exampleData2"</span>
     <span class="na">showXAxis=</span><span class="s">"true"</span>
     <span class="na">showYAxis=</span><span class="s">"true"</span>
     <span class="na">tooltips=</span><span class="s">"true"</span>
     <span class="na">interactive=</span><span class="s">"true"</span>
      
     <span class="na">objectEquality=</span><span class="s">"true"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;svg&gt;&lt;/svg&gt;</span>
    <span class="nt">&lt;/nvd3-line-chart&gt;</span>
<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
 
<span class="c">&lt;!-- LIBS JS --&gt;</span>
<span class="nt">&lt;script</span> <span class="na">src=</span><span class="s">"webjars/angularjs/${angularjs.version}/angular.js"</span><span class="nt">&gt;&lt;/script&gt;</span>
<span class="nt">&lt;script</span> <span class="na">src=</span><span class="s">"webjars/angularjs/${angularjs.version}/angular-resource.js"</span><span class="nt">&gt;&lt;/script&gt;</span>
<span class="nt">&lt;script</span> <span class="na">src=</span><span class="s">"webjars/d3js/${d3js.version}/d3.js"</span><span class="nt">&gt;&lt;/script&gt;</span>
<span class="nt">&lt;script</span> <span class="na">src=</span><span class="s">"webjars/nvd3/${nvd3.version}/nv.d3.js"</span><span class="nt">&gt;&lt;/script&gt;</span>
<span class="nt">&lt;script</span> <span class="na">src=</span><span class="s">"webjars/angularjs-nvd3-directives/${angularjs-nvd3-directives.version}/angularjs-nvd3-directives.js"</span><span class="nt">&gt;&lt;/script&gt;</span>
 
<span class="c">&lt;!-- YOUR JS --&gt;</span>
<span class="nt">&lt;script</span> <span class="na">src=</span><span class="s">"app.js"</span><span class="nt">&gt;&lt;/script&gt;</span>
<span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span>
</code></pre></div></div>

<h1 id="project">Project</h1>

<p><a href="https://github.com/DamienFremont/damienfremont.com-blog-labs/tree/master/20151108-javaee-angularjs-bootstrap-charts_d3js">https://github.com/DamienFremont/damienfremont.com-blog-labs/tree/master/20151108-javaee-angularjs-bootstrap-charts_d3js</a>
https://github.com/DamienFremont/damienfremont.com-blog-labs/tree/master/20151108-javaee-angularjs-bootstrap-charts_d3js</p>

<h1 id="references">References</h1>

<p><a href="http://cmaurer.github.io/angularjs-nvd3-directives/">http://cmaurer.github.io/angularjs-nvd3-directives/</a>
http://cmaurer.github.io/angularjs-nvd3-directives/</p>

<p><a href="http://ngmodules.org/modules/angularjs-nvd3-directives">http://ngmodules.org/modules/angularjs-nvd3-directives</a>
http://ngmodules.org/modules/angularjs-nvd3-directives</p>

<p><a href="https://github.com/angularjs-nvd3-directives/angularjs-nvd3-directives">https://github.com/angularjs-nvd3-directives/angularjs-nvd3-directives</a>
https://github.com/angularjs-nvd3-directives/angularjs-nvd3-directives</p>

<p><a href="https://github.com/angularjs-nvd3-directives/angularjs-nvd3-directives/blob/master/examples/objectEquality.html">https://github.com/angularjs-nvd3-directives/angularjs-nvd3-directives/blob/master/examples/objectEquality.html</a>
https://github.com/angularjs-nvd3-directives/angularjs-nvd3-directives/blob/master/examples/objectEquality.html</p>

<p><a href="http://busypeoples.github.io/post/promises-in-angular-js/">http://busypeoples.github.io/post/promises-in-angular-js/</a>
http://busypeoples.github.io/post/promises-in-angular-js/</p>

<h2 id="origin">Origin</h2>
<p><a href="https://damienfremont.com/2015/11/08/javaee-angularjs-bootstrap-howto-charts-with-d3js/">https://damienfremont.com/2015/11/08/javaee-angularjs-bootstrap-howto-charts-with-d3js/</a></p>

</div>

            <div class="row border rounded p-3 mt-5">

    <div class="col-4 cold-md-2 p-3">
        <img class="rounded-circle float-end" width="96" height="96" src="/assets/img/avatar-damien.jpg" />
    </div>

    <div class="col-8 cold-md-10">
        <h5>Hi, I'm <a class="text-reset" href="/about">Damien</a></h5>

        <p class="text-muted">
            Software Developer
        </p>
        <p>
            <a class="p-2 text-reset text-decoration-none" href="https://www.linkedin.com/in/damienfremont/" target="_blank" rel="noopener">
                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-linkedin"
    viewBox="0 0 16 16">
    <path
        d="M0 1.146C0 .513.526 0 1.175 0h13.65C15.474 0 16 .513 16 1.146v13.708c0 .633-.526 1.146-1.175 1.146H1.175C.526 16 0 15.487 0 14.854zm4.943 12.248V6.169H2.542v7.225zm-1.2-8.212c.837 0 1.358-.554 1.358-1.248-.015-.709-.52-1.248-1.342-1.248S2.4 3.226 2.4 3.934c0 .694.521 1.248 1.327 1.248zm4.908 8.212V9.359c0-.216.016-.432.08-.586.173-.431.568-.878 1.232-.878.869 0 1.216.662 1.216 1.634v3.865h2.401V9.25c0-2.22-1.184-3.252-2.764-3.252-1.274 0-1.845.7-2.165 1.193v.025h-.016l.016-.025V6.169h-2.4c.03.678 0 7.225 0 7.225z" />
</svg>
            </a>
            <a class="p-2 text-reset text-decoration-none" href="https://github.com/damienfremont" target="_blank" rel="noopener">
                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-github"
    viewBox="0 0 16 16">
    <path
        d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8" />
</svg>
            </a>
            <a class="p-2 text-reset text-decoration-none" href="https://x.com/damien_fremont" target="_blank" rel="noopener">
                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" role="img" viewBox="0 0 1024 1024">
    <title>X</title>
    <path fill="currentColor"
        d="M818 800 498.11 333.745l.546.437L787.084 0h-96.385L455.738 272 269.15 0H16.367l298.648 435.31-.036-.037L0 800h96.385l261.222-302.618L565.217 800zM230.96 72.727l448.827 654.546h-76.38L154.217 72.727z"
        transform="translate(103 112)" />
</svg>
            </a>
        </p>
        <p class="text-muted">
            Founder of this blog, love Java and Open Source stuff. Follow him on Twitter.
        </p>
    </div>

</div>


        </div>
        <div class="col-sm-6 col-md-4 col-lg-3 offset-0">

            
            <h3 class="pt-0 fw-bold text-secondary">Most Read</h3>

<div class="list-group shadow">

    

    <div class="pb-xl-2 list-group-item">

        <a href="/2021/02/18/test-driven-development-tdd-in-java-helloworld-examples" class="text-reset text-decoration-none h-100">

            <div class="row">
                <div class="col-md-2">
                    <span class="display-6">
                        1
                    </span>
                </div>
                <div class="col">

                    <h6 class="fw-bold text-limit-line-2 my-0">
                        <span class="site-strapline">Dev.</span>

                        How-to JUnit: Test Driven Development / TDD In Java (Step by step with Helloworld Examples)

                    </h6>
                    <div>
                        <small class="text-body-secondary">

                            
                            <span class="text-muted"> java </span>
                            
                            <span class="text-muted"> junit </span>
                            
                            <span class="text-muted"> spring </span>
                            

                        </small>
                    </div>

                </div>
            </div>
        </a>
    </div>

    

    <div class="pb-xl-2 list-group-item">

        <a href="/2017/11/23/rest-api-maturity-levels-from-0-to-5" class="text-reset text-decoration-none h-100">

            <div class="row">
                <div class="col-md-2">
                    <span class="display-6">
                        2
                    </span>
                </div>
                <div class="col">

                    <h6 class="fw-bold text-limit-line-2 my-0">
                        <span class="site-strapline">Dev.</span>

                        RESTful API Maturity Levels - From 0 To 5

                    </h6>
                    <div>
                        <small class="text-body-secondary">

                            
                            <span class="text-muted"> design </span>
                            
                            <span class="text-muted"> rest </span>
                            

                        </small>
                    </div>

                </div>
            </div>
        </a>
    </div>

    

    <div class="pb-xl-2 list-group-item">

        <a href="/2017/11/11/maslows-hierarchy-of-needs-for-software-developers" class="text-reset text-decoration-none h-100">

            <div class="row">
                <div class="col-md-2">
                    <span class="display-6">
                        3
                    </span>
                </div>
                <div class="col">

                    <h6 class="fw-bold text-limit-line-2 my-0">
                        <span class="site-strapline">Dev.</span>

                        Maslows Hierarchy Of Needs For Software Developers (Not Food!)

                    </h6>
                    <div>
                        <small class="text-body-secondary">

                            
                            <span class="text-muted"> agile </span>
                            
                            <span class="text-muted"> quicktip </span>
                            

                        </small>
                    </div>

                </div>
            </div>
        </a>
    </div>

    

    <div class="pb-xl-2 list-group-item">

        <a href="/2015/07/23/how-to-cucumber-java-reuse-same-scenario-for-core-service-and-web-ui-tests" class="text-reset text-decoration-none h-100">

            <div class="row">
                <div class="col-md-2">
                    <span class="display-6">
                        4
                    </span>
                </div>
                <div class="col">

                    <h6 class="fw-bold text-limit-line-2 my-0">
                        <span class="site-strapline">Dev.</span>

                        How-To Cucumber: Re-use Same Scenario For Core Service And Web UI Tests

                    </h6>
                    <div>
                        <small class="text-body-secondary">

                            
                            <span class="text-muted"> bdd </span>
                            
                            <span class="text-muted"> cucumber </span>
                            
                            <span class="text-muted"> java </span>
                            

                        </small>
                    </div>

                </div>
            </div>
        </a>
    </div>

    

    <div class="pb-xl-2 list-group-item">

        <a href="/2014/12/19/how-to-expandcollapse-table-rows-with-bootstrap" class="text-reset text-decoration-none h-100">

            <div class="row">
                <div class="col-md-2">
                    <span class="display-6">
                        5
                    </span>
                </div>
                <div class="col">

                    <h6 class="fw-bold text-limit-line-2 my-0">
                        <span class="site-strapline">Dev.</span>

                        How-To Bootstrap: Expand and Collapse Table Rows With Bootstrap

                    </h6>
                    <div>
                        <small class="text-body-secondary">

                            
                            <span class="text-muted"> bootstrap </span>
                            
                            <span class="text-muted"> css </span>
                            
                            <span class="text-muted"> javascript </span>
                            

                        </small>
                    </div>

                </div>
            </div>
        </a>
    </div>

    

</div>

            <br />

            <div class="bg-body-tertiary px-4 py-3">
        
    <h4 class="pt-0">Follow on</h4>

<ul class="list-unstyled wp-container-62130c4b8662b wp-block-social-links has-normal-icon-size">

    <li><a target="_blank" href="https://www.linkedin.com/in/damienfremont"
            class="text-reset text-decoration-none">
            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-linkedin"
    viewBox="0 0 16 16">
    <path
        d="M0 1.146C0 .513.526 0 1.175 0h13.65C15.474 0 16 .513 16 1.146v13.708c0 .633-.526 1.146-1.175 1.146H1.175C.526 16 0 15.487 0 14.854zm4.943 12.248V6.169H2.542v7.225zm-1.2-8.212c.837 0 1.358-.554 1.358-1.248-.015-.709-.52-1.248-1.342-1.248S2.4 3.226 2.4 3.934c0 .694.521 1.248 1.327 1.248zm4.908 8.212V9.359c0-.216.016-.432.08-.586.173-.431.568-.878 1.232-.878.869 0 1.216.662 1.216 1.634v3.865h2.401V9.25c0-2.22-1.184-3.252-2.764-3.252-1.274 0-1.845.7-2.165 1.193v.025h-.016l.016-.025V6.169h-2.4c.03.678 0 7.225 0 7.225z" />
</svg>
            <span class="mx-2">LinkedIn</span></a></li>
    
    <li><a target="_blank" href="https://github.com/damienfremont"
            class="text-reset text-decoration-none">
            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-github"
    viewBox="0 0 16 16">
    <path
        d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8" />
</svg>
            <span class="mx-2">Github</span></a></li>
    
    <li><a target="_blank" href="http://x.com/damien_fremont"
            class="text-reset text-decoration-none">
            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" role="img" viewBox="0 0 1024 1024">
    <title>X</title>
    <path fill="currentColor"
        d="M818 800 498.11 333.745l.546.437L787.084 0h-96.385L455.738 272 269.15 0H16.367l298.648 435.31-.036-.037L0 800h96.385l261.222-302.618L565.217 800zM230.96 72.727l448.827 654.546h-76.38L154.217 72.727z"
        transform="translate(103 112)" />
</svg>
            <span class="mx-2">X / Twitter</span></a></li>
    
    <li><a target="_blank" href="https://www.facebook.com/DamienFremontBlog/"
            class="text-reset text-decoration-none">
            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-facebook"
    viewBox="0 0 16 16">
    <path
        d="M16 8.049c0-4.446-3.582-8.05-8-8.05C3.58 0-.002 3.603-.002 8.05c0 4.017 2.926 7.347 6.75 7.951v-5.625h-2.03V8.05H6.75V6.275c0-2.017 1.195-3.131 3.022-3.131.876 0 1.791.157 1.791.157v1.98h-1.009c-.993 0-1.303.621-1.303 1.258v1.51h2.218l-.354 2.326H9.25V16c3.824-.604 6.75-3.934 6.75-7.951" />
</svg>
            <span class="mx-2">Facebook</span></a></li>
    
    <li><a target="_blank" href="https://play.google.com/store/apps/dev?id=8294041563468906844"
            class="text-reset text-decoration-none">
            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-google-play"
    viewBox="0 0 16 16">
    <path
        d="M14.222 9.374c1.037-.61 1.037-2.137 0-2.748L11.528 5.04 8.32 8l3.207 2.96zm-3.595 2.116L7.583 8.68 1.03 14.73c.201 1.029 1.36 1.61 2.303 1.055zM1 13.396V2.603L6.846 8zM1.03 1.27l6.553 6.05 3.044-2.81L3.333.215C2.39-.341 1.231.24 1.03 1.27" />
</svg>
            <span class="mx-2">GooglePlay</span></a></li>


    <li><a target="_blank" href="https://discord.com/invite/PPTjWjjm9a"
            class="text-reset text-decoration-none">
            <?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="currentColor" width="18" height="18" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
    <path
        d="M9.593 10.971c-.542 0-.969.475-.969 1.055 0 .578.437 1.055.969 1.055.541 0 .968-.477.968-1.055.011-.581-.427-1.055-.968-1.055zm3.468 0c-.542 0-.969.475-.969 1.055 0 .578.437 1.055.969 1.055.541 0 .968-.477.968-1.055-.001-.581-.427-1.055-.968-1.055z" />
    <path
        d="M17.678 3H4.947A1.952 1.952 0 0 0 3 4.957v12.844c0 1.083.874 1.957 1.947 1.957H15.72l-.505-1.759 1.217 1.131 1.149 1.064L19.625 22V4.957A1.952 1.952 0 0 0 17.678 3zM14.01 15.407s-.342-.408-.626-.771c1.244-.352 1.719-1.13 1.719-1.13-.39.256-.76.438-1.093.562a6.679 6.679 0 0 1-3.838.398 7.944 7.944 0 0 1-1.396-.41 5.402 5.402 0 0 1-.693-.321c-.029-.021-.057-.029-.085-.048a.117.117 0 0 1-.039-.03c-.171-.094-.266-.16-.266-.16s.456.76 1.663 1.121c-.285.36-.637.789-.637.789-2.099-.067-2.896-1.444-2.896-1.444 0-3.059 1.368-5.538 1.368-5.538 1.368-1.027 2.669-.998 2.669-.998l.095.114c-1.71.495-2.499 1.245-2.499 1.245s.21-.114.561-.275c1.016-.446 1.823-.57 2.156-.599.057-.009.105-.019.162-.019a7.756 7.756 0 0 1 4.778.893s-.751-.712-2.366-1.206l.133-.152s1.302-.029 2.669.998c0 0 1.368 2.479 1.368 5.538 0-.001-.807 1.376-2.907 1.443z" />
</svg>
            <span class="mx-2">Discord Server</span></a></li>


</ul>

</div>

            <br />

            <div class="bg-body-tertiary px-4 py-3">

    <h4 class="pt-0">Support this project!</h4>

    <ul class="list-unstyled">

        
        <li>
            <a class="text-reset text-decoration-none text-limit-line-1"
                href="https://buymeacoffee.com/damienfremont" target="_blank">
                <?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="currentColor" width="16" height="16" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
  <path 
    d="M822.592 192h14.272a32 32 0 0 1 31.616 26.752l21.312 128A32 32 0 0 1 858.24 384h-49.344l-39.04 546.304A32 32 0 0 1 737.92 960H285.824a32 32 0 0 1-32-29.696L214.912 384H165.76a32 32 0 0 1-31.552-37.248l21.312-128A32 32 0 0 1 187.136 192h14.016l-6.72-93.696A32 32 0 0 1 226.368 64h571.008a32 32 0 0 1 31.936 34.304L822.592 192zm-64.128 0 4.544-64H260.736l4.544 64h493.184zm-548.16 128H820.48l-10.688-64H214.208l-10.688 64h6.784zm68.736 64 36.544 512H708.16l36.544-512H279.04z" />
</svg>
                <span class="">buymeacoffee.com/damienfremont</span>
            </a>
        </li>
        

        

        
        <li>
            <a class="text-reset text-decoration-none text-limit-line-1"
                href="https://www.paypal.com/donate/?hosted_button_id=5WTGL666THA58" target="_blank">
                <?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="currentColor" width="16" height="16" viewBox="0 0 512 512" id="Layer_1" data-name="Layer 1"
    xmlns="http://www.w3.org/2000/svg">
    <path
        d="M424.81,148.79c-.43,2.76-.93,5.58-1.49,8.48-19.17,98-84.76,131.8-168.54,131.8H212.13a20.67,20.67,0,0,0-20.47,17.46L169.82,444.37l-6.18,39.07a10.86,10.86,0,0,0,9.07,12.42,10.72,10.72,0,0,0,1.7.13h75.65a18.18,18.18,0,0,0,18-15.27l.74-3.83,14.24-90,.91-4.94a18.16,18.16,0,0,1,18-15.3h11.31c73.3,0,130.67-29.62,147.44-115.32,7-35.8,3.38-65.69-15.16-86.72A72.27,72.27,0,0,0,424.81,148.79Z" />
    <path
        d="M385.52,51.09C363.84,26.52,324.71,16,274.63,16H129.25a20.75,20.75,0,0,0-20.54,17.48l-60.55,382a12.43,12.43,0,0,0,10.39,14.22,12.58,12.58,0,0,0,1.94.15h89.76l22.54-142.29-.7,4.46a20.67,20.67,0,0,1,20.47-17.46h42.65c83.77,0,149.36-33.86,168.54-131.8.57-2.9,1.05-5.72,1.49-8.48h0C410.94,98.06,405.19,73.41,385.52,51.09Z" />
</svg>
                <span class="">paypal.com/damienfremont</span>
            </a>
        </li>
        

        
        <li>
            <a class="text-reset text-decoration-none text-limit-line-1"
                href="https://damienfremont.itch.io/" target="_blank">
                <?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" aria-label="itch.io" role="img" width="18" height="18" viewBox="0 0 512 512">
    <rect  rx="15%" />
    <path
        d="M118 95c-16 10-49 47-49 56v16c0 21 19 38 36 38 21 0 38-17 38-37 0 20 17 37 38 37 20 0 36-17 36-37 0 20 18 37 39 37s39-17 39-37c0 20 16 37 36 37 21 0 38-17 38-37 0 20 17 37 38 37 17 0 36-17 36-38v-16c0-9-33-46-49-56a3511 3511 0 00-276 0zm99 101l-7 9a43 43 0 01-68-9l-7 9c-8 8-19 13-31 13l-4-1-2 46v18c0 36-4 118 16 138 30 7 86 10 142 10s112-3 142-10c20-20 16-102 16-138v-18l-2-46-4 1c-12 0-23-5-31-13l-7-9-7 9a43 43 0 01-68-9 43 43 0 01-38 22h-1-1a43 43 0 01-38-22zm-31 40c12 0 23 0 37 15l33-2 33 2c14-15 25-15 37-15 6 0 29 0 45 46l18 63c13 46-4 47-26 47-31-1-49-24-49-47a371 371 0 01-117 0c1 23-17 46-48 47-22 0-39-1-26-47l18-63c16-46 39-46 45-46zm70 36s-33 31-39 42l22-1v19h34v-19l22 1c-6-11-39-42-39-42z" />
</svg>
                <span class="">itchio.com/damienfremont</span>
            </a>
        </li>
        

        <!-- TODO: patreon.com/damienfremont -->
        <!-- TODO: ko-fi.com/damienfremont -->
        
    </ul>

</div>
        </div>
    </div>

</div>
</div>

home.html

<h2>Home</h2>
<p></p>

login.html

<!-- FROM https://github.com/sahat/satellizer/blob/master/examples/client/partials/login.html -->
 
<div class="panel panel-default col-md-4 col-md-offset-4">
  <div class="panel-body">
    <h4 class="text-center">
      <i class="glyphicon glyphicon-log-in"></i> Log in
    </h4>
 
    <form name="loginForm" ng-submit="emailLogin()" novalidate>
 
      <!-- LOGIN -->
      <div class="form-group has-feedback"
        ng-class="{ 'has-error': loginForm.email.$invalid && loginForm.email.$dirty }">
        <input server-error class="form-control input-lg" type="text"
          name="email" ng-model="email" placeholder="Email" required
          autofocus>
        <div class="help-block" ng-if="loginForm.email.$dirty"
          ng-messages="loginForm.email.$error">
          <div ng-message="required">Please enter your email</div>
          <div ng-message="server"></div>
        </div>
      </div>
 
      <!-- PASSWORD -->
      <div class="form-group has-feedback"
        ng-class="{ 'has-error': loginForm.password.$invalid && loginForm.password.$dirty }">
        <input server-error class="form-control input-lg"
          type="password" name="password" ng-model="password"
          placeholder="Password" required>
        <div class="help-block" ng-if="loginForm.password.$dirty"
          ng-messages="loginForm.password.$error">
          <div ng-message="required">Please enter your password</div>
          <div ng-message="server"></div>
        </div>
      </div>
 
      <!-- SUBMIT -->
      <button type="submit" class="btn btn-block btn-success"
        ng-disabled="loginForm.$invalid">Log in</button>
 
    </form>
  </div>
</div>

web.xml

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
     http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
 
  <servlet>
    <servlet-name>REST</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>javax.ws.rs.Application</param-name>
      <param-value>com.damienfremont.blog.MyAppCONFIG</param-value>
    </init-param>
    <init-param>
      <param-name>jersey.config.server.provider.classnames</param-name>
      <param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>REST</servlet-name>
    <url-pattern>/api/*</url-pattern>
  </servlet-mapping>
 
  <servlet>
    <servlet-name>WEBJARS</servlet-name>
    <servlet-class>org.webjars.servlet.WebjarsServlet</servlet-class>
    <init-param>
      <param-name>disableCache</param-name>
      <param-value>true</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>WEBJARS</servlet-name>
    <url-pattern>/webjars/*</url-pattern>
  </servlet-mapping>
 
</web-app>

Project

https://github.com/DamienFremont/damienfremont.com-blog-labs/tree/master/20151119-javaee-angularjs-bootstrap-auth_basic https://github.com/DamienFremont/damienfremont.com-blog-labs/tree/master/20151119-javaee-angularjs-bootstrap-auth_basic

References

https://github.com/sahat/satellizer https://github.com/sahat/satellizer

https://github.com/sahat/satellizer/tree/master/examples/client https://github.com/sahat/satellizer/tree/master/examples/client

https://github.com/sahat/satellizer/tree/master/examples/server/java https://github.com/sahat/satellizer/tree/master/examples/server/java

https://hackhands.com/building-instagram-clone-angularjs-satellizer-nodejs-mongodb/ https://hackhands.com/building-instagram-clone-angularjs-satellizer-nodejs-mongodb/

https://github.com/sahat/instagram-hackhands https://github.com/sahat/instagram-hackhands

Origin

https://damienfremont.com/2015/11/19/javaee-angularjs-bootstrap-how-to-authent-basic/