Tuesday, June 30, 2020

Executor And ExecutorService in Java With Examples

This post gives an overview of Java Executors framework which comprises-

  1. Executor interfaces- Executor, ExecutorService and ScheduledExecutorService interfaces which define the three executor object types.
  2. Thread pools- Executor implementation classes like ThreadPoolExecutor and ScheduledThreadPoolExecutor which use thread pools.
  3. Fork/Join- A framework (from JDK 7) for taking advantage of multiple processors.

Thread management through executors in Java

In large-scale applications, its good to separate thread management and creation from the rest of the application. The concurrent API in Java has a feature called executors that provides an alternative to managing threads through the Thread class.

Executor interface in Java

At the core of the Java executors framework is the Executor interface, which also has two sub interfaces ExecutorService and ScheduledExecutorService.

An object of type Executor can execute runnable tasks. An Executor is normally used instead of explicitly creating threads. For example If r is a Runnable object, and e is an Executor object you can replace

(new Thread(r)).start();
with
e.execute(r);

Methods in Java Executor interface

The Executor interface in Java provides a single method execute().

void execute(Runnable command)- Executes the given command at some time in the future. The command may execute in a new thread, in a pooled thread, or in the calling thread, at the discretion of the Executor implementation.

Java ExecutorService interface

ExecutorService interface in Java extends Executor interface and provides methods to manage termination (through shutdown() method) and methods that can produce a Future (using submit() with a Callable) for tracking progress of one or more asynchronous tasks.

ExecutorService interface has more versatile submit method. Like execute, submit accepts Runnable objects, but also accepts Callable objects, which allows the task to return a value. The submit method returns a Future object, which is used to retrieve the Callable return value and to manage the status of both Callable and Runnable tasks.

ExecutorService Implementing classes

In the Java concurrency there are three pre defined executor classes that implement the Executor and ExecutorService interfaces.

  1. ThreadPoolExecutor- Implements the Executor and ExecutorService interfaces and executes the submitted task using one of the pooled thread.
  2. ScheduledThreadPoolExecutor- It extends ThreadPoolExecutor and also implements the ScheduledExecutorService interface. This class schedule commands to run after a given delay, or to execute periodically.
  3. ForkJoinPool implements the Executor and ExecutorService interfaces and is used by the Fork/Join Framework.

Before writing any examples for Executor or ExecutorService, two things are worth knowing Executors class and ThreadPools.

ThreadPools in Java

In a large scale application if each task uses its own thread then allocating and deallocating many thread objects creates a significant memory management overhead.

Thread pool as the name suggests provides a set of threads, any task which has to be executed get a thread from this pool.

Executors class in Java

Executors class provides factory and utility methods for Executors framework classes like Executor, ExecutorService, ScheduledExecutorService, ThreadFactory, and Callable.

Though you can use ThreadPoolExecutor and ScheduledThreadPoolExecutor directly, but the best way to get an executor is to use one of the static factory methods provided by the Executors utility class.

Some of the factory methods provided by Java Executors class are-

  1. static ExecutorService newCachedThreadPool()- Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available.
  2. static ExecutorService newFixedThreadPool(int numThreads)- Creates a thread pool that reuses a fixed number of threads.
  3. static ScheduledExecutorService newScheduledThreadPool(int numThreads)- Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically.
  4. newSingleThreadExecutor()- Creates an Executor that uses a single worker thread operating off an unbounded queue.

Java ExecutorService Examples

As already mentioned apart from execute() method, ExecutorService also has submit() method which is overloaded to take either Runnable or Callable as parameter. So let's see examples for these methods.

Using execute method

In this ExecutorService example a thread pool of two threads is created, and 6 runnable tasks are executed using execute() method. These 6 tasks will be executed using only these 2 threads from the thread pool, new thread won't be created for each of the 6 tasks. It can be verified from the thread name in the output.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorDemo {
 public static void main(String args[]) {
  // creating executor with pool of 2 threads
  ExecutorService ex = Executors.newFixedThreadPool(2);
  // running 6 tasks
  ex.execute(new Task());
  ex.execute(new Task());
  ex.execute(new Task());
  ex.execute(new Task());
  ex.execute(new Task());
  ex.execute(new Task());
  //shutting down the executor service
  ex.shutdown();
 }
}
 
/**
 *
 */
class Task implements Runnable{
 @Override
 public void run() {
  System.out.println("in run task for thread - " + Thread.currentThread().getName());
  // Introducing some delay for switching
  try {
   Thread.sleep(500);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}

Output

in run task for thread - pool-1-thread-2
in run task for thread - pool-1-thread-1
in run task for thread - pool-1-thread-1
in run task for thread - pool-1-thread-2
in run task for thread - pool-1-thread-2
in run task for thread - pool-1-thread-1

Submit with Runnable parameter example

In this ExecutorService Java example submit method is used to submit a runnable task for execution which returns a Future representing that task. The Future's get() method will return null upon successful completion of a runnable task.

In the example 2 runnable tasks are submitted which return future objects, in case of Runnable, Future's get method will return null.

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ExecutorServiceDemo {
 public static void main(String args[]) {
  // creating executor with pool of 2 threads
  ExecutorService ex = Executors.newFixedThreadPool(2);
  // running tasks
  Future f1 = ex.submit(new Task());
  Future f2 = ex.submit(new Task());
  try {
   // getting the future value
   System.out.println("Future f1 " + f1.get());
   System.out.println("Future f1 " + f1.get());
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (ExecutionException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  ex.shutdown();
 }
}

/**
 * Runnable 
 */
class Task implements Runnable{

 @Override
 public void run(){
  System.out.println("in run task for thread - " + Thread.currentThread().getName());
  // Introducing some delay for switching
  try {
   Thread.sleep(500);
  } catch (InterruptedException e) {
   e.printStackTrace();  
  }
 }
}

Output

in run task for thread - pool-1-thread-2
in run task for thread - pool-1-thread-1
Future f1 null
Future f1 null

Submit with Callable as parameter example

In this ExecutorService Java example callable task is submitted using submit() method.

Callable interface has call method which can return value too, so in this case when Future's get method is called it'll return a value. Note that here callable is implemented as a lambda expression.

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ExecutorServiceDemo {
  public static void main(String args[]) {
    // creating executor with pool of 2 threads
    ExecutorService ex = Executors.newFixedThreadPool(2);
    // Callable implemented as lambda
    Callable<String> c = ()->"Callable lambda is called";
    // running tasks with callable as param
    Future f1 = ex.submit(c);
    try {
      // getting the future value
      System.out.println("Future f1 " + f1.get());
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    ex.shutdown();      
  }
}

Output

Future f1 Callable lambda is called

ExecutorService shutdown

An ExecutorService can be shut down, which will cause it to reject new tasks. Two different methods are provided for shutting down an ExecutorService. The shutdown() method will allow previously submitted tasks to execute before terminating, while the shutdownNow() method prevents waiting tasks from starting and attempts to stop currently executing tasks. Upon termination, an executor has no tasks actively executing, no tasks awaiting execution, and no new tasks can be submitted. An unused ExecutorService should be shut down to allow reclamation of its resources.

ScheduledExecutorService interface in Java

ScheduledExecutorService extends ExecutorService and provides methods that can schedule commands to run after a given delay, or to execute periodically.

It has methods that execute a Runnable or Callable task after a specified delay.

  • schedule(Callable<V> callable, long delay, TimeUnit unit) - Creates and executes a ScheduledFuture that becomes enabled after the given delay.
  • schedule(Runnable command, long delay, TimeUnit unit) - Creates and executes a one-shot action that becomes enabled after the given delay.

In addition, the interface defines scheduleAtFixedRate and scheduleWithFixedDelay, which executes specified tasks repeatedly, at defined intervals.

  • scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) - Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given period; that is executions will commence after initialDelay then initialDelay+period, then initialDelay + 2 * period, and so on.
  • scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) - Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given delay between the termination of one execution and the commencement of the next.

ScheduledThreadPoolExecutor Java Example code

In this ScheduledExecutorService Java example callable task is submitted using schedule method which will be executed after a delay of 2 Sec.

import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class STEDemo {
  public static void main(String[] args) {
    ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(2);
    // Callable implemented as lambda
    Callable<String> c = ()->{
      System.out.println("Time of execution- " + new Date());
      return "Callable lambda is called";
    };
    System.out.println("Time before execution- " + new Date());
    // scheduling tasks with callable as param
    // it will execute after a delay of 2 Secs
    ScheduledFuture<String> sf = scheduledExecutor.schedule(c, 2, TimeUnit.SECONDS); 
    try {
      System.out.println("Value- " + sf.get());
    } catch (InterruptedException | ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    scheduledExecutor.shutdown();
  }
}

Output

Time before execution- Wed Nov 21 11:37:15 IST 2018
Time of execution- Wed Nov 21 11:37:17 IST 2018
Value- Callable lambda is called

That's all for this topic Executor And ExecutorService in Java With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Callable And Future in Java Concurrency
  2. Java ArrayBlockingQueue With Examples
  3. CopyOnWriteArrayList in Java With Examples
  4. Java CyclicBarrier With Examples
  5. Java Concurrency Interview Questions And Answers

You may also like-

  1. How to Iterate a HashMap of ArrayLists of String in Java
  2. How to sort HashSet in Java
  3. Difference Between Comparable and Comparator in Java
  4. Difference Between Checked And Unchecked Exceptions in Java
  5. static Reference to The Non-static Method or Field Error
  6. Race condition in Java multi-threading
  7. Interface Default Methods in Java
  8. Java ThreadLocal Class With Examples

Wednesday, June 10, 2020

Angular - Call One Service From Another

In the Service in Angular With Examples post we saw how Components in Angular should only concentrate on view-related functionality. Any application logic like fetching data through server calls, user input validation, logging to console should be delegated to a service in Angular. It doesn’t mean that all the application logic for a component has to go in a single service, you can create separate services for different functionalities and then call one service from another in Angular application. In this post we’ll see how to call one service from another in Angular.

Angular Service that needs another service

A service in Angular may have a dependency on another service for example you may have a DataService to get data from backend, SecurityService to secure your app, LoggerService to log to log file and these classes may have interdependency.

You don’t have to do much to configure dependency between services. A service that needs another service should have a @Injectable decorator and then you can apply the same constructor injection pattern where you provide the service dependency with in the constructor.

For example if there is a UserService that needs LoggerService for logging purpose can define the dependency in its constructor as shown below-

@Injectable({
  providedIn: 'root',
})
export class UserService {
  constructor(private loggerService: LoggerService){}
  ..
  ..
}

Call one service from another Angular example

Let’s create a full example to see how to configure dependency for another service. We’ll revisit the example Angular @Input and @Output Example that way we can also show how using service classes reduce the complexity in your application by making the communication among several components easy. You don’ have to relay that much on providing custom property binding through @Input and providing custom event binding through @Output. Service class can act like a centralized class which facilitate communication among Angular components.

In the example user names are displayed and clicking any of these names displays the user details.

Initially user names are displayed.

call one service from another

On clicking name, details are displayed.

Angular service dependency on another service

user.model.ts class

First thing is to define the User class with fields Name, Age, JoinDate.

export class User {
  name : string;
  age : number;
  joinDate : Date;
  constructor(name: string, age : number, joinDate : Date) {
    this.name = name;
    this.age = age;
    this.joinDate  = joinDate;
  }
}

user.component.html

Template for displaying user names.

<div class="row">
  <div class="col-xs-12 col-md-8 px-3">
    <p style="cursor:pointer" 
      class="list-group-item" 
      (click)="onClickUser()">
      {{user.name}}
    </p>
  </div>
</div>

UserComponent class

import { Component, OnInit, Input } from '@angular/core';
import { User } from './user.model';
import { UserService } from '../services/user.service';

@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit {
  @Input() user: User;
  @Input() index: Number;
  constructor(private userService: UserService){}
  ngOnInit(): void {
  }
  onClickUser(){
    this.userService.indexClicked.emit(this.index);
  }
}

As you can see in UserComponent there is an input property binding for user which means it will get user data from another component. In the onClickUser() method it emits the index of the clicked user.

AppComponent class

That’s where user data is fetched from the service and passed on to the UserComponent to display user names.

import { Component, OnInit } from '@angular/core';
import { User } from './user/user.model';
import { UserService } from './services/user.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'], 
})
export class AppComponent implements OnInit{
  users: User[] = [];
  constructor(private userService: UserService){}
  ngOnInit(){
    // get all the users
    this.users = this.userService.users;
  }
}

app.component.html

<div class="container">
  <div class="row">
    <div class="col-md-5">
      <div class="list-group">
        <app-user *ngFor="let u of users; let i = index" [user]="u" [index]="i"></app-user>
      </div>
    </div>
    <div class="col-md-7">
      <appuser-detail></appuser-detail>
    </div>
  </div>
</div>

As you can see in *ngFor directive user array iteration is done and each user is assigned to the [user] property and index is also assigned to the [index] property binding.

UserService class

import { User } from '../user/user.model';
import { EventEmitter, Injectable } from '@angular/core';
import { LoggerService } from './logger.service';

@Injectable({
  providedIn: 'root',
})
export class UserService {
  // dependency on Logger Service
  constructor(private loggerService: LoggerService){}
  // User detail array
  users = [new User('Jack', 62, new Date('2005-03-25')),
  new User('Olivia', 26, new Date('2014-05-09')),
  new User('Manish', 34, new Date('2010-10-21'))] ;
  
  indexClicked = new EventEmitter<Number>();

  getUserDetails(id: Number){
    this.loggerService.log("getting user data for ID- " + id);
    return this.users[id.valueOf()];
  }
}

This is the class that has users stored in the array. There is a property indexClicked of type EventEmitter that emits a number. In the UserComponent class index of the selected user is emitted using this property. Method getUserDetails() returns user instance from the array for the passed index.

UserService has a dependency on LoggerService which is specified in the constructor. In the getUserDetails() method loggerService is used to log a message.

LoggerService class

Though it is better to use @Injectable decorator with provider for LoggerService too, just to show another way of providing service, provider for this service is registered in AppModule.

export class LoggerService {

  constructor() { }
  log(msg: string) { 
    console.log(msg); 
  }
  error(msg: string) { 
    console.error(msg); 
  }
}

AppModule class

@NgModule({
  declarations: [
    AppComponent,
    UserComponent, 
    UserDetailComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [LoggerService],
  bootstrap: [AppComponent]
})
export class AppModule { }

UserDetailComponent class

This component has the property bindings for showing user details for the selected user.

import { Component, OnInit } from '@angular/core';
import { UserService } from '../services/user.service';
import { User } from './user.model';

@Component({
    selector: 'appuser-detail',
    templateUrl: './userdetail.component.html'
  })
export class UserDetailComponent implements OnInit{
  id: Number;
  user: User;
  constructor(private userService: UserService){
    this.userService.indexClicked.subscribe(
      (index: Number) => {
        this.id = index;
        console.log(this.id);
        this.user = this.userService.getUserDetails(this.id);
      }
    )
  }
  ngOnInit() {
    //this.user = this.userService.getUserDetails(this.id);
  }
}

In the UserService there is a property indexClicked that emits event. In this component we subscribe to that property and get the index. Using that index userService.getUserDetails() method is called by passing the index as argument.

userdetail.component.html

<div *ngIf="user">
  <div class="jumbotron">
    <h2>User Details</h2>
    <div class="row">
      <div class="col-xs-5 px-3">
        <label>Name: </label> {{ user.name }}      
      </div>
      <div class="col-xs-4 px-3">
        <label>Age: </label> {{ user.age }}
      </div>
      <div class="col-xs-4 px-3">
        <label>Joining Date: </label> {{ user.joinDate | date:'dd/MM/yyyy'}}
      </div>
    </div>
  </div>
</div>

Here *ngIf directive is used to show the details only when there is user data to be displayed.

That's all for this topic Angular - Call One Service From Another. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Angular Tutorial Page


Related Topics

  1. Injector Hierarchy and Service Instances in Angular
  2. Angular Routing Concepts With Example
  3. Angular Disable Button Example
  4. Angular ngStyle Directive With Examples
  5. Angular Two-Way Data Binding With Examples

You may also like-

  1. Angular Attribute Binding With Examples
  2. Angular Application Bootstrap Process
  3. Nested Route (Child Route) in Angular
  4. Highlight Currently Selected Menu Item Angular Routing Example
  5. CopyOnWriteArrayList in Java
  6. Literals in Java
  7. List in Python With Examples
  8. Spring Transaction Management JDBC Example Using @Transactional Annotation

Tuesday, June 9, 2020

Injector Hierarchy and Service Instances in Angular

In the Service in Angular With Examples post we saw an example of creating service where provider metadata was provided with in the @Injectable() decorator.

@Injectable({
 providedIn: 'root',
})

But that is not the only way to register a provider in Angular, there is a complete injector hierarchy and the number of service instances created depends on how you register the provider.


Providing services at different levels

For any service you are going to use in your Angular app you must register at least one provider. The provider can be part of the service's own metadata, making that service available everywhere, or you can register providers with specific modules or components. There are the following three ways for registering a provider for the service.

1. In the @Injectable() decorator for the service itself. By default, the Angular CLI command ng generate service registers a provider with the root injector for your service by including provider metadata in the @Injectable() decorator.

@Injectable({
 providedIn: 'root',
})

When you provide the service at the root level, Angular creates a single, shared instance of the Service and injects it into any class that asks for it. As per Angular docs Using the @Injectable() providedIn property is preferable to the @NgModule() providers array because that allows Angular to optimize an app by removing the service from the compiled app if it isn't used, this process of optimization is knows as tree-shaking.

2. You can also register a provider with a specific NgModule. In that case same servcie instance is available to all components in that NgModule.

For example configuring an app-wide provider in the @NgModule() of AppModule. You will have to use the providers property of the @NgModule() decorator.

@NgModule({
  providers: [LoggerService],
  bootstrap: [AppComponent]
})
export class AppModule { }

3. You can also register a provider at the component level, in that case you get a new instance of the service with each new instance of that component.

To register a service provider at the component level you can use the providers property of the @Component() decorator.

@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.css'],
  providers:  [ LoggerService ]
})
export class UserComponent implements OnInit {
 ..
 ..
}

Injector hierarchies in Angular

Based on these types of service providers there are two injector hierarchies in Angular.

  • ModuleInjector hierarchy— Configure a ModuleInjector in this hierarchy using an @NgModule() or @Injectable() annotation. A single service instance will be used at the root level or modulr level based upon the configuration used.
  • ElementInjector hierarchy— Angular creates ElementInjectors implicitly for each DOM element. When you provide services in a component, that service is available via the ElementInjector at that component instance. It will also be available at child components if you are not providing it again in the child component using the providers property.

Service provider example using @Injectable() decorator

In the post Service in Angular With Examples there is an example of creating a LoggerService which is decorated with @Injectable() decorator to provide the metadata that allows Angular to inject it into a component as a dependency.

Service provider example using @NgModule

Let’s see the same example by registering service in providers array of @NgModule.

LoggerService class

Now @Injectable decorator is not used in LoggerService class.

export class LoggerService {
  constructor() { }
  log(msg: string) { 
    console.log(msg); 
  }
  error(msg: string) { 
    console.error(msg); 
  }
}

Service is registered in the AppModule class now, refer the providers properties of @NgModule decorator.


import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { UserComponent } from './user/user.component';
import { LoggerService } from './services/logger.service';

@NgModule({
  declarations: [
    AppComponent,
    UserComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [LoggerService],
  bootstrap: [AppComponent]
})
export class AppModule { }

Service provider example at component level

In an example for registering provider at component level we’ll create an Angular application that shows the existing user and has a UI to add a new User.

Angular injector hierarchy

When a new user is added and submit button is clicked that user details should be added to the list of existing users.

Angular injector and service instance

After submit button is clicked.

In the example there is a UserService class that has an array of users and a function to add new user.

import { User } from '../user/user.model';

export class UserService {
  users = [new User('Jack', 62, new Date('2005-03-25')),
  new User('Olivia', 26, new Date('2014-05-09')),
  new User('Manish', 34, new Date('2010-10-21'))] ;

  addUser(user: User){
    this.users.push(user);
  }
}

For User objects a User model class is used.

export class User {
  name : string;
  age : number;
  joinDate : Date;
  constructor(name: string, age : number, joinDate : Date) {
    this.name = name;
    this.age = age;
    this.joinDate  = joinDate;
  }
}

AppComponent class

This is the component class where UserService is configured with in the providers array. In the ngOnInit() method all the existing users are assigned to the users variable, which is an array of type User, by calling the UserService.

import { Component, OnInit } from '@angular/core';
import { User } from './user/user.model';
import { UserService } from './services/user.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'], 
  providers: [UserService]
})
export class AppComponent implements OnInit{
  users: User[] = [];
  constructor(private userService: UserService){}
  ngOnInit(){
    this.users = this.userService.users;
  }
}

app.component.html

Template has selector tags for the child components.

<div class="container">
  <div class="row">
    <div class="col-xs-12 col-md-8">
      <app-adduser></app-adduser>
      <h3>User Details</h3>
      <app-user *ngFor="let u of users" [user]="u"></app-user>
    </div>
  </div>
</div>

AddUserComponent

In the AddUserComponent which is the child component of the AppComponent, UserService is provided again. There is also a method addUser() that gets the entered value for the new User, create a User object and call the addUser() method of the userService to add the entered user to the array of existing users.

import { User } from './user.model';

@Component({
  selector: 'app-adduser',
  templateUrl: './adduser.component.html',
  styleUrls: ['./adduser.component.css'],
  providers: [UserService]
})
export class AddUserComponent {
 
  constructor(private userService: UserService){}

  addUser(name: HTMLInputElement, age: HTMLInputElement, date: HTMLInputElement){
    this.userService.addUser(new User(name.value, Number(age.value), new Date(date.value)));
    // resetting input elements
    name.value = '';
    age.value = '';
    date.value = '';
  }
}
adduser.component.html

HTML template for providing a UI to add new user. It has three fields for name, age and joining date and a submit button. There is also click event binding calling the addUser() method.

<div class="row">
  <div class="col-xs-12 col-md-8">
    <div class="form-group">
      <label for="name">Name:</label>
      <input class="form-control" placeholder="Enter name" id="name" #enteredname>
    </div>
    <div class="form-group">
      <label for="age">Age:</label>            
      <input class="form-control" placeholder="Enter age" id="age" #enteredage>
    </div>      
    <div class="form-group">
      <label for="joindate">Joining Date:</label>    
      <input class="form-control" placeholder="Enter joining date" id="joindate" #entereddate>
    </div>
    <button (click)="addUser(enteredname, enteredage, entereddate)" class="btn btn-primary">Submit</button>
  </div>
</div>
UserComponent

In the component class there is a property binding using @Input decorator. In the AppComponent template there is a for loop that binds user to this property in each iteration, that’s how user details are displayed.

import { Component, OnInit, Input } from '@angular/core';
import { User } from './user.model';

@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit {
  @Input() user: User;
  
  ngOnInit(): void {
  }
}

user.component.html

<div class="container">
  <div class="row">
    <div class="col-xs-12 col-md-8 px-3">
      <p>{{user.name}} {{user.age}} {{user.joinDate | date:'dd/MM/yyyy'}}</p>
    </div>
  </div>
</div>

So these are all the classes and if you have got everything right then you can try to add new user. It won’t add it to the users array and you won’t see any new User details. That will happen because of the provider at the child component too. In the AddUserComponent too a provider is registered, that results in the creation of new UserService instance overriding the instance created by the provider at the AppComponent level.

If you have registered a service provider at parent component level, the created service instance is used by the child components too if they don't register their own provider. In this example since child component registers its own provider so a new service instance is created for the child component.

When you add a new user from AddUserComponent it is added to the array attached to the UserService instance of AddUserComponent. The details which are showed using the user property of UserComponent gets user from the array which is attached to the UserService instance of AppComponent. That is why new user details are not added.

You can comment the providers property in the @Component decorator of the AddUserComponent. Now only Single instance of UserService is created at the AppComponent level (Parent component), child component AddUserComponent shares the same instance.

@Component({
    selector: 'app-adduser',
    templateUrl: './adduser.component.html',
    styleUrls: ['./adduser.component.css'],
    //providers: [UserService]
  })
  export class AddUserComponent {
 ..
 ..
 }

That's all for this topic Injector Hierarchy and Service Instances in Angular. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Angular Tutorial Page


Related Topics

  1. Angular - Call One Service From Another
  2. Creating New Component in Angular
  3. Angular ngFor Directive With Examples
  4. Angular @Input and @Output Example
  5. Angular Disable Button Example

You may also like-

  1. Angular Two-Way Data Binding With Examples
  2. Angular One-Way Data Binding Using String Interpolation
  3. Angular Routing Concepts With Example
  4. Angular Access Control CanActivate Route Guard Example
  5. ConcurrentHashMap in Java
  6. BigDecimal in Java
  7. Spring MVC - Binding List of Objects Example
  8. Bubble Sort Program in Python