In this post, we are going to learn how to implement RESTful web services using Spring Boot and Cassandra db.
Project Structure:
Tools & Technologies:
pom.xml
Configuring the Cassandra DB properties
src/main/resources/cassandra.properties
CassandraUtil.java
Employee.java
EmployeeDAO.java
EmployeeService.java
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'};Maven Configuration
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
pom.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 properties
src/main/resources/cassandra.properties
cassandra.contactpoints=localhost,127.0.0.1Utility class for Cassandra db operations:
cassandra.port=9042
cassandra.keyspace=ranga
CassandraUtil.java
package com.ranga.util;MyCassandraTemplate.java
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());
}
}
package com.ranga.util;Employee entity:
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.java
package com.ranga.entity;Employee DAO & Impl classes;
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 + "]";
}
}
EmployeeDAO.java
package com.ranga.dao;EmployeeDAOImpl.java
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();
}
/**Employee Service & Impl classes
*
*/
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);
}
}
EmployeeService.java
package com.ranga.service;EmployeeServiceImpl.java
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();
}
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.javapackage 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:
5 comments:
Very nice post, Ranga Reddy!
I have similar requirement with the spring-boot and cassandra. I am trying to build an application with the following requirement...
1. A data model to maintain inventory supply and demand records.
2. RESTful API, which reads supply, demand and calculates inventory supply and demand.
How can I build the data model for this scenario? Can you please help me in this regard?
Thanks in advance!!
You are the best!!!
Very nice article for beginners.
It is giving me a whole list of errors with this as the common factor:
nested exception is com.datastax.driver.core.exceptions.NoHostAvailableException: All host(s) tried for query failed (tried: /54.200.224.46:9042 (com.datastax.driver.core.ConnectionException: [/54.200.224.46:9042] Unexpected error during transport initialization (com.datastax.driver.core.TransportException: [/54.200.224.46:9042] Connection has been closed)))
Any idea what is wrong?
Thanks for sharing Cassandra details are very nice & you are deeply info about API using Spring Boot and Cassandra related much better.
Post a Comment