Consuming a RESTful web service with AngularJS

duration 20 minutes

Prerequisites:

Explore how to access a simple RESTful web service and consume its resources with AngularJS in Open Liberty.

What you’ll learn

You will learn how to access a REST service and deserialize the returned JSON that contains a list of artists and their albums by using the high-level $resource service of AngularJS.

The REST service that provides the artists and albums resource was written for you in advance and responds with the artists.json.

artists.json

 1[
 2    {
 3        "name": "foo",
 4        "albums": [
 5            {
 6                "title": "album_one",
 7                "artist": "foo",
 8                "ntracks": 12
 9            },
10            {
11                "title": "album_two",
12                "artist": "foo",
13                "ntracks": 15
14            }
15        ]
16    }, 
17    {
18        "name": "bar",
19        "albums": [
20            {
21                "title": "foo walks into a bar",
22                "artist": "bar",
23                "ntracks": 12
24            }
25        ]
26    }, 
27    {
28        "name": "dj",
29        "albums": [
30        ]
31    }
32]

You will implement an AngularJS client that consumes this JSON and displays its contents at the following URL: http://localhost:9080.

To learn more about REST services and how you can write them, see Creating a RESTful web service.

Getting started

The fastest way to work through this guide is to clone the Git repository and use the projects that are provided inside:

git clone https://github.com/openliberty/guide-rest-client-angularjs.git
cd guide-rest-client-angularjs

The start directory contains the starting project that you will build upon.

The finish directory contains the finished project that you will build.

Before you begin, make sure you have all the necessary prerequisites.

Try what you’ll build

The finish directory in the root of this guide contains the finished application. Give it a try before you proceed.

To try out the application, first go to the finish directory and run the following Maven goal to build the application and deploy it to Open Liberty:

cd finish
mvn liberty:run

After you see the following message, your Liberty instance is ready:

The defaultServer server is ready to run a smarter planet.

Navigate your browser to the application root http://localhost:9080 to see the following output:

foo wrote 2 albums:
    Album titled album_one by foo contains 12 tracks
    Album tilted album_two by foo contains 15 tracks
bar wrote 1 albums:
    Album titled foo walks into a bar by bar contains 12 tracks
dj wrote 0 albums:

After you are finished checking out the application, stop the Liberty instance by pressing CTRL+C in the command-line session where you ran Liberty. Alternatively, you can run the liberty:stop goal from the finish directory in another shell session:

mvn liberty:stop

Starting the service

Before you begin the implementation, start the provided REST service so that the artist JSON is available to you.

Navigate to the start directory to begin.

When you run Open Liberty in dev mode, dev mode listens for file changes and automatically recompiles and deploys your updates whenever you save a new change. Run the following goal to start Open Liberty in dev mode:

mvn liberty:dev

After you see the following message, your Liberty instance is ready in dev mode:

**************************************************************
*    Liberty is running in dev mode.

Dev mode holds your command-line session to listen for file changes. Open another command-line session to continue, or open the project in your editor.

After the Liberty instance is started, you can find your artist JSON at the following URL: http://localhost:9080/artists.

Any local changes to your JavaScript and HTML are picked up automatically, so you don’t need to restart the Liberty instance.

Creating the AngularJS controller

Begin by registering your application module. Every application must contain at least one module, the application module, which will be bootstrapped to launch the application.

Create the consume-rest file.
src/main/webapp/js/consume-rest.js

consume-rest.js

 1// tag::consumeRestApp[]
 2var app = angular.module('consumeRestApp', ['ngResource']);
 3// end::consumeRestApp[]
 4
 5// tag::Artists[]
 6// tag::resource-module[]
 7app.factory("artists", function($resource) {
 8// end::resource-module[]
 9    // tag::resource-call[]
10    return $resource("http://localhost:9080/artists");
11    // end::resource-call[]
12});
13// end::Artists[]
14
15// tag::Controller[]
16app.controller("ArtistsCtrl", function($scope, artists) {
17    artists.query(function(data) {
18        // tag::Scope[]
19        $scope.artists = data;
20        // end::Scope[]
21    }, function(err) {
22        console.error("Error occured: ", err);
23    });
24});
25// end::Controller[]

The application module is defined by consumeRestApp.

Your application will need some way of communicating with RESTful web services in order to retrieve their resources. In the case of this guide, your application will need to communicate with the artists service to retrieve the artists JSON. While there exists a variety of ways of doing this, you can use the fairly straightforward AngularJS $resource service.

The ngResource module is registered as it is appended after consumeRestApp. By registering another module, you are performing a dependency injection, exposing all functionalities of that module to your main application module.

Next, the Artists AngularJS service is defined by using the Factory recipe. The Factory recipe constructs a new service instance with the return value of a passed in function. In this case, the $resource module that you imported earlier is the passed in function. Target the artist JSON URL in the $resource() call.

The controller controls the flow of data in your application.Each controller is instantiated with its own isolated scope, accessible through the $scope parameter. All data that is bound to this parameter is available in the view to which the controller is attached.

You can now access the artists property from the template at the point in the Document Object Model (DOM) where the controller is registered.

Creating the AngularJS template

You will create the starting point of your application. This file will contain all elements and attributes specific to AngularJS.

Create the starting point of your application.
src/main/webapp/index.html

index.html

 1<!-- tag::copyright[] -->
 2<!--
 3  Copyright (c) 2016,2023 IBM Corp.
 4 
 5  Licensed under the Apache License, Version 2.0 (the "License");
 6  you may not use this file except in compliance with the License.
 7  You may obtain a copy of the License at
 8 
 9     http://www.apache.org/licenses/LICENSE-2.0
10 
11  Unless required by applicable law or agreed to in writing, software
12  distributed under the License is distributed on an "AS IS" BASIS,
13  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  See the License for the specific language governing permissions and
15  limitations under the License.
16-->
17<!-- end::copyright[] -->
18<!-- tag::html[] -->
19<!DOCTYPE html>
20<html>
21    <!-- tag::head[] -->
22    <head>
23        <!-- tag::AngularJS[] -->
24        <!-- tag::angular-script[] -->
25        <script 
26            src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.js">
27        </script>
28        <!-- end::angular-script[] -->
29        <!-- tag::angular-resource-script[] -->
30        <script 
31           src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular-resource.js">
32        </script>
33        <!-- end::angular-resource-script[] -->
34        <!-- end::AngularJS[] -->
35        <!-- tag::consume-rest[] -->
36        <script src="./js/consume-rest.js"></script>
37        <!-- end::consume-rest[] -->
38    </head>
39    <!-- end::head[] -->
40    <!-- tag::body[] -->
41    <!-- tag::consumeRestApp[] -->
42    <body ng-app="consumeRestApp">
43    <!-- end::consumeRestApp[] -->
44        <!-- tag::controller[] -->
45        <!-- tag::ArtistCtrl[] -->
46        <div ng-controller="ArtistsCtrl">
47        <!-- end::ArtistCtrl[] -->
48            <!-- tag::repeat[] -->
49            <!-- tag::Artists[]-->
50            <div ng-repeat="artist in artists">
51            <!-- end::Artists[] -->
52                <!-- tag::artist-info[] -->
53                <p>{{ artist.name }} wrote {{ artist.albums.length }} albums:</p>
54                <!-- end::artist-info[] -->
55                <div ng-repeat="album in artist.albums">
56                    <p style="text-indent: 20px">
57                        Album titled <b>{{ album.title }}</b> by 
58                                     <b>{{ album.artist }}</b> contains 
59                                     <b>{{ album.ntracks }}</b> tracks
60                    </p>
61                </div>
62            </div>
63            <!-- end::repeat[] -->
64        </div>
65        <!-- end::controller[] -->
66    </body>
67    <!-- end::body[] -->
68</html>
69<!-- end::html[] -->

consume-rest.js

 1// tag::consumeRestApp[]
 2var app = angular.module('consumeRestApp', ['ngResource']);
 3// end::consumeRestApp[]
 4
 5// tag::Artists[]
 6// tag::resource-module[]
 7app.factory("artists", function($resource) {
 8// end::resource-module[]
 9    // tag::resource-call[]
10    return $resource("http://localhost:9080/artists");
11    // end::resource-call[]
12});
13// end::Artists[]
14
15// tag::Controller[]
16app.controller("ArtistsCtrl", function($scope, artists) {
17    artists.query(function(data) {
18        // tag::Scope[]
19        $scope.artists = data;
20        // end::Scope[]
21    }, function(err) {
22        console.error("Error occured: ", err);
23    });
24});
25// end::Controller[]

Before your application is bootstrapped, you must pull in two AngularJS libraries and import consume-rest.js.

The first import is the base AngularJS library, which defines the angular.js script in your HTML. The second import is the library responsible for providing the APIs for the $resource service, which also defines the angular-resource.js script in your HTML. The application is bootstrapped because the consumeRestApp application module is attached to the body of the template.

Next, the ArtistCtrl controller is attached to the DOM to create a new child scope. The controller will make the artists property of the $scope object available to access at the point in the DOM where the controller is attached.

Once the controller is attached, the artists property can be data-bounded to the template and accessed using the {{ artists }} expression. You can use the ng-repeat directive to iterate over the contents of the artists property.

After everything is set up, point your browser to the application root http://localhost:9080 to see the following output:

foo wrote 2 albums:
    Album titled album_one by foo contains 12 tracks
    Album tilted album_two by foo contains 15 tracks
bar wrote 1 albums:
    Album titled foo walks into a bar by bar contains 12 tracks
dj wrote 0 albums:

Testing the AngularJS client

No explicit code directly uses the consumed artist JSON, so you do not need to write any test cases for this guide.

Whenever you change your AngularJS implementation, the application root at http://localhost:9080 will reflect the changes automatically. You can visit the root to manually check whether the artist JSON was consumed correctly.

When you are done checking the application root, exit dev mode by pressing CTRL+C in the command-line session where you ran the Liberty.

When you develop your own applications, testing becomes a crucial part of your development lifecycle. If you need to write test cases, follow the official unit testing and end-to-end testing documentation on the official AngularJS website.

Great work! You’re done!

You have just accessed a simple RESTful web service and consumed its resources by using AngularJS in Open Liberty.

Guide Attribution

Consuming a RESTful web service with AngularJS by Open Liberty is licensed under CC BY-ND 4.0

Copy file contents
Copied to clipboard

Prerequisites:

Nice work! Where to next?

What did you think of this guide?

Extreme Dislike Dislike Like Extreme Like

What could make this guide better?

Raise an issue to share feedback

Create a pull request to contribute to this guide

Need help?

Ask a question on Stack Overflow

Like Open Liberty? Star our repo on GitHub.

Star