Download as pdf or txt
Download as pdf or txt
You are on page 1of 17

10/11/21, 1:50 PM Angular Tutorial: Angular 7 and the RESTEasy Framework - DZone Web Dev

(/)  (/users/login.html)
 (/search)
REFCARDZ
(/refcardz)
RESEARCH
(/research)
WEBINARS
(/webinars)
ZONES

DZone (/)
>
Web Dev Zone (/web-development-programming-tutorials-tools-news)
>
Angular Tutorial: Angular 7
and the RESTEasy Framework

Angular Tutorial: Angular 7 and the


RESTEasy Framework

(/users/3546231/nagappan08.html) by

Nagappan Subramanian (/users/3546231/nagappan08.html)


 CORE
·
Jun. 12, 19
·
Web Dev Zone
(/web-development-programming-tutorials-tools-news)
·
Tutorial


Like
(11)

Comment
(0)

Save


Tweet

[New Research] 2021 Application Security Trend Report:


Discover how the shift in security focus across the SDLC is
impacting dev teams — from addressing the most common threat
agents to exploring the best practices and tools being employed to
develop secure applications. Check it out >>

Developers who want to quickly build web applications with flexible front-end and
backend frameworks can work with multiple tech stacks like MEAN, LAMP, and so on.

One such web application development stack is Angular 7 and RESTEasy. The advantage
of having Angular 7 as a framework is that it can be used to develop apps for any kind of
device, faster using pre-built templates. Likewise, RESTEasy can be used as your backend
framework to provide the REST API services which are light weight and portable to any
kind of container.

In this article, we'll show you how to build a product catalog which displays a list of
products that the user can search through, edit, delete, or create products in a page.

https://dzone.com/articles/angular-7-resteasy-framework-application-step-wise 1/17
10/11/21, 1:50 PM Angular Tutorial: Angular 7 and the RESTEasy Framework - DZone Web Dev


(/)  (/users/login.html)
 (/search)

REFCARDZ
(/refcardz)
RESEARCH
(/research)
WEBINARS
(/webinars)
ZONES

Angular 7 will be used on the front-end for the product catalog and RESTEasy will be
used for the backend application. We'll also show how to build both the front- and
backend, then integrate the two different framework seamlessly to work as complete
web application.

Front-End Web Development


Angular 7 is a framework which can be used to build applications for web, desktop, and
mobile devices. As of now, LTS will have support for Angular 7 up to April 18, 2020. It is
licensed under the MIT license.

TypeScript is the language used for programming the behaviors, services, etc.

Angular 7 Setup
Node and npm has to be installed. Then the angular-cli command prompt will be
installed.

1 npm install -g @angular/cli

To learn more of the detailed steps, please refer to the Angular site
(https://angular.io/guide/setup-local). Once installed, it can be verified by the
command  ng -version .

Generate a Basic App Template


An Angular 7 basic template app can be created with the below command:

1 ng new angular-tour-of-heroes

When we enter the command it asks for routing — say no. We'll be using CSS for styling,
so just enter and then the app will be created. Now go into tge application folder and
check tgat the application works by giving the  ng serve -o  command to show the
application. Use the below command to generate a product component.

1 ng generate component heroes

Now let's modify the application to show product catalog. Change the title inside the
src/index.html file to something like "Product Inventory Management."

In the app.componen.ts file, change the title to "Product Catalog."


https://dzone.com/articles/angular-7-resteasy-framework-application-step-wise 2/17
10/11/21, 1:50 PM Angular Tutorial: Angular 7 and the RESTEasy Framework - DZone Web Dev
In the app.componen.ts file, change the title to Product Catalog.

(/)  (/users/login.html)
In the generated component file (files are app*, product/*),  (/search)
change all the instances of

"heroes" to "products."
REFCARDZ
(/refcardz)
RESEARCH
(/research)
WEBINARS
(/webinars)
ZONES

The Angular application first starts with the main.ts file, where the Boostrap module is
provided, which is the app module. In turn, the app module invokes the app component.
That app component renders the view with the following HTML. The title value provided
by the app component will hold the string literal which gets display here.

It has been marked with the  app-products  directive, which will be a special directive
decorated as a component, i.e. a product component.

1 <!--The content below is only a placeholder and can be replaced.-->


2 <div style="text-align:center">
3 <h1>
4 {{ title }}!
5 </h1>
6 <app-products></app-products>
7 </div>

Display the Product Catalog


Now let's create the product cards. Inside the product folder, code up the product card as
an HTML template. Now the div with the catalog is the outer layout, then the outer frame
with div card block is provided. If the user has not selected any products, then
the  selectedProduct  variable will not be present, so the  card-body  has been applied
with all the details and a whole block is iterable for each product in the product list. The
reference of the product is passed for all the events.

All the events will be binded with  (event)="functionname" . These function are defined
in the component.

1 <div class="catalog">
2 <div class="card cardsize clickable" *ngFor="let product of products" (click)="onSelect(pr
3 ....
4 <div *ngIf="selectedProduct!=product" class="card-body">
5 <h2 class="card-title">{{product.name | titlecase}}<button class="delete" (click)="
6 <p class="card-subtitle">Product Details</p>
7 <p class="card-text"><span class="propertyname">Id:</span>{{product.id}}</p>
8 <p class="card-text"><span class="propertyname">Qty:</span>{{product.qty}}</p>
9 <p class="card-text"><span class="propertyname">Brand:</span>{{product.brand}}</p>
10 <p class="card-text"><span class="propertyname">Desc:</span>{{product.desc}}</p>
11 </div>
12 </div>
13 </div>

The component which is backed by the HTML template for model data binding has to be
coded like below. The component is a logical view of the whole web page which consits of
an HTML template with TypeScript modules (to learn more about the components that 3/17
https://dzone.com/articles/angular-7-resteasy-framework-application-step-wise
10/11/21, 1:50 PM Angular Tutorial: Angular 7 and the RESTEasy Framework - DZone Web Dev
an HTML template with TypeScript modules (to learn more about the components that
are available, go to
(/)  (/users/login.html)
 (/search)
the Angular site (https://angular.io/guide/architecture-
components)).
REFCARDZ
(/refcardz)
RESEARCH
(/research)
WEBINARS
(/webinars)
ZONES

1 import { Component, OnInit } from '@angular/core';
2 import { Product } from '../product';
3 import { PRODUCTS } from '../mock-products';
4 import { ProductService } from '../product.service';
5 import { Logger } from '../logger.service';
6
7
8 @Component({
9 selector: 'app-products',
10 templateUrl: './products.component.html',
11 styleUrls: ['./products.component.css']
12 })
13 export class ProductsComponent implements OnInit {
14
15 products = PRODUCTS;//takes the mock products and display the products for view.
16
17 selectedProduct: Product;//On click of the card, it takes that product to selectedProduct var
18
19 constructor(private productService: ProductService, private logger: Logger) {
20 this.selectedProduct = null;
21 }

The product component has been injected with the product service and logger service.
The product component class has the member products that have been iterated in the
HTML template ngFor.

1 export class Product {


2 id: number;
3 name: string;
4 qty: number;
5 brand: string;
6 desc: string;
7 }

It is assigned to  PRODUCTS , which is an initialized global mock constant.

1 import {Product} from './product';


2
3 export var PRODUCTS: Product[] = [
4 {id: 11, name: 'Inspiron Laptop', qty: 3, brand: 'Dell', desc: 'It is a 14 inch wide screen
5 {id: 12, name: 'Power X ', qty: 5, brand: 'LG', desc: 'It has 2300mAH battery and free mobi
6 {id: 13, name: 'Keyboard', qty: 7, brand: 'TVS Gold Keyboard', desc: 'Its of standard size.
7 ];

Upon initializing the component, it invokes the  getProducts  method of the component,
which invokes the product service. This in turn invokes the RESTEasy API to get the
information.

1 ngOnInit() {
2 this getProducts();
https://dzone.com/articles/angular-7-resteasy-framework-application-step-wise 4/17
10/11/21, 1:50 PM Angular Tutorial: Angular 7 and the RESTEasy Framework - DZone Web Dev
2 this.getProducts();
3
4
}

(/) 
(/users/login.html)
 (/search)
5 getProducts(): void {
REFCARDZ
(/refcardz)
6
RESEARCH
(/research)
WEBINARS
(/webinars)
ZONES

this.productService.getProducts().
7 subscribe((response: any) => {
8 this.products = [];
9 response.map((productelem)=>{
10 this.products.push(productelem.product);
11 });
12 console.log(this.products);
13 });
14 }

The product service which will invoke the REST API with a basic authorization header
will get the observable and return that to the component. The 'on subscribe' component
gets the response, maps the product object, and pushes this to the products model of the
component.

1 import { Injectable } from '@angular/core';


2 import { Product } from './product';
3 import { PRODUCTS } from './mock-products';
4 import { Logger } from './logger.service';
5 import { HttpClient } from '@angular/common/http';
6 import { HttpHeaders } from '@angular/common/http';
7 import { Observable } from 'rxjs';
8
9 const HTTPOPTIONS = {
10 headers: new HttpHeaders({
11 'Authorization': 'Basic YWRtaW46YWRtaW4=',
12 })
13 };
14
15 @Injectable({
16 providedIn: 'root',
17 })
18 export class ProductService {
19
20 constructor(private logger: Logger, private httpclient: HttpClient) { }
21 getProducts(): Observable<any> {
22 this.logger.log("message is getting logged successfully");
23 return this.httpclient.get("http://localhost:8080/resteasyexamples/rest/products", HTTP
24 }

We will explain what we do to produce the output from RESTEasy examples later.

Selecting a Card
If the card has been clicked, it opens up for edit, by setting the  selectedProduct  variable
(which is the piece of code in dotted spaces). It opens up the form for all the fields.

1 <div *ngIf="selectedProduct==product">
2 <h2 class="card-title">Create/Edit Product<button class="delete" (click)="onDelete(product)">
3 <form (ngSubmit)="onSubmit(product)">
4 <label>Name:</label><input [(ngModel)]="selectedProduct.name" name="productName" placeholde
5 <br/>
https://dzone.com/articles/angular-7-resteasy-framework-application-step-wise 5/17
10/11/21, 1:50 PM Angular Tutorial: Angular 7 and the RESTEasy Framework - DZone Web Dev
5 <br/>
6 <div style="width: 7rem;">
7

(/) 
(/users/login.html)
<label>Qty:</label><input [(ngModel)]="selectedProduct.qty"

 style="width:
name="productQty" (/search)
8 </div>
REFCARDZ
(/refcardz)
RESEARCH
(/research)
9 <label>Brand:</label><input
WEBINARS
(/webinars)
ZONES

[(ngModel)]="selectedProduct.brand" 
name="productBrand" placeholder
10 <br/>
11 <label>Desc:</label><input [(ngModel)]="selectedProduct.desc" name="productDesc" placeholde
12 <input style="float:right; width: 5rem;" type="submit" value="Save" />
13 </form>
14 </div>

The card will be the edit mode if the model variable  selctedProduct  holds a reference
to the product. This is done by the product component upon selection of the card. It
invokes  onSelect , which takes the clicked product card and maps it to
the  selectedProduct . Once the user enters the values as required, the submit button
triggers the  onSubmit  method, which takes the modified product detail values and
passes them to the product service.

1 //when click on product card, the selectedProduct is cached by the class member.
2 onSelect(product: Product) : void {
3 console.log("product selected");
4 this.selectedProduct = product;
5 }
6
7
8 //as the product is double binded, when edit or add product is done, it automatically applies
9 onSubmit(product: Product) {
10 console.log(product);
11 this.productService.createOrEditProduct(product).subscribe((response:any)=>{
12 product.id = response;
13 });
14 this.selectedProduct = null;
15 }

In the product service, it will invoke the REST API by passing the product model and
product id (i.e. it invokes the PUT method). Upon successfully updating the product, this
code returns the modified id. This modified id will be set back to the product model id
field. So, via two way data-binding, those values appears on the screen.

1 createOrEditProduct(product): Observable<any> {
2 if (product.id==0) {
3 return this.httpclient.post("http://localhost:8080/resteasyexamples/rest/products", {"produ
4 } else {
5 return this.httpclient.put("http://localhost:8080/resteasyexamples/rest/products/"+prod
6 }
7 }

Add Product
In the UI, there is top div block which contains the Add Product button. This click event
will create a new card in the edit mode, i.e. a card will be opened up with the product
f th t th d t il
https://dzone.com/articles/angular-7-resteasy-framework-application-step-wise 6/17
10/11/21, 1:50 PM Angular Tutorial: Angular 7 and the RESTEasy Framework - DZone Web Dev
form so the user can enter the details.

1 <div>

(/)  (/users/login.html)
 (/search)
2 <input [(ngModel)]="searchText" placeholder="product name"/>
REFCARDZ
(/refcardz)
RESEARCH
(/research)
WEBINARS
(/webinars)
ZONES

3 <button class="btn btn-primary" type="button" (click)="onSearch(searchText)">Search Product
4 <button class="btn btn-primary" type="button" (click)="onAdd(product)">Add Product</button>
5 </div>

This will invoke the  onAdd  method of the component which creates a new instance of the
product model and the id will not be set (the id will be assigned only by the backend
REST service at the time of submission). The newly created product will also be assigned
to the   selectedProduct  reference, so upon submit it will be taken care of.

1 //while clicking on add product, the product entity created with available id and pushed to p
2 onAdd(product: Product): void {
3 console.log("product added");
4 product = {id: 0, name: '', qty: 0, brand: '', desc: ''};
5 this.selectedProduct = product;
6 this.products.push(product);
7 }

When the user submits the form in the product card, it goes to the onSubmit  of the
product component which internally calls the product REST API's POST method. The
backend REST API will create a product and return the newly assigned product id to the
front-end.

Delete Product
In each card, at top-right corner, there is a delete icon to delete the card. When the user
clicks it, the  onDelete  method of the product component will be invoked. It will remove
the product from the product list.

1 //while delete is clicked, the product will be removed from the products modal.
2 onDelete(product: Product) : void {
3 this.products = this.products.filter(p1 => p1!=product);
4 this.productService.deleteProduct(product.id);
5 }

This, in turn, invokes the delete method of product service to call the REST API'S DELETE
service. This will delete the product and return a successful message.

The product list which is presisted is always cached in the front-end product component
in  this.products . Now, the search has been done from the UI itself. The user enters the
product name partially or completely, then clicking the search button will invoke the
following method.

1 //while searching, the product name search field value given will be searched in each product
2 onSearch(searchText: string) : void {
3 alert(searchText);
4 thi d t thi d t filt ( 1 > 1 i d Of( hT t)> 0)
https://dzone.com/articles/angular-7-resteasy-framework-application-step-wise 7/17
10/11/21, 1:50 PM Angular Tutorial: Angular 7 and the RESTEasy Framework - DZone Web Dev
4 this.products = this.products.filter(p1 => p1.name.indexOf(searchText)>=0);
5 }

(/)  (/users/login.html)
 (/search)
REFCARDZ
(/refcardz)
RESEARCH
(/research)
Styling is done for the
WEBINARS
(/webinars)
whole Angular 7 application file in

ZONES

in the styles.css the project root


path. The styles specific to the product component are manged in the product
component folder. Both the file stylings are listed below.

Some key things to be noted in the CSS stylings are that the cards are of the same size and
more cards wrap into the next line. This is caused by defining the   .catalog  class
with  "display:flex; flex-wrap: wrap" . So, irrespective of the content inside the
product card, it all comes out to be the same size.

./styles.css

1 /* You can add global styles to this file, and also import other style files */
2 /* Application-wide Styles */
3 h1 {
4 color: #369;
5 font-family: Arial, Helvetica, sans-serif;
6 font-size: 250%;
7 }
8 h2, h3 {
9 color: #444;
10 font-family: Arial, Helvetica, sans-serif;
11 font-weight: lighter;
12 border-bottom: 1px solid #ddd;
13 }
14 body {
15 margin: 2em;
16 }
17 body, input[type="text"], button {
18 color: #888;
19 font-family: Cambria, Georgia;
20 }
21 .catalog {
22 display: flex;
23 flex-wrap: wrap;
24 padding: 5px;
25 }
26 .card {
27 border: 1px solid #ddd !important;
28 padding: 0px;
29 display: inline-block;
30 margin: 5px;
31 }
32 .cardsize {
33 width: 17rem;
34 }
35 .card-title {
36 background: #369;
37 color: white;
38 margin: 0px;
39 padding:5px;
40 text-align: left;
41 }
42 .card-subtitle {
https://dzone.com/articles/angular-7-resteasy-framework-application-step-wise 8/17
10/11/21, 1:50 PM Angular Tutorial: Angular 7 and the RESTEasy Framework - DZone Web Dev
43 text-align: left;
44
45
padding-left:
(/)
5px;
font-size: 18px;
(/users/login.html)
  (/search)
46 font-weight: bold;
REFCARDZ
(/refcardz)
RESEARCH
(/research)
WEBINARS
(/webinars)
ZONES

47 }
48 .card-text {
49 text-align: left;
50 padding-left: 5px;
51 font-size: 14px;
52 }
53 .propertyname {
54 font-weight: bold;
55 }
56 /* everywhere else */
57 * {
58 font-family: Arial, Helvetica, sans-serif;
59 }

src/app/products/product.component.css

1 .clickable {
2 cursor: pointer;
3 }
4 .delete {
5 float: right;
6 color: #369;
7 font-weight: bold;
8 cursor: pointer;
9 }
10 label {
11 display: inline-block;
12 padding-bottom: 5px;
13 width: 3rem;
14 text-align:right;
15 }
16 input {
17 width: 13rem;
18 display: inline-block;
19 }

The logger service has also been injected to the component. That logger service gets the
message and prints it in the console. This has been decoupled as service, so logging-
related logic can be directly applied to the logger service, which impacts the complete
application.

1 import { Injectable } from '@angular/core';


2
3 @Injectable({
4 providedIn: 'root'
5 })
6 export class Logger{
7 logs: string[] = [];
8
9 log(message: string) {
10 this.logs.push(message);
11 console.log(message);
}
https://dzone.com/articles/angular-7-resteasy-framework-application-step-wise 9/17
10/11/21, 1:50 PM Angular Tutorial: Angular 7 and the RESTEasy Framework - DZone Web Dev
12 }
13 }
(/)  (/users/login.html)
 (/search)

REFCARDZ
(/refcardz)
RESEARCH
(/research)
WEBINARS
(/webinars)
ZONES

Front-end Angular 7 application code sample can be reference from the GitHub link.
(https://github.com/nagappan080810/angular7projects/tree/master/angular-
product-catalog)

Backend RESTEasy API Service


RESTEasy is a simple way to build REST APIs that are portable to any containers. We
have used RESTEasy 3.7.0 and has deployed it to Tomcat 8.

Now, create a web application project from the Maven web application template and then
add the following dependency for the RESTEasy framework in pom.xml:

1 <properties>
2 <maven.compiler.source>1.8</maven.compiler.source>
3 <maven.compiler.target>1.8</maven.compiler.target>
4 <resteasyversion>3.7.0.Final</resteasyversion>
5 <tomcat.version>8.5.35</tomcat.version>
6 </properties>
7 <dependencies>
8 <dependency>
9 <groupId>org.jboss.resteasy</groupId>
10 <artifactId>resteasy-jaxrs</artifactId>
11 <version>${resteasyversion}</version>
12 </dependency>
13 <dependency>
14 <groupId>org.jboss.resteasy</groupId>
15 <artifactId>resteasy-servlet-initializer</artifactId>
16 <version>${resteasyversion}</version>
17 </dependency>
18 <dependency>
19 <groupId>org.jboss.resteasy</groupId>
20 <artifactId>resteasy-cache-core</artifactId>
21 <version>${resteasyversion}</version>
22 </dependency>
23 <dependency>
24 <groupId>org.jboss.resteasy</groupId>
25 <artifactId>resteasy-multipart-provider</artifactId>
26 <version>${resteasyversion}</version>
27 </dependency>
28 <dependency>
29 <groupId>org.jboss.resteasy</groupId>
30 <artifactId>resteasy-jettison-provider</artifactId>
31 <version>${resteasyversion}</version>
32 </dependency>
33 <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
34 <dependency>
35 <groupId>commons-io</groupId>
36 <artifactId>commons-io</artifactId>
37 <version>2.6</version>
38 </dependency>

The product entity will be created as shown below, which is similar to the front-end.
https://dzone.com/articles/angular-7-resteasy-framework-application-step-wise 10/17
p
10/11/21, 1:50 PM
y ,
Angular Tutorial: Angular 7 and the RESTEasy Framework - DZone Web Dev

1 @XmlRootElement
(/) (/users/login.html)

 (/search)
2 @XmlAccessorType(XmlAccessType.FIELD)
3 public class Product
REFCARDZ
(/refcardz) {

RESEARCH
(/research)
WEBINARS
(/webinars)
ZONES

4 @XmlElement
5 private Integer id;
6 private String name;
7 private Integer qty;
8 private String brand;
9 private String desc;
10 @XmlTransient
11 private Date modifiedDate;
12
13 public Product() {
14 this.modifiedDate = new Date();
15 }
16
17 public Product(Integer id, String name, Integer availableQty, String brand, String desc) {
18 this.id = id;
19 this.name = name;
20 this.qty = availableQty;
21 this.brand = brand;
22 this.desc = desc;
23 this.modifiedDate = new Date();
24 }
25
26 public Product(Integer id, Product product) {
27 this.id = id;
28 this.name = product.getName();
29 this.qty = product.getQty();
30 this.brand = product.getBrand();
31 this.modifiedDate = new Date();
32 }
33
34 public Integer getId() {
35 return id;
36 }
37
38 public void setId(Integer id) {
39 this.id = id;
40 }
41
42 public String getName() {
43 return name;
44 }
45
46 public void setName(String name) {
47 this.name = name;
48 }
49
50 public int getQty() {
51 return qty;
52 }
53
54 public void setQty(Integer qty) {
55 this.qty = qty;
56 }
57
58 public String getBrand() {
59 return brand;
https://dzone.com/articles/angular-7-resteasy-framework-application-step-wise 11/17
10/11/21, 1:50 PM Angular Tutorial: Angular 7 and the RESTEasy Framework - DZone Web Dev

60 }
61
(/) (/users/login.html)
  (/search)
62 public void setBrand(String brand) {
63 this.brand
REFCARDZ
(/refcardz) = brand;

RESEARCH
(/research)
WEBINARS
(/webinars)
ZONES

64 }
65
66 public Date getModifiedDate() {
67 return modifiedDate;
68 }
69
70 public void setModifiedDate(Date modifiedDate) {
71 this.modifiedDate = modifiedDate;
72 }
73 }

This is a simple product JAX-RS REST API service to create a product, get all products,
update a product. and delete a product. All the product lists have been maintained in the
in-memory inventory  field. It returns the entity and the RESTEasy framework will
convert the entity and response and returns the appropriate status code.

1 @Path("products")
2 public class ProductService {
3 private static Map<Integer, Product> inventory = new HashMap<>();
4 static {
5 inventory.put(1, new Product(1, "Inspiron Laptop", 5, "Dell", "Laptop will be robust an
6 inventory.put(2, new Product(2, "Power X", 3, "LG", "Very good battery with 2300mah and
7 inventory.put(3, new Product(3, "Thumbdrive", 3, "Kingston", "Trustable thumbdrive whic
8 }
9 private static int maxProductId = 4;
10
11 Logger logger = Logger.getLogger(ProductService.class);
12
13 @POST
14 @Path("/")
15 @Consumes("application/json")
16 @Produces("application/text")
17 public String createProduct(Product productDetails) {
18 Product newproduct = new Product(maxProductId++, productDetails);
19 inventory.put(newproduct.getId(), newproduct);
20 return newproduct.getId().toString();
21 }
22
23
24 @GET
25 @Path("/")
26 //@PermitAll
27 @Produces("application/json")
28 public Collection<Product> getProducts() {
29 System.out.println("getproducts");
30 return inventory.values();
31 }
32
33 @GET
34 @Path("/{id}")
35 @Produces("application/json")
36 public Product getProduct(@PathParam("id") Integer id) {
37 return inventory.get(id);
38 }
https://dzone.com/articles/angular-7-resteasy-framework-application-step-wise 12/17
10/11/21, 1:50 PM Angular Tutorial: Angular 7 and the RESTEasy Framework - DZone Web Dev
38 }
39
40 @DELETE

(/) 
(/users/login.html)
 (/search)
41 @Path("/{id}")
REFCARDZ
(/refcardz)
42
RESEARCH
(/research)
WEBINARS
(/webinars)
ZONES

@Produces("application/text")
43 public String deleteProduct(@PathParam("id") Integer id) {
44 inventory.remove(id);
45 return "product deleted successfully";
46 }
47
48 @PUT
49 @Path("/{id}")
50 @Consumes("application/json")
51 @Produces("application/text")
52 public String updateProduct(@PathParam("id") Integer id, Product productDetails) {
53 inventory.remove(id);
54 Product updatedproduct = new Product(maxProductId++, productDetails);
55 inventory.put(updatedproduct.getId(), updatedproduct);
56 return updatedproduct.getId().toString();
57 }
58
59
60 }

All the REST API methods will be intialized by the standalone servlet intializer. This has
been done by extending the basic JAX-RS application class.

1 import javax.ws.rs.ApplicationPath;
2 import javax.ws.rs.core.Application;
3
4 @ApplicationPath("/rest")
5 public class ApplicationMain extends Application {
6
7 }

Basic Authentication
All the REST API resource methods are protected by basic authentication that has been
intialized in the front-end as HTTP options.

1 const HTTPOPTIONS = {
2 headers: new HttpHeaders({
3 'Authorization': 'Basic YWRtaW46YWRtaW4=',
4 })
5 };

This security has been provided by  SecurityFilter , which


implents  ContainerRequestFilter .

All the methods before invocation take the header authorization key value and decode it
for credentials. This then validates the credentials and, if successful, invokes the REST
API methods. Otherwise, it returns with a failed exception.

https://dzone.com/articles/angular-7-resteasy-framework-application-step-wise 13/17
10/11/21, 1:50 PM Angular Tutorial: Angular 7 and the RESTEasy Framework - DZone Web Dev

1 @Provider
2 @Priority(2000)
(/) 
(/users/login.html)

3 public class SecurityFilter implements ContainerRequestFilter {


 (/search)
4 private static final ServerResponse ACCESS_FORBIDDEN = new ServerResponse("NOBODY CAN ACCES
REFCARDZ
(/refcardz)
RESEARCH
(/research)
WEBINARS
(/webinars)
ZONES

5 private static final ServerResponse ACCESS_DENIED = new ServerResponse("Authorization heade
6 private static final ServerResponse INTERNAL_SERVER_ERROR = new ServerResponse("Authorizati
7 private static final String AUTHORIZATION_PROPERTY = "Authorization";
8 @Override
9 public void filter(ContainerRequestContext containerRequestContext) throws IOException {
10 ResourceMethodInvoker methodInvoker = (ResourceMethodInvoker)
11 containerRequestContext.getProperty("org.jboss.resteasy.core.ResourceMethodInvoker"
12 Method method = methodInvoker.getMethod();
13 if (!method.isAnnotationPresent(PermitAll.class)) {
14 if (method.isAnnotationPresent(DenyAll.class)) {
15 containerRequestContext.abortWith(ACCESS_FORBIDDEN);
16 return;
17 }
18 final MultivaluedMap<String, String> headers = containerRequestContext.getHeaders()
19 final List<String> authorization = headers.get(AUTHORIZATION_PROPERTY);
20
21 if(authorization==null || authorization.isEmpty()) {
22 containerRequestContext.abortWith(ACCESS_DENIED);
23 return;
24 }
25 String credentials = null;
26 try{
27 credentials = new String(Base64.decode(authorization.get(0).replaceFirst("Basic
28 } catch(Exception exception) {
29 containerRequestContext.abortWith(INTERNAL_SERVER_ERROR);
30 return;
31 }
32 final StringTokenizer credentialsParser = new StringTokenizer(credentials, ":");
33 String username = credentialsParser.nextToken();
34 String password = credentialsParser.nextToken();
35 if (username.equals("admin") && password.equals("admin")) {
36 System.out.println("!!!Authenticated Successfully!!!");
37 //skip authorization check as roles not mentioned.
38 if (method.getAnnotation(RolesAllowed.class)==null) {
39 return;
40 }
41 String[] rolesAllowed = method.getAnnotation(RolesAllowed.class).value();
42 boolean isAllowed = false;
43 for(String role: rolesAllowed) {
44 if (role.equals("admin")) {
45 System.out.println("!!Authorized successfully!!");
46 isAllowed = true;
47 break;
48 }
49 }
50 if (!isAllowed) {
51 containerRequestContext.abortWith(ACCESS_DENIED);
52 return;
53 }
54 } else {
55 containerRequestContext.abortWith(ACCESS_DENIED);
56 return;
57 }
58 }
59 }
60 }
https://dzone.com/articles/angular-7-resteasy-framework-application-step-wise 14/17
10/11/21, 1:50 PM Angular Tutorial: Angular 7 and the RESTEasy Framework - DZone Web Dev


(/)  (/users/login.html)
 (/search)
CORS Handler
REFCARDZ
(/refcardz)
RESEARCH
(/research)
WEBINARS
(/webinars)
ZONES

Angular 7 runs on port 4200, whereas RESTEasy has a different origin, so the REST API
calls may break due to your browser's CORS policy. So, to handle the cross-origin request,
we need to add an Angular domain to the  allowOrigin  in the CORS filter.

1 @Provider
2 @Priority(4000)
3 public class CustomCorsFilter extends CorsFilter {
4
5 public CustomCorsFilter() {
6 this.getAllowedOrigins().add("http://localhost:4200");
7 }
8
9 }

When there is cross-origin request, the browser sends a pre-flight request ( OPTIONS ) to
the backend. Upon successfully getting a response from the backend, it sends the actual
GET, POST, or any other calls to the REST API services. So  CORSAllowFilter  has been
created as shown below and annotated with  @Provider  so that it will be autoscanned by
the  StandaloneServletInitializer . It also sends allow headers so the basic
authentication can be sent in the actual method. It also passed the list of methods
possible for the REST resource's URL.

1 @Provider
2 @Priority(3000)
3 public class CorsAllowFilter implements ContainerResponseFilter {
4 @Override
5 public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContex
6 if (containerResponseContext.getHeaders().containsKey("Access-Control-Allow-Origin")==f
7 containerResponseContext.getHeaders().add("Access-Control-Allow-Origin", "http://lo
8 }
9 containerResponseContext.getHeaders().add(
10 "Access-Control-Allow-Credentials", "true");
11 containerResponseContext.getHeaders().add(
12 "Access-Control-Allow-Headers",
13 "origin, content-type, accept, authorization");
14 containerResponseContext.getHeaders().add(
15 "Access-Control-Allow-Methods",
16 "GET, POST, PUT, DELETE, OPTIONS, HEAD");
17 }
18 }

Backend RESTEasy example can be referenced from the GitHub link


(https://github.com/nagappan080810/resteasy_workbook).

https://dzone.com/articles/angular-7-resteasy-framework-application-step-wise 15/17
10/11/21, 1:50 PM Angular Tutorial: Angular 7 and the RESTEasy Framework - DZone Web Dev


(/)  (/users/login.html)
 (/search)

REFCARDZ
(/refcardz)
RESEARCH
(/research)
WEBINARS
(/webinars)
ZONES

Topics:
RESTEASY,
ANGULAR 7,
ANGULAR TUTORIAL,
WEB DEV,
FULL-STACK APPLICATION DEVELOPMENT

Opinions expressed by DZone contributors are their own.

Popular on DZone
Monitoring Web Servers Should Never Be Complex (/articles/monitoring-web-servers-
should-never-be-complex?fromrel=true)

My Funny Habit: Code Review for Solo Projects (/articles/my-funny-habit-code-review-


for-solo-projects?fromrel=true)

How to Get All Employees Using Spring Boot Layered Architecture and JdbcTemplate
(/articles/how-to-get-all-employees-using-spring-boot-layered-1?fromrel=true)

How to Mock a Web Server in Your Java Applications (/articles/how-to-mock-a-web-


server-using-wiremock-in-your-ja?fromrel=true)

Web Dev Partner Resources


Salesforce Application Design
Get an overview of how to design applications to run on
the Salesforce Platform, exploring the no- to-full code
spectrum. Download the Refcard ►

Presented by Skuid

Getting Started With IaC


Infrastructure as code (IaC) means that you use code to
define and manage infrastructure rather than using
manual processes. Explore now ►

Presented by Pulumi

NoSQL Migration Essentials


Walk through the primary steps for moving from a SQL
to NoSQL database — plus design principles to help
guide your migration. Get started ►

Presented by Couchbase

Monday.com helps teams work more efficiently to


execute projects that deliver results on time. Try for Free

Presented by Monday.com

https://dzone.com/articles/angular-7-resteasy-framework-application-step-wise 16/17
10/11/21, 1:50 PM Angular Tutorial: Angular 7 and the RESTEasy Framework - DZone Web Dev

ABOUT US
(/)  (/users/login.html)
 (/search)
About DZone (/pages/about)

RESEARCH
(/research)
WEBINARS
(/webinars)
ZONES

Send feedback (mailto:support@dzone.com)
REFCARDZ
(/refcardz)
Careers (https://devada.com/careers/)
Sitemap (/sitemap)

ADVERTISE
Advertise with DZone (/pages/advertise)
+1 (919) 238-7100 (tel:+19192387100)

CONTRIBUTE ON DZONE
Article Submission Guidelines (/articles/dzones-article-submission-guidelines)
MVB Program (/pages/mvb)
Become a Contributor (/pages/contribute)
Visit the Writers' Zone (/writers-zone)

LEGAL
Terms of Service (/pages/tos)
Privacy Policy (/pages/privacy)

CONTACT US
600 Park Offices Drive
Suite 300
Durham, NC 27709
support@dzone.com (mailto:support@dzone.com)
+1 (919) 678-0300 (tel:+19196780300)

Let's be friends:    
(/pages/feeds)

(https://twitter.com/DZoneInc)

(https://www.facebook.com/DZoneInc)

(https://www.linkedin.com/company/dzone/)

DZone.com is powered by 



(https://devada.com/answerhub/)

https://dzone.com/articles/angular-7-resteasy-framework-application-step-wise 17/17

You might also like