Friday, April 12, 2024

Creating Tar File And GZipping Multiple Files in Java

If you want to GZIP multiple files that can’t be done directly as you can only compress a single file using GZIP. In order to GZIP multiple files you will have to archive multiple files into a tar and then compress it to create a .tar.gz compressed file. In this post we'll see how to create a tar file in Java and gzip multiple files.

Refer How to Untar a File in Java to see how to untar a file.

Using Apache Commons Compress

Here I am posting a Java program to create a tar file using Apache Commons Compress library. You can download it from here– https://commons.apache.org/proper/commons-compress/download_compress.cgi

Make sure to add commons-compress-xxx.jar in your application’s class path. I have used commons-compress-1.13 version.

Steps to create tar files

Steps for creating tar files in Java are as follows-

  1. Create a FileOutputStream to the output file (.tar.gz) file.
  2. Create a GZIPOutputStream which will wrap the FileOutputStream object.
  3. Create a TarArchiveOutputStream which will wrap the GZIPOutputStream object.
  4. Then you need to read all the files in a folder.
  5. If it is a directory then just add it to the TarArchiveEntry.
  6. If it is a file then add it to the TarArchiveEntry and also write the content of the file to the TarArchiveOutputStream.

Folder Structure used

Here is a folder structure used in this post to read the files. Test, Test1 and Test2 are directories here and then you have files with in those directories. Your Java code should walk through the whole folder structure and create a tar file with all the entries for the directories and files and then compress it.

Test
  abc.txt
  Test1
     test.txt
     test1.txt
  Test2
     xyz.txt

Creating tar file in Java example

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.utils.IOUtils;

public class TarGZIPDemo {
 public static void main(String[] args) {
  String SOURCE_FOLDER = "/home/netjs/Documents/netjs/Test";
  TarGZIPDemo tGzipDemo = new TarGZIPDemo();
  tGzipDemo.createTarFile(SOURCE_FOLDER);

 }
  private void createTarFile(String sourceDir){
    TarArchiveOutputStream tarOs = null;
    try {
      File source = new File(sourceDir);
      // Using input name to create output name
      FileOutputStream fos = new FileOutputStream(source.getAbsolutePath().concat(".tar.gz"));
      GZIPOutputStream gos = new GZIPOutputStream(new BufferedOutputStream(fos));
      tarOs = new TarArchiveOutputStream(gos);
      addFilesToTarGZ(sourceDir, "", tarOs);    
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }finally{
      try {
        tarOs.close();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }
 
 public void addFilesToTarGZ(String filePath, String parent, TarArchiveOutputStream tarArchive) throws IOException {
  File file = new File(filePath);
  // Create entry name relative to parent file path 
  String entryName = parent + file.getName();
  // add tar ArchiveEntry
  tarArchive.putArchiveEntry(new TarArchiveEntry(file, entryName));
  if(file.isFile()){
   FileInputStream fis = new FileInputStream(file);
   BufferedInputStream bis = new BufferedInputStream(fis);
   // Write file content to archive
   IOUtils.copy(bis, tarArchive);
   tarArchive.closeArchiveEntry();
   bis.close();
  }else if(file.isDirectory()){
   // no need to copy any content since it is
   // a directory, just close the outputstream
   tarArchive.closeArchiveEntry();
   // for files in the directories
   for(File f : file.listFiles()){        
    // recursively call the method for all the subdirectories
    addFilesToTarGZ(f.getAbsolutePath(), entryName+File.separator, tarArchive);
   }
  }          
 }
}

On opening the created .tar.gz compressed file using archive manager.

creating .tar.gz file in Java

That's all for this topic Creating Tar File And GZipping Multiple Files in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Programs Page


Related Topics

  1. Zipping Files And Folders in Java
  2. Unzip File in Java
  3. Compress And Decompress File Using GZIP Format in Java
  4. Java Program to Convert a File to Byte Array
  5. Reading Delimited File in Java Using Scanner

You may also like-

  1. How to Create Deadlock in Java
  2. Convert int to String in Java
  3. Read or List All Files in a Folder in Java
  4. How to Compile Java Program at Runtime
  5. How HashMap Works Internally in Java
  6. Serialization Proxy Pattern in Java
  7. Bounded Type Parameter in Java Generics
  8. Polymorphism in Java

Thursday, April 11, 2024

Creating HTTP server in Node.js

The post Introduction to Node.js gives you an idea about Node.js and the features of Node.js. Building on top of that in this post we'll see how to create a HTTP web server using NodeJS. That also gives you an idea about using JavaScript at server side with NodeJS.

Creating a HTTP Server using NodeJS

We'll start by creating a web server written with Node.js which returns plain text 'Hello World From NodeJS' to the user.

Steps for creating a web server in NodeJS are as given below.

  1. First things you need to do is to load the built-in http module. This module provides functionality for creating an HTTP server.
    const http = require('http');
    
  2. Create server using http.createServer() method.

    http.createServer() method takes requestListener function as an argument and returns a new instance of http.Server.

    This function is meant to handle an incoming HTTP request and return an HTTP response. The requestListener function takes two arguments, a request object and a response object.

    The request object has the data of the HTTP request sent by the user. The response object is used to set the response sent back from the server.

    const requestListener = function (req, res){
    	..
    	..
    }
    

    Pass this requestListener function to the http.createServer() method

    const server = http.createServer(requestListener); 
    
  3. Once the server is created you want it to listen for the connections that is done using server.listen() method. server.listen() method takes three arguments-
    • Port number- Port the created server is bound to as an endpoint.
    • Host name- IP address of the system where server is running.
    • Callback function- A callback function which is executed when the server starts listening at the given port.

nodeserver.js

Create a file nodeserver.js and write the code as given below to create a web server using NodeJS.

const http = require('http');

const hostname = 'localhost';
const port = 3000;

const requestListener = function(req, res){
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.write('Hello World');
    res.write(' From NodeJS\n');
    res.end();
}
const server = http.createServer(requestListener);

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

You can also write the requestListener function as an arrow function that makes the code more compact.

const http = require('http');

const hostname = 'localhost';
const port = 3000;
const server = http.createServer((req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.write('Hello World');
    res.write(' From NodeJS\n');
    res.end();
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Points to note here-

  1. Port number used is 3000.
  2. Host name is 'localhost' which refers to the local system and used in place of the internal IP address 127.0.0.1. Which means to send a request to the server you’ll have to use the URL- http://localhost:3000/
  3. In the requestListener function response is created. First thing is the HTTP status code of the response which is set as “200” which means “OK”.
  4. Response header is set using res.setHeader() method. In the example it sets content type of the response as plain text.
  5. Response is written using res.write() method which can write chunks of data as response stream.
  6. end() method signals that no more data will be written to the Writable.

You can run the server by executing the JavaScript file.

node nodeserver.js

Server running at http://localhost:3000/

After that you can access http://localhost:3000/ using a browser which will establish a communication with the server. By going to the Chrom Dev tools and then Network tab you can also check the request and response.

HTTP server in Node.js

Response as HTML from NodeJS web server

In the above example content type of the response returned by the server is plain text but NodeJS web server can return content of different formats like HTML, JSON, XML, CSV also.

For that you need to set the 'Content-Type' with the corresponding format in the response header and send the content in the same format.

The following example shows how to return HTML from the server.

const http = require('http');

const hostname = 'localhost';
const port = 3000;

const server = http.createServer((req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/html');
    res.write('<html><head><title>My HTML</title></head><body><h2>Hello World from nodeJS</h2></body></html>');
    res.end();
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

As you can see now the 'Content-Type' is 'text/html' and the content that is sent back is HTML. If you re-execute the file again after stopping the server (you can use ctrl-c to stop the server) and access the URL- http://localhost:3000/ now the response you see in the browser is of type HTML.

Response as JSON from NodeJS web server

The following example shows how to return JSON from the server.

const http = require('http');

const hostname = 'localhost';
const port = 3000;

const server = http.createServer((req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'application/json');
    res.write(JSON.stringify({msg: "hello world from NodeJS" }));
    res.end();
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

As you can see now the 'Content-Type' is ' application/json' and the content that is sent back is in JSON format. If you re-execute the file again after stopping the server (you can use ctrl-c to stop the server) and access the URL- http://localhost:3000/ now the response you see in the browser is of type JSON.

Serving HTML file from webserver using Node.js

Mypage.html

HTML file that the web server will return.

<!DOCTYPE HTML>
<html>
    <head>
        <title>My HTML</title>
    </head>
    <body>
        <h2>Hello World from nodeJS</h2>
        <p>The content is read from a HTML file.</p>
    </body>
</html>

To work with the file system on your computer you need to import Node.js file system module which is called fs.

Also import path module which provides utilities for working with file and directory paths.

In the fs module there is readFile method which takes the file path as one argument and a callback function as another argument. The callback function takes two arguments, first as error (if there is some error while reading the file) and second as content of the file (if file is successfully read).

nodeserver.js

const http = require('http');
const path = require('path');
const fs = require('fs');

const hostname = 'localhost';
const port = 3000;

const server = http.createServer((req, res) => {
    const filePath = path.join(__dirname, 'mypage.html');
    console.log(filePath);
    fs.readFile(filePath, (err, data) => {
        if(err){
            res.setHeader('Content-Type', 'text/plain');
            res.statusCode = 404;
            return res.end("Error while reading file");
        }
        res.statusCode = 200;
        res.setHeader('Content-Type', 'text/html');
        res.write(data);
        return res.end();
    })
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Points to note here-

  1. Path to the file is constructed using path.join() method which joins all the arguments to the path.join() together and returns the resulting path.
  2. First argument to path.join() is __dirname which is a variable given by Node.js itself storing the directory name of the current module.
  3. In the fs.readFile() callback check has been made to see if there is an error in that case response status is set as '404' which indicates that the server cannot find the requested resource.
  4. If there is no error content of the file is send as response.

That's all for this topic Creating HTTP server in Node.js. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How to Install Node.js and NPM in Windows
  2. JavaScript Arrow Function With Examples
  3. JavaScript let and const With Examples

You may also like-

  1. Angular First App - Hello world Example
  2. Nested Route (Child Route) in Angular
  3. JSX in React
  4. React HelloWorld App - First React App
  5. Creating a Thread in Java
  6. Java Concurrency Interview Questions And Answers
  7. Linked List Implementation Java Program
  8. Spring MVC Form Example With Bean Validation

Wednesday, April 10, 2024

Angular Custom Property Binding Using @Input Decorator

In the post Angular Property Data Binding we saw how to bind data to a property of an element. We can also bind a custom property of an Angular component that’s what we’ll see in this post how to bind custom property in Angular using @Input decorator.


Angular custom property binding

Using custom property binding to set the model property of a custom component is a great way for parent and child components to communicate. For example following statement in the parent template shows the binding for the property "childItem" in the child component.

<app-child [childItem]=“parentItem”></app-child> 
  • Here <app-child> is the selector defined in the child component.
  • childItem is a field in the child component.
  • parentItem is a field in parent component.

By using custom property binding here, childItem is bound to the value of the parentItem. But that needs one more thing to work properly, using @Input decorator.

Using @Input decorator in custom property binding

By default any property in a component is accessible with in the component where it is defined. If you want to expose any property outside of the component then that property has to be decorated with @Input decorator.

export class UserComponent {
  @Input() usr: User;
  ...
  ...
}

With usr property decorated with @Input decorator, parent component can bind to this property of the child component.

@Input decorator marks a class field as an input property. The input property is bound to a DOM property in the template. During change detection, Angular automatically updates the data property with the DOM property's value.

Angular custom property binding example

The requirement is to show user details in a child component where each user instance is passed from the parent component. Thing to notice here is that use of @Input decorator gives you a chance to break your code into separate components which promotes reusing of components. Here child component can be termed as a presentational component.

Creating a User class

Create a Type script class user.model.ts to define a User class. If you are aware of MVC (Model View Controller) pattern then this class is the Model. There are 3 fields name, age and joinDate in the User class.

user.model.ts

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;
  }
}

app.component.ts (Parent component)

import {Component} from '@angular/core';
import { User } from './user/user.model';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  users: User[];
  constructor(){
    //Adding User instances to users array
    this.users = [new User('Jack', 56, new Date('2005-03-25')),
    new User('Lisa', 32, new Date('2012-05-09')),
    new User('Jayesh', 28, new Date('2014-10-21'))] ;
  }
}

AppComponent uses User model so that is imported. An array of type User is defined and user instances are added to that array in the Constructor.

app.component.html

<div class="container">
  <h3>User Details</h3>
  <app-user *ngFor="let user of users" 
               [usr]="user">
  </app-user>
</div>

In the template with in the <app-user> selector users array is iterated using ngFor directive and each user instance is bound to the usr property of the child component.

user.component.ts (Child component)

import { 
    Component, Input
 } from '@angular/core';
import { User } from './user.model';
@Component({
  selector: 'app-user',
  templateUrl: './user.component.html'
})
export class UserComponent {
  @Input() usr!: User;
}

In the child component usr variable is decorated with @Input decorator indicating that parent component can bind to this property. Note that non-null assertion operator (!) is used here to suspend strict null and undefined checks for the usr property.

User.component.html

In the template user data is displayed using string interpolation.

<div class="row">
  <div class="col-xs-6">
    <label>Name: </label> {{ usr.name }}
    <label>Age: </label> {{ usr.age }}
    <label>Join Date: </label> {{ usr.joinDate | date:'dd/MM/yyyy' }}
  </div>
</div>
Angular Custom Property Binding

That's all for this topic Angular Custom Property Binding Using @Input Decorator. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Angular Tutorial Page


Related Topics

  1. Angular Style Binding With Examples
  2. Angular Two-Way Data Binding With Examples
  3. Angular Custom Event Binding Using @Output Decorator
  4. Angular Custom Two-Way Data Binding
  5. How to Install Node.js and NPM in Windows

You may also like-

  1. Angular ngClass Directive With Examples
  2. Angular Cross Component Communication Using Subject Observable
  3. Setting Wild Card Route in Angular
  4. FormArray in Angular With Example
  5. Java Multithreading Interview Questions And Answers
  6. How to Sort HashSet in Java
  7. How to Convert Date And Time Between Different Time-Zones in Java
  8. Convert String to int in Python

Tuesday, April 9, 2024

Angular Custom Event Binding Using @Output Decorator

In the post Angular event binding we saw how event binding allows you to listen and respond to the events sent by the host elements. We can also bind a custom event of an Angular component that’s what we’ll see in this post how to bind custom event in Angular using @Output decorator.


Angular custom event binding

Using custom event binding is a great way for parent and child components to communicate where parent component is informed of any change in the child component. For example following statement in the parent template shows the event binding for the property "onUserSelected" in the child component.

Statement in parent component-

<app-user *ngFor="let user of users" 
            [usr]="user" (onUserSelected)="showUser($event)">

Property in child component-

@Output() onUserSelected: EventEmitter<User>;

@Output decorator, $event and EventEmitter

While doing a custom event binding in Angular three things you will come across are-

  1. @Output decorator
  2. EventEmitter class
  3. $event object

1. @Output decorator

A property in a Component that emits a custom event is decorated with @Output decorator. For example in the statement

@Output() onUserSelected: EventEmitter<User>;

onUserSelected is decorated with @Output() which means this property is going to emit a custom event. That is why this property is of type EventEmitter.

2. EventEmitter class

EventEmitter class is used in components with the @Output to emit custom events synchronously or asynchronously. EventEmitter maintains a list of subscribing instances and register handlers for the event.

EventEmitter class has two methods-

  • emit(value?: T)- Emits an event containing a given value, T signifies the value to emit.
  • subscribe()- Registers handlers for events emitted by this instance.

When we assign an EventEmitter to an output, subscription of instances is automatically done by Angular so you don't need to use this method explicitly in most of the scenarios.

3. $event object

In an event binding, Angular sets up an event handler for the target event. The binding conveys information about the event. This information is encapsulated in $event and may include data values such as an event object, string, or number.

When the event is raised, the handler executes the template statement. For example in the following statement

(onUserSelected)="showUser($event)"

(onUserSelected) is the target event

showUser($event) is the template statement.

When the event onUserSelected is raised, template statement, which in our example is showUser($event) method, is executed. Argument of the showUser() method is $event which encapsulates the value passed as method parameter.

Angular custom event binding example

We have got enough information about the event binding and the parts that form the custom event binding. Let’s create an example using that knowledge now. Note than example is created using Angular 17 and Bootstrap 5.

In the example there are two child components UserComponent and UserDataComponent and AppComponent is the parent component.

Initially list of user names is displayed (Done through UserComponent), on clicking any of the user User details are displayed (Done through UserDataComponent).

user.model.ts

In the Model class there are 3 fields name, age and 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;
  }
}

app.component.ts (Parent component)

AppComponent uses User model so that is imported. An array of type User is defined and user instances are added to that array in the Constructor. Property selectedUser stores the value of the User which is selected and used to display details for the selected User. When the custom event is raised showUser() method gets called which assigns value to the selectedUser property.

import {Component} from '@angular/core';
import { User } from './user/user.model';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  users: User[];
  selectedUser!: User;
  constructor(){
    //Adding User instances to users array
    this.users = [new User('Jack', 56, new Date('2005-03-25')),
                  new User('Lisa', 32, new Date('2012-05-09')),
                  new User('Jayesh', 28, new Date('2014-10-21'))
                 ] ;
  }
  showUser(user: User) : void {
    // Setting selected user
    this.selectedUser = user;
  }
}

app.component.html

<div class="container">
  <h3>Click User to get details</h3>
  <app-user 
      *ngFor="let user of users" 
      [usr]="user" (onUserSelected)="showUser($event)">
  </app-user>

  <user-data *ngIf="selectedUser" [user]="selectedUser"></user-data>
</div>

Template has two selectors tags for the child templates. With in the <app-user> selector users array is iterated using ngFor directive and each user instance is bound to the usr property of the child component, onUserSelected is the output property (to emit event).

user.component.ts (Child component)

import { Component, Input, Output, EventEmitter } from '@angular/core';
import { User } from './user.model';
@Component({
  selector: 'app-user',
  templateUrl: './user.component.html'
})
export class UserComponent {
  @Input() usr!: User;
  @Output() onUserSelected: EventEmitter<User>;
  constructor(){
    this.onUserSelected = new EventEmitter();
  }
  userClicked() : void{
    this.onUserSelected.emit(this.usr);
  }
}

In the child component usr variable is decorated with @Input decorator indicating that parent component can bind to this property.

onUserSelected is decorated with @Output indicating that it will emit an event.

In the userClicked() method using emit method an event is emitted with current user instance as event value which will be encapsulated in $event.

User.component.html

In the template user name is displayed, there is also an even binding for click event which calls the userClicked() method. Execution of userClicked() method results in emitting the event with the user instance as value.

<div class="row">
  <div class="col-xs-6">
    <label>Name:</label><span (click)='userClicked()'> {{ usr.name }}</span>
  </div>
</div>

userdata.component.ts (Child component)

import { 
  Component, Input
 } from '@angular/core';
import { User } from './user.model';
@Component({
  selector: 'user-data',
  templateUrl: './userdata.component.html'
})
export class UserDataComponent{
  @Input() user!: User;
}

Another child component UserDataComponent has a property user which is decorated with @Input decorator indicating that parent component can bind to this property. This is property to which selected user is assigned and then used to display user details.

userdata.component.html

This template shows the user details.

<div class="mt-4 p-3 bg-light">
  <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>

Testing the application

Initially user names are displayed.

Angular Custom Event Binding

When user name is clicked

Custom Event Binding Example

That's all for this topic Angular Custom Event Binding Using @Output Decorator. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Angular Tutorial Page


Related Topics

  1. Angular Custom Property Binding Using @Input Decorator
  2. Angular Custom Two-Way Data Binding
  3. Angular Style Binding With Examples
  4. Angular Example to Render Multiple Rows
  5. Angular @Input and @Output Example

You may also like-

  1. Angular ngClass Directive With Examples
  2. Angular @Component Decorator
  3. Service in Angular With Examples
  4. Angular Disable Button Example
  5. Multiple Catch Blocks in Java Exception Handling
  6. intern() Method in Java String
  7. Varargs (Variable-length Arguments) in Java
  8. Spring Batch Processing With List of Objects in batchUpdate() Method

Monday, April 8, 2024

Switch Expressions in Java 12

In Java 12 Switch statement has been extended to be used either as a statement or an expression. In this article we’ll see with some examples how to use this new feature switch expressions in Java.


Java Switch expressions

A new form of switch label, written "case L ->" has been added in Java 12 that allows the code to the right of the label to execute only if the label is matched.

We’ll try to understand this switch expression with an example, initially let’s use traditional switch statement to write a conditional switch-case branch and then use switch expression to see how it simplifies it.

For example if you want to display the quarter, passed month falls into then you can group three case statements where break statement is used with only the last one in the group.

public class SwitchCaseDemo {

 public static void main(String[] args) {
  int month = 4;  
  switch(month){
   case 1:    
   case 2:    
   case 3: System.out.println("Quarter 1"); 
     break;
   
   case 4:   
   case 5:     
   case 6: System.out.println("Quarter 2"); 
     break;
   
   case 7:   
   case 8:  
   case 9: System.out.println("Quarter 3"); 
     break;
   
   case 10:     
   case 11:   
   case 12: System.out.println("Quarter 4"); 
      break;
   
   default: System.out.println("Invalid month value passed");
  }
 }
}

Consider some of the pain areas here-

  1. Even if multiple cases have the same end value still you need to write them in the separate lines.
  2. Use of many break statements make it unnecessarily verbose.
  3. Missing a break statement results in an accidental fall-through.

Now let’s write the same example using Java switch expressions.

public class SwitchCaseDemo {

  public static void main(String[] args) {
    int month = 4;        
    switch(month){
      case 1, 2, 3 -> System.out.println("Quarter 1");         

      case 4, 5, 6 -> System.out.println("Quarter 2");     
  
      case 7, 8, 9 -> System.out.println("Quarter 3");             
       
      case 10, 11, 12 -> System.out.println("Quarter 4");              
      
      default -> System.out.println("Invalid month value passed");
    }
  }
}

Note the changes here-

  1. Multiple case labels can be grouped together now.
  2. Break statement is not required any more. If a label is matched, then only the expression or statement to the right of an arrow label is executed; there is no fall through.
  3. This new switch form uses the lambda-style syntax introduced in Java 8 consisting of the arrow between the label and the code that returns a value.

The new kind of case label has the following form

case label_1, label_2, ..., label_n -> expression;|throw-statement;|block

Java 12 onward you can use colon syntax (:) too with multiple case labels but in that case break statement has to be used to avoid fall-through.

public class SwitchCaseDemo {

 public static void main(String[] args) {
  int month = 4;  
  switch(month){
   case 1, 2, 3: System.out.println("Quarter 1"); 
         break;

   case 4, 5, 6: System.out.println("Quarter 2");  
       break;
   case 7, 8, 9: System.out.println("Quarter 3");    
       break;
   case 10, 11, 12: System.out.println("Quarter 4");     
       break;
   default : System.out.println("Invalid month value passed");
  }
 }
}

Why is it called Switch expression

Now the more pertinent question is why this new feature is called switch expression in Java. As you must be knowing; Statements are essentially "actions" that have to be executed. Expressions, however, are "requests" that produce a value. Same difference applies to switch statement and switch expressions too.

Here is an example showing returning a value from a traditional switch statement.

public class SwitchCaseDemo {
 public static void main(String[] args) {
  System.out.println(getMessage("Start"));
 }
 private static String getMessage(String event) {
  String message = "No event to log";
  switch (event) {
    case "Start":
      message = "User started the event";
      break;
    case "Stop":
      message = "User stopped the event";
      break;
  }
  return message;
 }
}

Output

User started the event

Same thing with Java Switch expressions. Since expression itself produces a value so it can be assigned to a variable directly.

public class SwitchCaseDemo {

 public static void main(String[] args) {
  System.out.println(getMessage("Start"));
 }
 private static String getMessage(String event) {
  var msg = switch (event) {
    case "Start" ->  "User started the event";
    case "Stop" -> "User stopped the event";
    default -> "No event to log";
  };
  return msg;
 }
}

Output

User started the event

Using yield statement with Switch expression

If you want to use colon syntax then you can assign the value directly using yield statement. The yield statement takes one argument, which is the value that the case label produces in a switch expression.

public class SwitchCaseDemo {

  public static void main(String[] args) {
    System.out.println(getMessage("Stop"));
  }
	 
  private static String getMessage(String event) {
    var msg = switch (event) {
      case "Start": 
        yield "User started the event";
      case "Stop": 
        yield "User stopped the event";
      default: 
        yield "No event to log";
    };
    return msg;
  }
}

Writing statement blocks

If you need to have multiple statements with in a case you can use a statement block enclosed in curly braces. Specify the value that the case label produces with the yield statement.

public class SwitchCaseDemo {

  public static void main(String[] args) {
    int month = 4;        
    var value = switch(month){
      case 1, 2, 3 ->{
        System.out.println("Quarter 1");     
        yield "Quarter 1";
      }
      case 4, 5, 6 -> {
        System.out.println("Quarter 2"); 
        yield "Quarter 2";
      }
          
      case 7, 8, 9 ->{
        System.out.println("Quarter 3");     
        yield "Quarter 3";
      }
               
      case 10, 11, 12 -> {
        System.out.println("Quarter 4");  
        yield "Quarter 4";            
      }
              
      default -> {
        System.out.println("Invalid month value passed");
        yield "Invalid month value";
      }
    };
    System.out.println("Value- " + value);
  }
}

That's all for this topic Switch Expressions in Java 12. If you have any doubt or any suggestions to make please drop a comment.Thanks!

>>>Return to Java Basics Tutorial Page


Related Topics

  1. Java Sealed Classes and Interfaces
  2. break Statement in Java With Examples
  3. Java Record Class With Examples
  4. Ternary Operator in Java
  5. Core Java Basics Interview Questions And Answers

You may also like-

  1. Private Methods in Java Interface
  2. Multi-Catch Statement in Java Exception Handling
  3. Creating a Thread in Java
  4. How HashMap Works Internally in Java
  5. Byte Streams in Java IO
  6. Check if Given String or Number is a Palindrome Java Program
  7. Spring Boot Hello World Web Application Example
  8. Connection Pooling With Apache DBCP Spring Example

Angular Custom Two-Way Data Binding

In the post Angular Two-Way Data Binding With Examples we saw how two way binding can be done using ngModel and it is a combination of both property binding and event binding. In this post we’ll see how to do custom two way data binding in Angular.

Angular custom two way data binding

You can use a custom property for two way data binding, for example-

<app-counter [(counter)]="counterValue"></app-counter>

Here counter is a property that has two way data binding. In the component you should have a counter property that can be assigned a value and a corresponding event named counterChange. Note that this convention has to be followed, the event name has to be ‘property name + change’.

Angular custom two way data binding example

Here is a simple example of custom two way data binding. There is a child component that displays the counter value and has buttons to decrement or increment counter value.

counter.component.html

<div>
  <label>Value </label> {{counter}}
  <hr/>
  <button class="btn btn-primary me-2" (click)="dec()">-</button>
  <button class="btn btn-primary" (click)="inc()">+</button>
</div> 

counter.component.ts

import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-counter',
  templateUrl: './counter.component.html'
})
export class CounterComponent{
  @Input() counter: number = 0;
  //event name has to be 'property name + change'
  @Output() counterChange = new EventEmitter<number>();

  dec(){
    --this.counter;
    this.counterChange.emit(this.counter);
  }
  inc(){
    ++this.counter;
    this.counterChange.emit(this.counter);
  }
}

In the component, counter property is decorated with @Input decorator which means property binding where value of counter is expected from the parent component through this binding.

There is also an event binding done using counterChange. Whenever decrement or increment button is clicked value of counter is changed and that changed value is emitted using counterChange event emitter.

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'], 
})
export class AppComponent{
  counterValue = 5;
}

app.component.html

<div class="container">
  <div class="row">
    <div class="col-sm-6">       
      <app-counter [(counter)]="counterValue"></app-counter>
      <label>Value of the counter is </label> {{counterValue}}
    </div>
  </div>
</div>

Here AppComponent.counterValue is two-way bound to the CounterComponent. counter property of CounterComponent gets its initial value from AppComponent.counterValue ( counterValue = 5 in AppComponent). Clicking the decrement and increment buttons updates the AppComponent.counterValue via the two-way binding.

So, there is a property binding where child property is bound to the parent property and there is also an event binding from child to parent causing the change in counter value.

Initial screen

On clicking decrement.

That's all for this topic Angular Custom Two-Way Data Binding. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Angular Tutorial Page


Related Topics

  1. Angular Custom Property Binding Using @Input Decorator
  2. Angular Custom Event Binding Using @Output Decorator
  3. Angular Style Binding With Examples
  4. Angular @Input and @Output Example
  5. Angular ngSwitch Directive With Examples

You may also like-

  1. Injector Hierarchy and Service Instances in Angular
  2. Angular - Call One Service From Another
  3. Forms in Angular
  4. Angular Project Structure With File Description
  5. Java String Interview Questions And Answers
  6. Java BlockingQueue With Examples
  7. Spring Boot spring-boot-starter-parent
  8. Apache Avro Format in Hadoop

Sunday, April 7, 2024

FormArray in Angular With Example

FormArray in Angular provides another way to group any number of controls apart from FormGroup in Angular. Difference between FormGroup and FormArray is that in FormGroup each child FormControl is added as the part of FormGroup object as a key, value pair where control name is the key. In FormArray value of each child FormControl is added into an array.

Since FormArray internally maintains an array of FormControls so it is easy to add or remove controls from it giving you capability to create a dynamic form using FormArray in Angular.