In this post, we are going to learn how to implement RESTful web services using Spring Boot and Cassandra db.
Project Structure:
Tools & Technologies:- Java 8
- Maven 3.0.3
- Spring Boot 1.2.5.RELEASE
- Cassandra Database 2.1.8
- Spring data cassandra 1.2.2.RELEASE
Cassandra Keyspace and Table Creation:
cqlsh> create keyspace "ranga" with replication = {'class': 'SimpleStrategy', 'replication_factor': '1'};
cqlsh:system_traces> use ranga;
cqlsh:ranga> CREATE TABLE employee(id bigint PRIMARY KEY, name text, age int, salary float);
cqlsh:system_traces> INSERT INTO employee(id, name, age, salary) VALUES(1, 'Ranga', 27, 30000);
cqlsh:ranga> select * from employee;
id | age | name | salary
----+-----+-------+--------
1 | 27 | Ranga | 30000
Maven Configurationpom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ranga</groupId>
<artifactId>SpringBootRestAPICassandraExample</artifactId>
<version>1.0.0-SNAPSHOT</version>
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.5.RELEASE</version>
</parent>
<dependencies>
<!-- Get the dependencies of a web application -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Data Cassandra -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Configuring the Cassandra DB propertiessrc/main/resources/cassandra.properties
cassandra.contactpoints=localhost,127.0.0.1
cassandra.port=9042
cassandra.keyspace=ranga
Utility class for Cassandra db operations:CassandraUtil.java
package com.ranga.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.cassandra.config.CassandraClusterFactoryBean;
import org.springframework.data.cassandra.config.CassandraSessionFactoryBean;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.convert.CassandraConverter;
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.core.CassandraTemplate;
import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
/**
* Utility class for getting the CassandraOperations object.
* @author Ranga Reddy
* @version 1.0
*/
@Configuration
@PropertySource(value = { "classpath:cassandra.properties" })
public class CassandraUtil {
/**
* Constant String for Keyspace
*/
private static final String KEYSPACE = "cassandra.keyspace";
/**
* Constant String for ContactPoints
*/
private static final String CONTACTPOINTS = "cassandra.contactpoints";
/**
* Constant String for Port
*/
private static final String PORT = "cassandra.port";
@Autowired
private Environment environment;
public CassandraUtil() {
System.out.println("CassandraUtil()");
}
private String getKeyspaceName() {
return environment.getProperty(KEYSPACE);
}
private String getContactPoints() {
return environment
.getProperty(CONTACTPOINTS);
}
private int getPortNumber() {
return Integer.parseInt(environment
.getProperty(PORT));
}
@Bean
public CassandraClusterFactoryBean cluster() {
CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
cluster.setContactPoints(getContactPoints());
cluster.setPort(getPortNumber());
return cluster;
}
@Bean
public CassandraMappingContext mappingContext() {
return new BasicCassandraMappingContext();
}
@Bean
public CassandraConverter converter() {
return new MappingCassandraConverter(mappingContext());
}
@Bean
public CassandraSessionFactoryBean session() throws Exception {
CassandraSessionFactoryBean cassandraSessionFactoryBean = new CassandraSessionFactoryBean();
cassandraSessionFactoryBean.setCluster(cluster().getObject());
cassandraSessionFactoryBean.setKeyspaceName(getKeyspaceName());
cassandraSessionFactoryBean.setConverter(converter());
cassandraSessionFactoryBean.setSchemaAction(SchemaAction.NONE);
return cassandraSessionFactoryBean;
}
@Bean
public CassandraOperations cassandraTemplate() throws Exception {
return new CassandraTemplate(session().getObject());
}
}
MyCassandraTemplate.java
package com.ranga.util;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.stereotype.Repository;
/**
* Utility class for handling all CRUD Operations.
* @author Ranga Reddy
* @version 1.0
*/
@Repository
public class MyCassandraTemplate {
@Autowired
private CassandraOperations cassandraTemplate;
/** MyCassandraTemplate Default constructor*/
public MyCassandraTemplate() {
System.out.println("MyCassandraTemplate()");
}
/**
* Creating the entity.
* @param entity
* @return {@link Object}
*/
public <T> T create(T entity) {
return cassandraTemplate.insert(entity);
}
/**
* Creating the list of entities.
* @param entity
*/
public <T> void createList(List<T> entities) {
cassandraTemplate.insert(entities);
}
/**
* Updating the entity.
* @param entity
* @param claz
* @return T
*/
public <T> T update(T entity) {
return (T) cassandraTemplate.update(entity);
}
/**
* Updating the list of entities.
* @param entity
* @param claz
* @return T
*/
public <T> void updateList(List<T> entities) {
cassandraTemplate.update(entities);
}
/**
* Updating the entity.
* @param entity
* @param claz
* @return T
*/
public <T> T update(T entity, Class<T> claz) {
return (T) cassandraTemplate.update(entity);
}
/**
* Get the Entity using Id.
* @param id
* @param claz
* @return T
*/
public <T> T findById(Object id, Class<T> claz) {
return cassandraTemplate.selectOneById(claz, id);
}
/**
* Delete the Entity using Id.
* @param id
* @param claz
*/
public <T> void deleteById(Object id, Class<T> claz) {
cassandraTemplate.deleteById(claz, id);
}
/**
* Delete the Entity using object.
* @param entity
*/
public void delete(Object entity) {
cassandraTemplate.delete(entity);
}
/**
* Deleting the list of entities
* @param entities
*/
public <T> void delete(List<T> entities) {
cassandraTemplate.delete(entities);
}
/**
* Deleting the all entities.
* @param claz
*/
public <T> void deleteAll(Class<T> claz) {
cassandraTemplate.deleteAll(claz);
}
/**
* Getting the all entities.
* @param claz
* @return List of entities
*/
public <T> List<T> findAll(Class<T> claz) {
return (List<T>) cassandraTemplate.selectAll(claz);
}
/**
* Getting the all entity values using specific id's data.
* @param ids
* @param claz
* @return
*/
public <T> List<T> findAll(List<Object> ids, Class<T> claz) {
return cassandraTemplate.selectBySimpleIds(claz, ids);
}
/**
* Getting the count of records.
* @param claz
* @return the count value.
*/
public <T> void truncate(Class<T> claz) {
cassandraTemplate.truncate(claz.getName());
}
/**
* Getting the count of records.
* @param claz
* @return the count value.
*/
public <T> long getCount(Class<T> claz) {
return cassandraTemplate.count(claz);
}
/**
* Checking the object exists or not.
* @param id
* @param claz
* @return true if the object exists in the database otherwise it will return false.
*/
public <T> boolean exists(Object id, Class<T> claz) {
return cassandraTemplate.exists(claz, id);
}
}
Employee entity:Employee.javapackage com.ranga.entity;
import org.springframework.data.cassandra.mapping.Column;
import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.Table;
/**
* Employee entity class.
*
* @author Ranga Reddy
* @version 1.0
*/
@Table("employee")
public class Employee {
@PrimaryKey("id")
private long id;
@Column("name")
private String name;
@Column
private int age;
@Column(value ="salary")
private float salary;
/**
* Default Constructor
*/
public Employee() {
super();
}
/**
* Parameterized Constructor
* @param id
* @param name
* @param age
* @param salary
*/
public Employee(long id, String name, int age, float salary) {
super();
this.id = id;
this.name = name;
this.age = age;
this.salary = salary;
}
/**
* @return the id
*/
public long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(long id) {
this.id = id;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the age
*/
public int getAge() {
return age;
}
/**
* @param age the age to set
*/
public void setAge(int age) {
this.age = age;
}
/**
* @return the salary
*/
public float getSalary() {
return salary;
}
/**
* @param salary the salary to set
*/
public void setSalary(float salary) {
this.salary = salary;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", age=" + age
+ ", salary=" + salary + "]";
}
}
Employee DAO & Impl classes;EmployeeDAO.java
package com.ranga.dao;
import java.util.List;
import com.ranga.entity.Employee;
/**
* DAO interface for Employee to perform CRUD operation.
* @author Ranga Reddy
* @version 1.0
*/
public interface EmployeeDAO {
/**
* Used to Create the Employee Information
* @param employee
* @return {@link Employee}
*/
public Employee createEmployee(Employee employee);
/**
* Getting the Employee Information using Id
* @param id
* @return {@link Employee}
*/
public Employee getEmployee(int id);
/**
* Used to Update the Employee Information
* @param employee
* @return {@link Employee}
*/
public Employee updateEmployee(Employee employee);
/**
* Deleting the Employee Information using Id
* @param id
*/
public void deleteEmployee(int id);
/**
* Getting the All Employees information
* @return
*/
public List<Employee> getAllEmployees();
}
EmployeeDAOImpl.java
/**
*
*/
package com.ranga.dao.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.ranga.dao.EmployeeDAO;
import com.ranga.entity.Employee;
import com.ranga.util.MyCassandraTemplate;
/**
* DAOImpl class for Employee to perform CRUD operation.
* @author Ranga Reddy
* @version 1.0
*/
@Repository
public class EmployeeDAOImpl implements EmployeeDAO {
@Autowired
private MyCassandraTemplate myCassandraTemplate;
@Override
public Employee createEmployee(Employee employee) {
return myCassandraTemplate.create(employee);
}
@Override
public Employee getEmployee(int id) {
return myCassandraTemplate.findById(id, Employee.class);
}
@Override
public Employee updateEmployee(Employee employee) {
return myCassandraTemplate.update(employee, Employee.class);
}
@Override
public void deleteEmployee(int id) {
myCassandraTemplate.deleteById(id, Employee.class);
}
@Override
public List<Employee> getAllEmployees() {
return myCassandraTemplate.findAll(Employee.class);
}
}
Employee Service & Impl classesEmployeeService.java
package com.ranga.service;
import java.util.List;
import com.ranga.entity.Employee;
/**
* Service interface for Employee to perform CRUD operation.
* @author Ranga Reddy
* @version 1.0
*/
public interface EmployeeService {
/**
* Used to Create the Employee Information
* @param employee
* @return {@link Employee}
*/
public Employee createEmployee(Employee employee);
/**
* Getting the Employee Information using Id
* @param id
* @return {@link Employee}
*/
public Employee getEmployee(int id);
/**
* Used to Update the Employee Information
* @param employee
* @return {@link Employee}
*/
public Employee updateEmployee(Employee employee);
/**
* Deleting the Employee Information using Id
* @param id
*/
public void deleteEmployee(int id);
/**
* Getting the All Employees information
* @return
*/
public List<Employee> getAllEmployees();
}
EmployeeServiceImpl.java
package com.ranga.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ranga.dao.EmployeeDAO;
import com.ranga.entity.Employee;
import com.ranga.service.EmployeeService;
/**
* Service Impl class for Employee to perform CRUD operation.
* @author Ranga Reddy
* @version 1.0
*/
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeDAO employeeDAO;
/**
* Default Constructor
*/
public EmployeeServiceImpl() {
super();
}
@Override
public Employee createEmployee(Employee employee) {
return employeeDAO.createEmployee(employee);
}
@Override
public Employee getEmployee(int id) {
return employeeDAO.getEmployee(id);
}
@Override
public Employee updateEmployee(Employee employee) {
return employeeDAO.updateEmployee(employee);
}
@Override
public void deleteEmployee(int id) {
employeeDAO.deleteEmployee(id);
}
@Override
public List<Employee> getAllEmployees() {
return employeeDAO.getAllEmployees();
}
}
Employee Rest Controller class:
EmployeeController.java
package com.ranga.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.ranga.entity.Employee;
import com.ranga.service.EmployeeService;
/**
* @author Ranga Reddy
* @version 1.0
* @since Aug 20, 2015
*/
@RestController
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
public EmployeeController() {
System.out.println("EmployeeController()");
}
@RequestMapping(value = "/employee", method = RequestMethod.POST)
Employee create(@RequestBody Employee employee) {
return employeeService.createEmployee(employee);
}
@RequestMapping(value = "/employee/{id}", method = RequestMethod.DELETE)
void delete(@PathVariable("id") int id) {
employeeService.deleteEmployee(id);
}
@RequestMapping(value="/employee", method = RequestMethod.GET)
List<Employee> findAll() {
return employeeService.getAllEmployees();
}
@RequestMapping(value = "/employee/{id}", method = RequestMethod.GET)
Employee findById(@PathVariable("id") int id) {
return employeeService.getEmployee(id);
}
@RequestMapping(value = "/employee", method = RequestMethod.PUT)
Employee update(@RequestBody Employee employee) {
return employeeService.updateEmployee(employee);
}
}
Spring Boot Application class:
Application.java
package com.ranga.main;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
/**
* Main application to run boot application.
*
* @author Ranga Reddy
* @version 1.0
*/
@SpringBootApplication
@ComponentScan(basePackages="com.ranga")
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
Run the Application.java file.
For testing purpose, i used SOAP UI
Reading All:
Creating:
Reading Specific:
Updating:
Deleting: