Angular + Spring Boot + Cassandra CRUD example

[no_toc]In this tutorial, ozenero shows you Angular Http Client & Spring Boot Server example that uses Spring Data to interact with Cassandra and Angular as a front-end technology to make request and receive response.

Related Posts:
Angular + Spring JPA + MySQL example | Angular Http Client – Spring Boot RestApi Server
Angular + Spring JPA + PostgreSQL example | Angular Http Client – Spring Boot RestApi Server
Angular + Spring JPA + MySQL example | Angular Http Client – Spring Boot RestApi Server
Angular + Spring Boot + MongoDB CRUD example
How to start Spring Data Cassandra with SpringBoot
Angular + Spring WebFlux + Spring Data Reactive Cassandra example | Full-Reactive Angular Http Client – Spring Boot RestApi Server

I. Technologies

– Java 1.8
– Maven 3.3.9
– Spring Tool Suite 3.9.0.RELEASE
– Spring Boot 1.5.9.RELEASE
– Angular
– Cassandra 3.9.0

II. Overview

angular-http-service-architecture

1. Spring Boot Server

angular-4-spring-data-cassandra-server-overview

A Spring Boot Cassandra – example:
How to start Spring Data Cassandra with SpringBoot

2. Angular Client

angular4-springdata-cassandra-httpclient-overview
For more details:
– About Angular Routing:
How to work with Angular Routing – Spring Boot + Angular
– About Angular Http Client to GET/POST/DELETE:
+ How to use Angular Http Client to fetch Data from SpringBoot RestAPI – Angular
+ How to use Angular HttpClient to POST, PUT, DELETE data on SpringBoot Rest APIs – Angular

III. Practice

1. Project Structure

1.1 Spring Boot Server

angular-4-spring-data-cassandra-server-structure

– Class Customer corresponds to customer table.
CustomerRepository is an interface extends Spring Data CassandraRepository, will be autowired in CustomerController for implementing repository methods and finder methods.
CustomerController is a REST Controller which has request mapping methods for RESTful requests such as: getAll, create, update, delete Customers.
– Configuration for Spring Data Cassandra properties in application.properties
– Dependencies for Spring Boot and Spring Data Cassandra in pom.xml

1.2 Angular Client

angular4-springdata-cassandra-client-structure

In this example, we have:
– 3 components: customers-list, customer-details, create-customer.
– 3 modules: FormsModule, HttpClientModule, AppRoutingModule.
customer.ts: class Customer (id, name, age, active).
customer.service.ts: Service for HttpClient methods.

2. How to do

2.0 Set up Cassandra

Open Cassandra CQL Shell:

– Create Cassandra keyspace with name javasampleapproach:

create keyspace javasampleapproach with replication={'class':'SimpleStrategy', 'replication_factor':1};

– Create customer table for javasampleapproach keyspace:

use javasampleapproach;

CREATE TABLE customer(
   id timeuuid PRIMARY KEY,
   name text,
   age int,
   active boolean
);

2.1 Spring Boot Server

2.1.1 Dependency
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-cassandra</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.1.2 Customer – Data Model
package com.javasampleapproach.angular4cassandra.model;

import java.util.UUID;

import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.Table;

@Table
public class Customer {

	@PrimaryKey
	private UUID id;

	private String name;
	private int age;
	private boolean active;

	public Customer() {
	}

	public Customer(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public UUID getId() {
		return id;
	}

	public void setId(UUID id) {
		this.id = id;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return this.name;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getAge() {
		return this.age;
	}

	public boolean isActive() {
		return active;
	}

	public void setActive(boolean active) {
		this.active = active;
	}

	@Override
	public String toString() {
		return "Customer [id=" + id + ", name=" + name + ", age=" + age + ", active=" + active + "]";
	}
}
2.1.3 Repository
package com.javasampleapproach.angular4cassandra.repo;

import org.springframework.data.cassandra.repository.CassandraRepository;

import com.javasampleapproach.angular4cassandra.model.Customer;

public interface CustomerRepository extends CassandraRepository {

}
2.1.4 REST Controller
package com.javasampleapproach.angular4cassandra.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.cassandra.repository.support.BasicMapId;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.datastax.driver.core.utils.UUIDs;
import com.javasampleapproach.angular4cassandra.model.Customer;
import com.javasampleapproach.angular4cassandra.repo.CustomerRepository;

@CrossOrigin(origins = "http://localhost:4200")
@RestController
@RequestMapping("/api")
public class CustomerController {

	@Autowired
	CustomerRepository customerRepository;

	@GetMapping("/customers")
	public List getAllCustomers() {
		System.out.println("Get all Customers...");

		List customers = new ArrayList<>();
		customerRepository.findAll().forEach(customers::add);
		return customers;
	}

	@PostMapping("/customers/create")
	public ResponseEntity createCustomer(@Valid @RequestBody Customer customer) {
		System.out.println("Create Customer: " + customer.getName() + "...");

		customer.setId(UUIDs.timeBased());
		customer.setActive(false);
		Customer _customer = customerRepository.save(customer);
		return new ResponseEntity<>(_customer, HttpStatus.OK);
	}

	@PutMapping("/customers/{id}")
	public ResponseEntity updateCustomer(@PathVariable("id") UUID id, @RequestBody Customer customer) {
		System.out.println("Update Customer with ID = " + id + "...");

		Customer customerData = customerRepository.findOne(BasicMapId.id("id", id));
		if (customerData == null) {
			return new ResponseEntity<>(HttpStatus.NOT_FOUND);
		}
		customerData.setName(customer.getName());
		customerData.setAge(customer.getAge());
		customerData.setActive(customer.isActive());
		Customer updatedcustomer = customerRepository.save(customerData);
		return new ResponseEntity<>(updatedcustomer, HttpStatus.OK);
	}

	@DeleteMapping("/customers/{id}")
	public ResponseEntity deleteCustomer(@PathVariable("id") UUID id) {
		System.out.println("Delete Customer with ID = " + id + "...");

		customerRepository.delete(BasicMapId.id("id", id));
		return new ResponseEntity<>("Customer has been deleted!", HttpStatus.OK);
	}

	@DeleteMapping("/customers/delete")
	public ResponseEntity deleteAllCustomers() {
		System.out.println("Delete All Customers...");

		customerRepository.deleteAll();
		return new ResponseEntity<>("All customers have been deleted!", HttpStatus.OK);
	}
}
2.1.5 Configuration for Spring Data Cassandra
spring.data.cassandra.keyspace-name=javasampleapproach
spring.data.cassandra.contact-points=127.0.0.1
spring.data.cassandra.port=9042

2.2 Angular Client

2.2.1 AppModule
import { AppRoutingModule } from './app-routing.module';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';

import { AppComponent } from './app.component';

import { CustomersListComponent } from './customers/customers-list/customers-list.component';
import { CustomerDetailsComponent } from './customers/customer-details/customer-details.component';
import { CreateCustomerComponent } from './customers/create-customer/create-customer.component';

import { CustomerService } from './customers/customer.service';

@NgModule({
  declarations: [
    AppComponent,
    CustomersListComponent,
    CustomerDetailsComponent,
    CreateCustomerComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule,
    HttpClientModule
  ],
  providers: [CustomerService],
  bootstrap: [AppComponent]
})

export class AppModule { }
2.2.2 Model
export class Customer {
  id: string;
  name: string;
  age: number;
  active: boolean;
}
2.2.3 DataService
import { Injectable } from '@angular/core';
import { HttpClient, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';

import { Customer } from './customer';

@Injectable()
export class CustomerService {

  private baseUrl = 'http://localhost:8080/api/customers';

  constructor(private http: HttpClient) { }

  getCustomer(id: string): Observable<Object> {
    return this.http.get(`${this.baseUrl}/${id}`);
  }

  createCustomer(customer: Object): Observable<Object> {
    return this.http.post(`${this.baseUrl}` + `/create`, customer);
  }

  updateCustomer(id: string, value: any): Observable<Object> {
    return this.http.put(`${this.baseUrl}/${id}`, value);
  }

  deleteCustomer(id: string): Observable<any> {
    return this.http.delete(`${this.baseUrl}/${id}`, { responseType: 'text' });
  }

  getCustomersList(query = {}): Observable<any> {
    return this.http.get(`${this.baseUrl}`);
  }

  deleteAll(): Observable<any> {
    return this.http.delete(`${this.baseUrl}` + `/delete`, { responseType: 'text' });
  }
}
2.2.4 Components

– CustomerDetailsComponent:

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

import { CustomerService } from '../customer.service';
import { Customer } from '../customer';

import { CustomersListComponent } from '../customers-list/customers-list.component';

@Component({
  selector: 'customer-details',
  templateUrl: './customer-details.component.html',
  styleUrls: ['./customer-details.component.css']
})
export class CustomerDetailsComponent implements OnInit {

  @Input() customer: Customer;

  constructor(private customerService: CustomerService, private listComponent: CustomersListComponent) { }

  ngOnInit() {
  }

  updateActive(isActive: boolean) {
    this.customerService.updateCustomer(this.customer.id,
      { name: this.customer.name, age: this.customer.age, active: isActive })
      .subscribe(
      data => {
        console.log(data);
        this.customer = data as Customer;
      },
      error => console.log(error));
  }

  deleteCustomer() {
    this.customerService.deleteCustomer(this.customer.id)
      .subscribe(
      data => {
        console.log(data);
        this.listComponent.reloadData();
      },
      error => console.log(error));
  }

}
<div *ngIf="customer">
	<div>
		<label>Name: </label> {{customer.name}}
	</div>
	<div>
		<label>Age: </label> {{customer.age}}
	</div>
	<div>
		<label>Active: </label> {{customer.active}}
	</div>

	<span class="button is-small btn-primary" *ngIf='customer.active' (click)='updateActive(false)'>Inactive</span>

	<span class="button is-small btn-primary" *ngIf='!customer.active' (click)='updateActive(true)'>Active</span>

	<span class="button is-small btn-danger" (click)='deleteCustomer()'>Delete</span>

	<hr/>
</div>

– CustomersListComponent:

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs/Observable';

import { CustomerService } from '../customer.service';
import { Customer } from '../customer';

@Component({
  selector: 'customers-list',
  templateUrl: './customers-list.component.html',
  styleUrls: ['./customers-list.component.css']
})
export class CustomersListComponent implements OnInit {

  customers: Observable;

  constructor(private customerService: CustomerService) {

  }

  ngOnInit() {
    this.reloadData();
  }

  deleteCustomers() {
    this.customerService.deleteAll()
      .subscribe(
      data => {
        console.log(data);
        this.reloadData();
      },
      error => console.log('ERROR: ' + error));
  }

  reloadData() {
    this.customers = this.customerService.getCustomersList();
  }
}
<h1>Customers</h1>

<div *ngFor="let customer of customers | async" style="width: 300px;">
	<customer-details [customer]='customer'></customer-details>
</div>

<div>
	<button type="button" class="button btn-danger" (click)='deleteCustomers()'>Delete All</button>
</div>

– CreateCustomerComponent:

import { Component, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { Customer } from '../customer';
import { CustomerService } from '../customer.service';

@Component({
  selector: 'create-customer',
  templateUrl: './create-customer.component.html',
  styleUrls: ['./create-customer.component.css']
})
export class CreateCustomerComponent implements OnInit {

  customer: Customer = new Customer();
  submitted = false;

  constructor(private customerService: CustomerService) { }

  ngOnInit() {
  }

  newCustomer(): void {
    this.submitted = false;
    this.customer = new Customer();
  }

  save() {
    this.customerService.createCustomer(this.customer)
      .subscribe(data => console.log(data), error => console.log(error));
    this.customer = new Customer();
  }

  onSubmit() {
    this.submitted = true;
    this.save();
  }
}
<h3>Create Customer</h3>
<div [hidden]="submitted" style="width: 300px;">
	<form (ngSubmit)="onSubmit()">
		<div class="form-group">
			<label for="name">Name</label> <input type="text"
				class="form-control" id="name" required [(ngModel)]="customer.name"
				name="name">
		</div>

		<div class="form-group">
			<label for="age">Age</label> <input type="text"
				class="form-control" id="age" required [(ngModel)]="customer.age"
				name="age">
		</div>

		<button type="submit" class="btn btn-success">Submit</button>
	</form>
</div>

<div [hidden]="!submitted">
	<h4>You submitted successfully!</h4>
	<button class="btn btn-success" (click)="newCustomer()">Add</button>
</div>
2.2.5 AppRoutingModule
import { CreateCustomerComponent } from './customers/create-customer/create-customer.component';
import { CustomersListComponent } from './customers/customers-list/customers-list.component';

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  { path: '', redirectTo: 'customers', pathMatch: 'full' },
  { path: 'customers', component: CustomersListComponent },
  { path: 'add', component: CreateCustomerComponent },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})

export class AppRoutingModule { }
2.2.6 App Component
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})

export class AppComponent {
  title = 'JavaSampleApproach';
  description = 'Angular4-HttpClient';

  constructor() { }

}
<div class="container-fluid">
	<div style="color: blue;">
		<h1>{{title}}</h1>
		<h3>{{description}}</h3>
	</div>

	<nav>
		<a routerLink="customers" class="btn btn-primary active" role="button" routerLinkActive="active">Customers</a>
		<a routerLink="add" class="btn btn-primary active" role="button" routerLinkActive="active">Add</a>
	</nav>
	<router-outlet></router-outlet>
</div>

3. Run & Check Result

Build and Run Spring Boot project with commandlines: mvn clean install and mvn spring-boot:run.
– Run the Angular App with command: npm start.

– Open browser for url http://localhost:4200/:
Add Customer(Jack,27):
angular4-springdata-cassandra-httpclient-result-add-customer

Add more customers, check Cassandra table:
angular4-springdata-cassandra-httpclient-result-add-customers-shell

Choose tab Customers:
angular4-springdata-cassandra-httpclient-result-show-customers

Update active status by click on Active label:
angular4-springdata-cassandra-httpclient-result-update-customer

Delete a customer (Jack):
angular4-springdata-cassandra-httpclient-result-delete-customer

Check Cassandra table again, Katherin‘s active status has changed, and Jack data has been deleted:
angular4-springdata-cassandra-httpclient-result-update-customers-shell

Click Delete All button:
angular4-springdata-cassandra-httpclient-result-delete-all-customers

IV. Source Code

SpringBootAngular4Cassandra
Angular4HttpClient-CassandraCRUD

0 0 votes
Article Rating
Subscribe
Notify of
guest
2.4K Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments