Signup/Sign In
PUBLISHED ON: JANUARY 18, 2021

Spring REST CRUD Application

In this article, we are going to create a CRUD(Create Read Update and Delete) Spring application. This application uses the REST(REpresentational State Transfer) approach to perform CRUD operations. It uses @RestController annotation to create a controller that handles requests and sends the response back in JSON format.

REST is an architectural style that contains a set of constraints to create web services. You can refer to our article on REST API. We can perform CRUD operations with this approach as well. Let's understand by example and create a maven based project that contains several files and the structure looks like below.

Project Structure

// DemoAppConfig.java

This is a configuration file in Java which is an alternate of the applicationContext.xml file that we created for the XML-based configuration example. The @Configuration annotation indicates that this is not a simple class but a configuration class and the @ComponentScan annotation is used to indicate the component location in our spring project.

The @PropertySource annotation is used to read the property file. Here, we have set database configuration and session factory to work with the database.

 package com.studytonight.springdemo.config; import java.beans.PropertyVetoException; import java.util.Properties; import java.util.logging.Logger; import javax.sql.DataSource; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; import org.springframework.orm.hibernate5.HibernateTransactionManager; import org.springframework.orm.hibernate5.LocalSessionFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.view.InternalResourceViewResolver; import com.mchange.v2.c3p0.ComboPooledDataSource; @Configuration @EnableWebMvc @EnableTransactionManagement @ComponentScan("com.studytonight.springdemo") @PropertySource({ "classpath:persistence-mysql.properties" }) public class DemoAppConfig implements WebMvcConfigurer {	@Autowired	private Environment env;	private Logger logger = Logger.getLogger(getClass().getName());	// define a bean for ViewResolver	@Bean	public DataSource myDataSource() {	ComboPooledDataSource myDataSource = new ComboPooledDataSource();	try {	myDataSource.setDriverClass("com.mysql.jdbc.Driver");	}	catch (PropertyVetoException exc) {	throw new RuntimeException(exc);	}	logger.info("jdbc.url=" + env.getProperty("jdbc.url"));	logger.info("jdbc.user=" + env.getProperty("jdbc.user"));	myDataSource.setJdbcUrl(env.getProperty("jdbc.url"));	myDataSource.setUser(env.getProperty("jdbc.user"));	myDataSource.setPassword(env.getProperty("jdbc.password"));	myDataSource.setInitialPoolSize(getIntProperty("connection.pool.initialPoolSize"));	myDataSource.setMinPoolSize(getIntProperty("connection.pool.minPoolSize"));	myDataSource.setMaxPoolSize(getIntProperty("connection.pool.maxPoolSize"));	myDataSource.setMaxIdleTime(getIntProperty("connection.pool.maxIdleTime"));	return myDataSource;	}	private Properties getHibernateProperties() {	// set hibernate properties	Properties props = new Properties();	props.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));	props.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));	return props;	}	private int getIntProperty(String propName) {	String propVal = env.getProperty(propName);	int intPropVal = Integer.parseInt(propVal);	return intPropVal;	}	@Bean	public LocalSessionFactoryBean sessionFactory(){	LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();	sessionFactory.setDataSource(myDataSource());	sessionFactory.setPackagesToScan(env.getProperty("hibernate.packagesToScan"));	sessionFactory.setHibernateProperties(getHibernateProperties());	return sessionFactory;	}	@Bean	@Autowired	public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {	HibernateTransactionManager txManager = new HibernateTransactionManager();	txManager.setSessionFactory(sessionFactory);	return txManager;	} }

// MySpringMvcDispatcherServletInitializer.java

This is the servlet dispatcher initializer class that reads configurations from the DemoAppConfig file and starts the application.

 package com.studytonight.springdemo.config; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class MySpringMvcDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {	@Override	protected Class<?>[] getRootConfigClasses() {	return null;	}	@Override	protected Class<?>[] getServletConfigClasses() {	return new Class[] { DemoAppConfig.class };	}	@Override	protected String[] getServletMappings() {	return new String[] { "/" };	} }

// CustomerDAO.java

This is a DAO(Data Access Object) interface that contains a couple of methods to get implemented in the implementation class.

 package com.studytonight.springdemo.dao; import java.util.List; import com.studytonight.springdemo.entity.Customer; public interface CustomerDAO {	public List<Customer> getCustomers();	public void saveCustomer(Customer theCustomer);	public Customer getCustomer(int theId);	public void deleteCustomer(int theId); } 

// CustomerDAOImpl.java

This is a DAO(Data Access Object) implementation class that implements the CutomerDAO interface and implements its methods.

 package com.studytonight.springdemo.dao; import java.util.List; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.query.Query; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import com.studytonight.springdemo.entity.Customer; @Repository public class CustomerDAOImpl implements CustomerDAO {	@Autowired	private SessionFactory sessionFactory;	@Override	public List<Customer> getCustomers() {	Session currentSession = sessionFactory.getCurrentSession();	Query<Customer> theQuery =	currentSession.createQuery("from Customer order by lastName",	Customer.class);	List<Customer> customers = theQuery.getResultList();	return customers;	}	@Override	public void saveCustomer(Customer theCustomer) {	Session currentSession = sessionFactory.getCurrentSession();	currentSession.saveOrUpdate(theCustomer);	}	@Override	public Customer getCustomer(int theId) {	Session currentSession = sessionFactory.getCurrentSession();	Customer theCustomer = currentSession.get(Customer.class, theId);	return theCustomer;	}	@Override	public void deleteCustomer(int theId) {	Session currentSession = sessionFactory.getCurrentSession();	Query theQuery =	currentSession.createQuery("delete from Customer where id=:customerId");	theQuery.setParameter("customerId", theId);	theQuery.executeUpdate();	} }

// Customer.java

It is an Entity class used to represent Customer details.

 package com.studytonight.springdemo.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="customer") public class Customer {	@Id	@GeneratedValue(strategy=GenerationType.IDENTITY)	@Column(name="id")	private int id;	@Column(name="first_name")	private String firstName;	@Column(name="last_name")	private String lastName;	@Column(name="email")	private String email;	public Customer() {	}	public int getId() {	return id;	}	public void setId(int id) {	this.id = id;	}	public String getFirstName() {	return firstName;	}	public void setFirstName(String firstName) {	this.firstName = firstName;	}	public String getLastName() {	return lastName;	}	public void setLastName(String lastName) {	this.lastName = lastName;	}	public String getEmail() {	return email;	}	public void setEmail(String email) {	this.email = email;	}	@Override	public String toString() {	return "Customer [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + "]";	} } 

// CustomerRestController.java

This is our controller class that is marked with @RestController and performs CRUD operations. It returns the output in JSON format to the user.

 package com.studytonight.springdemo.rest; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; 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.RestController; import com.studytonight.springdemo.entity.Customer; import com.studytonight.springdemo.service.CustomerService; @RestController public class CustomerRestController {	@Autowired	private CustomerService customerService;	@GetMapping("/customers")	public List<Customer> getCustomers(){	return customerService.getCustomers();	}	@GetMapping("/customers/{customerId}")	public Customer getCustomer(@PathVariable int customerId){	return customerService.getCustomer(customerId);	}	@PostMapping("/customers")	public Customer addCustomer(@RequestBody Customer customer){	customer.setId(0);	customerService.saveCustomer(customer);	return customer;	}	@PutMapping("/customers")	public Customer updateCustomer(@RequestBody Customer customer){	customerService.saveCustomer(customer);	return customer;	}	@DeleteMapping("/customers/{customerId}")	public String deleteCustomer(@PathVariable int customerId){	customerService.deleteCustomer(customerId);	return "Deleted Customer Id: "+customerId;	} }

// CustomerService.java

 package com.studytonight.springdemo.service; import java.util.List; import com.studytonight.springdemo.entity.Customer; public interface CustomerService {	public List<Customer> getCustomers();	public void saveCustomer(Customer theCustomer);	public Customer getCustomer(int theId);	public void deleteCustomer(int theId); } 

// CustomerServiceImpl.java

 package com.studytonight.springdemo.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.studytonight.springdemo.dao.CustomerDAO; import com.studytonight.springdemo.entity.Customer; @Service public class CustomerServiceImpl implements CustomerService {	// need to inject customer dao	@Autowired	private CustomerDAO customerDAO;	@Override	@Transactional	public List<Customer> getCustomers() {	return customerDAO.getCustomers();	}	@Override	@Transactional	public void saveCustomer(Customer theCustomer) {	customerDAO.saveCustomer(theCustomer);	}	@Override	@Transactional	public Customer getCustomer(int theId) {	return customerDAO.getCustomer(theId);	}	@Override	@Transactional	public void deleteCustomer(int theId) {	customerDAO.deleteCustomer(theId);	} } 

// persistence-mysql.properties

This is a property file that contains database related configurations and is accessed in the config file using the @PropertySource annotation.

 # # JDBC connection properties # jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/springwithdb?useSSL=false jdbc.user=user_name jdbc.password=user_password # # Connection pool properties # connection.pool.initialPoolSize=5 connection.pool.minPoolSize=5 connection.pool.maxPoolSize=20 connection.pool.maxIdleTime=3000 # # Hibernate properties # hibernate.dialect=org.hibernate.dialect.MySQLDialect hibernate.show_sql=true hibernate.packagesToScan=com.studytonight.springdemo.entity

Run the Application

After successfully completing the project and adding the dependencies run the application using the server and you will get the output as below.

To test the application, we used a Postman application. It is a good application to check web requests. You can install it from the official site and then use it.

Access All the Customers

Add New Customer

Show all Customers after Adding new Customer

Fetch Single Customer



About the author:
I am a Java developer by profession and Java content creator by passion. I have over 5 years of experience in Java development and content writing. I like writing about Java, related frameworks, Spring, Springboot, etc.