Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/openliberty/guide-rest-client-angular

A guide on how to access a simple RESTful web service and consume its resources with Angular in Open Liberty: https://openliberty.io/guides/rest-client-angular.html
https://github.com/openliberty/guide-rest-client-angular

Last synced: 3 months ago
JSON representation

A guide on how to access a simple RESTful web service and consume its resources with Angular in Open Liberty: https://openliberty.io/guides/rest-client-angular.html

Awesome Lists containing this project

README

        

// Copyright (c) 2019, 2023 IBM Corporation and others.
// Licensed under Creative Commons Attribution-NoDerivatives
// 4.0 International (CC BY-ND 4.0)
// https://creativecommons.org/licenses/by-nd/4.0/
//
// Contributors:
// IBM Corporation
:projectid: rest-client-angular
:page-layout: guide-multipane
:page-duration: 20 minutes
:page-description: Explore how to access a simple RESTful web service and consume its resources with Angular in Open Liberty.
:page-essential: false
:page-guide-catagory: none
:page-permalink: /guides/{projectid}
:page-releasedate: 2019-06-21
:page-related-guides: ['rest-intro', 'rest-client-java', 'rest-client-angularjs']
:page-seo-title: Consuming a RESTful Java web service with Angular
:page-seo-description: A getting started tutorial with examples on how to access a RESTful Java microservice and consume its resources using the Angular framework.
:common-includes: https://raw.githubusercontent.com/OpenLiberty/guides-common/prod
:source-highlighter: prettify
:guide-author: Open Liberty
= Consuming a RESTful web service with Angular

[.hidden]
NOTE: This repository contains the guide documentation source. To view the guide in published form, view it on the https://openliberty.io/guides/{projectid}.html[Open Liberty website].

Explore how to access a simple RESTful web service and consume its resources with Angular in OpenLiberty.

// =================================================================================================
// Introduction
// =================================================================================================

== What you'll learn

https://angular.io[Angular^] is a framework for creating interactive web applications. Angular applications are written in HTML, CSS, and https://www.typescriptlang.org[TypeScript^], a variant of JavaScript. Angular helps you create responsive and intuitive applications that download once and run as a single web page. Consuming REST services with your Angular application allows you to request only the data and operations that you need, minimizing loading times.

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 an Angular service and the Angular HTTP Client. You will then present this data using an Angular component.

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

The Angular application was created and configured for you in the `frontend` directory. It contains the default starter application. There are many files that make up an Angular application, but you only need to edit a few to consume the REST service and display its data.

Angular applications must be compiled before they can be used. The Angular compilation step was configured as part of the Maven build. You can use the `start` folder of this guide as a template for getting started with your own applications built on Angular and Open Liberty.

artists.json
[source, json, linenums, role="code_column"]
----
include::finish/src/resources/artists.json[]
----

// Static guide instruction
ifndef::cloud-hosted[]
You will implement an Angular client that consumes this JSON and displays its contents
at the `\http://localhost:9080/app` URL.
endif::[]

// Cloud hosted guide instruction
ifdef::cloud-hosted[]
You will implement an Angular client that consumes this JSON and displays its contents.
endif::[]

To learn more about REST services and how you can write them, see
https://openliberty.io/guides/rest-intro.html[Creating a RESTful web service^].

// =================================================================================================
// Getting Started
// =================================================================================================
[role='command']
include::{common-includes}/gitclone.adoc[]

[role='command']
include::{common-includes}/twyb-intro.adoc[]

// Static guide instruction
ifndef::cloud-hosted[]
Then, point your browser to the web application root http://localhost:9080/app[http://localhost:9080/app^] to see the following output:
endif::[]

// Cloud hosted guide instruction
ifdef::cloud-hosted[]
Click the following button to visit the web application ***/app*** root endpoint:
::startApplication{port="9080" display="external" name="Visit application" route="/app"}

You will see the following output:
endif::[]

[subs="quotes", role="no_copy"]
----
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:
----

[role='command']
include::{common-includes}/twyb-end.adoc[]

// =================================================================================================
// Starting the service
// =================================================================================================

== 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.

// cloud-hosted guide instructions:
ifdef::cloud-hosted[]
```bash
cd /home/project/guide-rest-client-angular/start
```
endif::[]

[role='command']
include::{common-includes}/devmode-lmp33-start.adoc[]

// Static guide instruction
ifndef::cloud-hosted[]
You can find your artist JSON at the http://localhost:9080/artists[http://localhost:9080/artists^] URL.
endif::[]

// Cloud hosted guide instruction
ifdef::cloud-hosted[]
You can find your artist JSON by running the following command at a terminal:
```bash
curl -s http://localhost:9080/artists | jq
```
endif::[]

// =================================================================================================
// Project configuration
// =================================================================================================

== Project configuration

The front end of your application uses Node.js to execute your Angular code. The Maven project is configured for you to install Node.js and produce the production files, which are copied to the web content of your application.

Node.js is server-side JavaScript runtime that is used for developing networking applications. Its convenient package manager, https://www.npmjs.com/[npm^], is used to execute the Angular scripts found in the `package.json` file. To learn more about Node.js, see the official https://nodejs.org/en/docs/[Node.js documentation^].

The [hotspot=frontend-plugin]`frontend-maven-plugin` is used to [hotspot=node-resource-install]`install` the dependencies listed in your `package.json` file from the npm registry into a folder called `node_modules`. The `node_modules` folder is found in your [hotspot=working-dir]`working` directory. Then, the configuration [hotspot=node-resource-build]`produces` the production files to the `src/main/frontend/src/app` directory.

The `src/main/frontend/src/angular.json` file is defined so that the production build is copied into the web content of your application.

pom.xml
[source, xml, linenums, role='code_column']
----
include::finish/pom.xml[]
----

// =================================================================================================
// Creating the root Angular module
// =================================================================================================

== Creating the root Angular module

Your application needs a way to communicate with and retrieve resources from RESTful web services. In this case, the provided Angular application needs to communicate with the artists service to retrieve the artists JSON. While there are various ways to perform this task, Angular contains a built-in `HttpClientModule` that you can use.

Angular applications consist of modules, which are groups of classes that perform specific functions. The Angular framework provides its own modules for applications to use. One of these modules, the HTTP Client module, includes convenience classes that make it easier and quicker for you to consume a RESTful API from your application.

You will create the module that organizes your application, which is called the root module. The root module includes the Angular HTTP Client module.

[role="code_command hotspot", subs="quotes"]
----
#Create the `app.module.ts` file.#
`src/main/frontend/src/app/app.module.ts`
----

app.module.ts
[source, javascript, linenums, role="code_column"]
----
include::finish/src/main/frontend/src/app/app.module.ts[]
----

The [hotspot=importHttpClientModule]`HttpClientModule` imports the class into the file. By using the [hotspot=atNgModule]`@NgModule` tag, you can declare a module and organize your dependencies within the Angular framework. The `imports` array is a declaration array that imports the [hotspot=httpClientModule]`HttpClientModule` so that you can use the HTTP Client module in your application.

// =================================================================================================
// Creating the Angular component to fetch data
// =================================================================================================

== Creating the Angular service to fetch data

You need to create the component that is used in the application to acquire and display data from the REST API. The component file contains two classes: the service, which handles data access, and the component itself, which handles the presentation of the data.

Services are classes in Angular that are designed to share their functionality across entire applications. A good service performs only one function, and it performs this function well. In this case, the `ArtistsService` class requests artists data from the REST service.

[role="code_command hotspot", subs="quotes"]
----
#Create the `app.component.ts` file.#
`src/main/frontend/src/app/app.component.ts`
----

app.component.ts
[source, javascript, linenums, role="code_column hide_tags=providersProperty,importOnInitAndAngularCorePackage"]
----
include::finish/src/main/frontend/src/app/app.component.ts[]
----

The file imports the [hotspot=importHttpClient]`HttpClient` class and the [hotspot=importInjectable]`Injectable` decorator.

The [hotspot=artistsServiceClass]`ArtistsService` class is defined. While it shares the file of the component class [hotspot=appComponentClass]`AppComponent`, it can also be defined in its own file. The class is annotated by [hotspot=atInjectable]`@Injectable` so instances of it can be provided to other classes anywhere in the application.

The class injects an instance of the [hotspot=httpClientInstance]`HttpClient` class, which it uses to request data from the REST API. It contains the [hotspot=artistsUrl]`ARTISTS_URL` constant, which points to the API endpoint it requests data from. The URL does not contain a host name because the artists API endpoint is accessible from the same host as the Angular application. You can send requests to external APIs by specifying the full URL. Finally, it implements a [hotspot=fetchArtistsMethod]`fetchArtists()` method that makes the request and returns the result.

To obtain the data for display on the page, the [hotspot=fetchArtistsMethod]`fetchArtists()` method tries to use the injected [hotspot=httpInstanceAndAwaitFeatureAndHttpGetAndToPromise]`http` instance to perform a `GET` HTTP request to the [hotspot=artistsUrl]`ARTISTS_URL` constant. If successful, it returns the result. If an error occurs, it prints the error message to the console.

The [hotspot=fetchArtistsMethod]`fetchArtists()` method uses a feature of JavaScript called [hotspot=asyncFeature]`async`, [hotspot=httpInstanceAndAwaitFeatureAndHttpGetAndToPromise]`await` to make requests and receive responses without preventing the application from working while it waits. For the result of the [hotspot=httpInstanceAndAwaitFeatureAndHttpGetAndToPromise]`HttpClient.get()` method to be compatible with this feature, it must be converted to a Promise by invoking its [hotspot=httpInstanceAndAwaitFeatureAndHttpGetAndToPromise]`toPromise()` method. APromise is how JavaScript represents the state of an asynchronous operation. If you want to learn more, check out https://promisejs.org[promisejs.org^] for an introduction.

// =================================================================================================
// Defining the component to consume the service
// =================================================================================================

== Defining the component to consume the service

Components are the basic building blocks of Angular application user interfaces. Components are made up of a TypeScript class annotated with the [hotspot=atComponent]`@Component` annotation and the HTML template file (specified by [hotspot=templateUrl]`templateUrl`) and CSS style files (specified by [hotspot=styleUrls]`styleUrls`.)

Update the [hotspot=appComponentClass]`AppComponent` class to use the artists service to fetch the artists data and save it so the component can display it.

[role="code_command hotspot", subs="quotes"]
----
#Update the `app.component.ts` file.#
`src/main/frontend/src/app/app.component.ts`
----

app.component.ts
[source, javascript, linenums, role="code_column"]
----
include::finish/src/main/frontend/src/app/app.component.ts[]
----

[role="edit_command_text"]
Replace the entire [hotspot=appComponentClass]`AppComponent` class along with the [hotspot=atComponent]`@Component` annotation. Add [hotspot=importOnInitAndAngularCorePackage]`OnInit` to the list of imported classes at the top.

The [hotspot=providersProperty]`providers` property on the [hotspot=atComponent]`@Component` annotation indicates that this component provides the [hotspot=artistsServiceClass]`ArtistsService` to other classes in the application.

[hotspot=appComponentClass]`AppComponent` implements [hotspot=onInitInterface]`OnInit`, which is a special interface called a lifecycle hook. When Angular displays, updates, or removes a component, it calls a specific function, the lifecycle hook, on the component so the component can run code in response to this event. This component responds to the [hotspot=onInitInterface]`OnInit` event via the [hotspot=ngOnInitMethod]`ngOnInit` method, which fetches and populates the component's template with data when it is initialized for display. The file imports the [hotspot=importOnInitAndAngularCorePackage]`OnInit` interface from the [hotspot=importOnInitAndAngularCorePackage]`@angular/core` package.

[hotspot=artistsClassMember]`artists` is a class member of type `any[]` that starts out as an empty array. It holds the artists retrieved from the service so the template can display them.

An instance of the [hotspot=artistsServiceInstanceDeclaration]`ArtistsService` class is injected into the constructor and is accessible by any function that is defined in the class. The [hotspot=ngOnInitMethod]`ngOnInit` function uses the [hotspot=artistsServiceInstance]`artistsService` instance to request the artists data. The [hotspot=fetchArtistsMethod]`fetchArtists()` method is an `async` function so it returns a Promise. To retrieve the data from the request, [hotspot=ngOnInitMethod]`ngOnInit` calls the [hotspot=thenClause]`then()` method on the Promise which takes in the data and stores it to the [hotspot=artistsClassMember]`artists` class member.

// =================================================================================================
// Creating the Angular component template
// =================================================================================================

== Creating the Angular component template

Now that you have a service to fetch the data and a component to store it in, you will create a template to specify how the data will be displayed on the page. When you visit the page in the browser, the component populates the template to display the artists data with formatting.

[role="code_command hotspot", subs="quotes"]
----
#Create the `app.component.html` file.#
`src/main/frontend/src/app/app.component.html`
----

app.component.html
[source, html, linenums, role="code_column"]
----
include::finish/src/main/frontend/src/app/app.component.html[]
----

The template contains a [hotspot=artistsDiv]`div` element that is enumerated by using the `ngFor` directive. The `artist` variable is bound to the `artists` member of the component. The [hotspot=artistsDiv]`div` element itself and all elements contained within it are repeated for each artist, and the [hotspot=artistNameAndAlbumsLengthPlaceholders]`{{ artist.name }}` and [hotspot=artistNameAndAlbumsLengthPlaceholders]`{{ artist.albums.length }}` placeholders are populated with the information from each artist. The same strategy is used to display each [hotspot=albumDiv]`album` by each artist.

// =================================================================================================
// Building the front end
// =================================================================================================

== Building the front end

The Open Liberty instance is already started, and the REST service is running. In a new command-line session, build the front end by running the following command in the `start` directory:

// Static guide instruction
ifndef::cloud-hosted[]
[role='command']
```
mvn generate-resources
```
endif::[]
// Cloud hosted guide instruction
ifdef::cloud-hosted[]
```bash
cd /home/project/guide-rest-client-angular/start
mvn generate-resources
```
endif::[]

The build might take a few minutes to complete. You can rebuild the front end at any time with the `generate-resources` Maven goal. Any local changes to your TypeScript or HTML are picked up when you build the front end.

// Static guide instruction
ifndef::cloud-hosted[]
Point your browser to the http://localhost:9080/app[http://localhost:9080/app^] web application root to see the following output:
endif::[]

// Cloud hosted guide instruction
ifdef::cloud-hosted[]
Click the following button to visit the web application ***/app*** root endpoint:
::startApplication{port="9080" display="external" name="Visit application" route="/app"}

You will see the following output:
endif::[]

[subs="quotes", role="no_copy"]
----
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:
----

If you use the `curl` command to access the web application root URL, you see only the application root page in HTML. The Angular framework uses JavaScript to render the HTML to display the application data. A web browser runs JavaScript, and the `curl` command doesn't.

== Testing the Angular client

No explicit code directly uses the consumed artist JSON, so you don't need to write any test cases.

// Static guide instruction
ifndef::cloud-hosted[]
Whenever you change and build your Angular implementation, the application root at http://localhost:9080/app[http://localhost:9080/app^] reflects the changes automatically.
endif::[]

// Cloud hosted guide instruction
ifdef::cloud-hosted[]
Whenever you change and build your Angular implementation, the changes are automatically reflected at the URL for the launched application.
endif::[]

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.

Although the Angular application that this guide shows you how to build is simple, when you build more complex Angular 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 https://angular.io/guide/testing[official Angular page^].

== Great work! You're done!

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

include::{common-includes}/attribution.adoc[subs="attributes"]