Posted In: Java Script, React, Spring, Spring REST

React 15 + Spring 5 + JDBC + REST + Maven – Complexity level 2

Technologies used

Maven 4.0.0
Spring 5.0.0.M4
React 15
Eclipse Neon
JDK 1.8
Log4j 2.7
jackson-core 2.8.6
jackson-databind 2.8.6
Firefox rest add-on for testing

In this example we will create simple Spring Rest services. This services will do simple CRUD operations. Then we will create simple UI grid using React, jQuery and Bootstrap.

Let us create services to do CRUD operations for employee.

Employee has following attributes

Employee ID
First Name
Last Name
Email ID
Date of birth
Hire date

Rest service end points will look like this

/service/employee/list method=POST
/service/employee/{employeeId} method=GET
/service/employee method=POST
/service/employee method=PUT
/service/employee method=DELETE

Either

Download example source and eclipse project

or create maven project from scratch

Create Maven project

Tomcat Datasource configuration

<Resource name="jdbc/javausecase_mysqldb" 
auth="Container" type="javax.sql.DataSource"
maxTotal="50" maxIdle="30" maxWaitMillis="10000"
username="root" password="pasword"
driverClassName="com.mysql.jdbc.Driver" 
url="jdbc:mysql://localhost:3306/javausecase_db"/>

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.javausecase</groupId>
	<artifactId>Example201712</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<dependencies>
		<dependency>
			<groupId>javax</groupId>
			<artifactId>javaee-api</artifactId>
			<version>7.0</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>5.0.0.M4</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>5.0.0.M4</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>5.0.0.M4</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>5.0.0.M4</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>5.0.0.M4</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>5.0.0.M4</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>5.0.0.M4</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>5.0.0.M4</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>5.0.0.M4</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>4.2.1.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.batch</groupId>
			<artifactId>spring-batch-core</artifactId>
			<version>3.0.7.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.integration</groupId>
			<artifactId>spring-integration-core</artifactId>
			<version>4.3.6.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.kafka</groupId>
			<artifactId>spring-kafka</artifactId>
			<version>1.1.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.session</groupId>
			<artifactId>spring-session</artifactId>
			<version>1.3.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-api</artifactId>
			<version>2.7</version>
		</dependency>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-core</artifactId>
			<version>2.7</version>
		</dependency>
		<dependency>
			<groupId>commons-beanutils</groupId>
			<artifactId>commons-beanutils</artifactId>
			<version>1.9.3</version>
		</dependency>
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-dbcp2</artifactId>
			<version>2.1.1</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.5</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>6.0.5</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate.javax.persistence</groupId>
			<artifactId>hibernate-jpa-2.1-api</artifactId>
			<version>1.0.0.Final</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>5.2.6.Final</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-core</artifactId>
			<version>2.8.6</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.8.6</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-annotations</artifactId>
			<version>2.8.6</version>
		</dependency>
		<dependency>
			<groupId>net.sf.json-lib</groupId>
			<artifactId>json-lib</artifactId>
			<version>2.4</version>
			<classifier>jdk15</classifier>
		</dependency>
	</dependencies>
	<repositories>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/libs-milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>
	<build>
		<finalName>Example201712</finalName>
	</build>
	<properties>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
		<failOnMissingWebXml>false</failOnMissingWebXml>
	</properties>
</project>

Steps – Rest services

1. Create Employee table
2. Add spring details to web.xml
3. Add spring details to application context.xml. Add component scan and conerters.
4. Create beans through annotations
5. Create Employee object
6. Create Spring Rest services
7. Create Spring Rest services
8. Call DAO to do CRUD operations

Steps – React UI

1. Create index.jsp to load react, jquery, bootstrap and application js files
2. Create app.js and write following React classes
3. Create App class which will be the starting point and add to ReactDOM.render
4. Create EmployeeTable (Grid) class to display Employee table header. Also create insert row in this class.
5. Call EmployeeTable from App class and pass list of employees to it. Access it using this.props in EmployeeTable.
6. Create Employee class to display employee
7. Create handleChange(eventfunction to make text boxes editable.
8. Call AJAX functions and use REST services

CREATE TABLE EMPLOYEE (
   EMPLOYEE_ID INT(10) AUTO_INCREMENT,
   FIRST_NM VARCHAR(50),
   LAST_NM VARCHAR(50),
   EMAIL_ID  VARCHAR(50),
   DT_OF_BIRTH DATE,
   HIRE_DT DATE,
   PRIMARY KEY( EMPLOYEE_ID )
);
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
		 http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	version="3.1">
	<display-name>Employee Web</display-name>
	<context-param>
		<param-name>contextClass</param-name>
		<param-value>
      	org.springframework.web.context.support.AnnotationConfigWebApplicationContext
      </param-value>
	</context-param>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>com.company.springapp.EmployeeServiceAppCtx</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
  <servlet>
    <display-name>springapp</display-name>
    <servlet-name>springapp</servlet-name>
    <servlet-class>
      org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>springapp</servlet-name>
	<url-pattern>/service/*</url-pattern>
  </servlet-mapping>
</web-app>

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">

	<context:component-scan base-package="com.company.springapp" />
	<bean
		class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
		<!-- NOTE: it is important to specify the order property, so this adapter 
			will be attempted before the HandlerAdapter that Spring MVC automatically 
			configures. This is because a MappingJacksonHttpMessageConverter is registered 
			automatically with the default adapter that will attempt to handle any Java 
			object including BufferedImage. -->
		<property name="order" value="1" />
		<property name="messageConverters">
			<list>
				<!-- Default converters -->
				<bean
					class="org.springframework.http.converter.StringHttpMessageConverter" />
				<bean class="org.springframework.http.converter.FormHttpMessageConverter" />
				<bean
					class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
				<bean
					class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />

				<!-- Converter for images -->
				<bean
					class="org.springframework.http.converter.BufferedImageHttpMessageConverter" />

				<!-- This must come after our image converter -->
				<bean
					class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
			</list>
		</property>
	</bean>
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix">
			<value>/WEB-INF/public/</value>
		</property>
		<property name="suffix">
			<value>.jsp</value>
		</property>
	</bean>
</beans>
package com.company.springapp;

import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaDialect;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

@Configuration
@ImportResource("WEB-INF/beans.xml")
public class EmployeeWebAppCtx {
	@Autowired
	private Environment environment;

	@Bean
	public DataSource dataSource() throws NamingException {
		Context initialContext = new InitialContext();
		try {
			return (DataSource) initialContext.lookup(
			        "java:comp/env/jdbc/javausecase_mysqldb");
		} catch (NamingException nm1) {
			nm1.printStackTrace();
			return null;
		}
	}

	@Bean
	public PlatformTransactionManager transactionManager()
	        throws NamingException {
		DataSource dataSource = dataSource();
		JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
		jpaTransactionManager.setDataSource(dataSource);
		jpaTransactionManager
		        .setEntityManagerFactory(entityManagerFactory());
		jpaTransactionManager
		        .setJpaDialect(hibernateJpaDialect());
		return jpaTransactionManager;
	}

	@Bean
	public NamedParameterJdbcTemplate namedParameterTemplate(
	        DataSource dataSource) {
		return new NamedParameterJdbcTemplate(dataSource);
	}

	@Bean
	public JdbcTemplate jdbcTemplate(DataSource dataSource) {
		return new JdbcTemplate(dataSource);
	}

	@Bean
	public HibernateJpaDialect hibernateJpaDialect() {
		return new HibernateJpaDialect();
	}

	@Bean
	public EntityManagerFactory entityManagerFactory()
	        throws NamingException {
		final LocalContainerEntityManagerFactoryBean em = 
				new LocalContainerEntityManagerFactoryBean();
		em.setDataSource(dataSource());

		em.setJpaDialect(hibernateJpaDialect());
		em.setPackagesToScan(environment.getProperty(
		        "jpa.packages", "com.company.springapp.entity"));
		em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());

		Properties hibernateProperties = new Properties();
		hibernateProperties.put("hibernate.show_sql", true);
		hibernateProperties.put("hibernate.dialect",
		        "org.hibernate.dialect.MySQLDialect");
		em.setJpaProperties(hibernateProperties);
		em.setPersistenceUnitName("employeeService");
		em.afterPropertiesSet();

		return em.getObject();
	}
}

package com.company.springapp;

import java.io.Serializable;
import java.util.Date;

public class Employee implements Serializable {
	private static final long serialVersionUID = -8404866163724033028L;
	private int employeeId;
	private String firstName;
	private String lastName;
	private String emailId;
	private Date dateofBirth;
	private Date hireDate;
	public int getEmployeeId() {
		return employeeId;
	}
	public void setEmployeeId(int employeeId) {
		this.employeeId = employeeId;
	}
	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 Date getDateofBirth() {
		return dateofBirth;
	}
	public void setDateofBirth(Date dateofBirth) {
		this.dateofBirth = dateofBirth;
	}
	public Date getHireDate() {
		return hireDate;
	}
	public void setHireDate(Date hireDate) {
		this.hireDate = hireDate;
	}
	public String getEmailId() {
		return emailId;
	}
	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}
	@Override
	public String toString() {
		return "Employee [employeeId=" + employeeId + ", firstName="
		        + firstName + ", lastName=" + lastName + ", emailId="
		        + emailId + ", dateofBirth=" + dateofBirth
		        + ", hireDate=" + hireDate + "]";
	}
}
package com.company.springapp;

import java.util.ArrayList;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
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.ResponseBody;

import com.fasterxml.jackson.databind.ObjectMapper;

import net.sf.json.JSONObject;

@Controller
public class EmployeeService {
	private static final Logger LOGGER = LogManager
	        .getLogger(EmployeeService.class);
	@Autowired
	private EmployeeDao employeeDao;

	@RequestMapping(value = "/employee/list",
	        method = { RequestMethod.POST })
	public @ResponseBody Object getEmployeeList(
	        ServletRequest req, ServletResponse res,
	        @RequestBody String requestJson)
	        throws EmployeeException {
		LOGGER.debug("inside list()");
		ArrayList<Employee> employeeList = null;
		try {
			employeeList = employeeDao.list();
		} catch (EmployeeException e) {
			LOGGER.error(e, e);
			throw e;
		} catch (Exception e) {
			LOGGER.error(e, e);
		}
		return employeeList;
	}

	@RequestMapping(value = "/employee/{employeeId}",
	        method = { RequestMethod.GET })
	public @ResponseBody Object getEmployee(ServletRequest req,
	        ServletResponse res,
	        @PathVariable("employeeId") int employeeId)
	        throws EmployeeException {
		LOGGER.debug("inside get()");
		Employee employee = null;
		Employee param = new Employee();
		try {
			param.setEmployeeId(employeeId);
			employee = employeeDao.get(param);
		} catch (EmployeeException e) {
			LOGGER.error(e, e);
			throw e;
		} catch (Exception e) {
			LOGGER.error(e, e);
		}
		return employee;
	}

	@RequestMapping(value = "/employee",
	        produces = "application/json",
	        consumes = "application/json",
	        method = { RequestMethod.POST })
	public @ResponseBody Object insertEmployee(
	        ServletRequest req, ServletResponse res,
	        @RequestBody String requestJson)
	        throws EmployeeException {
		LOGGER.debug("inside insertEmployee()");
		LOGGER.debug(requestJson);

		try {
			Employee employee = new ObjectMapper()
			        .readValue(requestJson, Employee.class);
			LOGGER.debug("insert() employee=" + employee);
			employeeDao.insert(employee);
		} catch (EmployeeException e) {
			LOGGER.error(e, e);
			throw e;
		} catch (Exception e) {
			LOGGER.error(e, e);
		}
		return JSONObject.fromObject("{'response' : 'success'}");
	}

	@RequestMapping(value = "/employee",
	        produces = "application/json",
	        consumes = "application/json",
	        method = { RequestMethod.PUT })
	public @ResponseBody Object updateEmployee(
	        ServletRequest req, ServletResponse res,
	        @RequestBody String requestJson)
	        throws EmployeeException {
		LOGGER.debug("inside updateEmployee()");

		try {
			Employee employee = new ObjectMapper()
			        .readValue(requestJson, Employee.class);
			LOGGER.debug("update() employee=" + employee);
			employeeDao.update(employee);
		} catch (EmployeeException e) {
			LOGGER.error(e, e);
			throw e;
		} catch (Exception e) {
			LOGGER.error(e, e);
		}
		return JSONObject.fromObject("{'response' : 'success'}");
	}

	@RequestMapping(value = "/employee",
	        produces = "application/json",
	        consumes = "application/json",
	        method = { RequestMethod.DELETE })
	public @ResponseBody Object deleteEmployee(
	        ServletRequest req, ServletResponse res,
	        @RequestBody String requestJson)
	        throws EmployeeException {
		LOGGER.debug("inside delete()");

		try {
			Employee employee = new ObjectMapper()
			        .readValue(requestJson, Employee.class);
			LOGGER.debug("delete() employee=" + employee);
			employeeDao.delete(employee);
		} catch (EmployeeException e) {
			LOGGER.error(e, e);
			throw e;
		} catch (Exception e) {
			LOGGER.error(e, e);
		}
		return JSONObject.fromObject("{'response' : 'success'}");
	}

	@RequestMapping(value = "/public/*",
	        method = { RequestMethod.GET, RequestMethod.POST })
	public String jspController(ServletRequest req,
	        ServletResponse res) throws Exception {
		LOGGER.debug("inside jspController() start");
		String model = "index";
		return model;
	}

}

package com.company.springapp;

import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Component;

@Component
public class EmployeeDaoImpl implements EmployeeDao {
	private static final Logger LOGGER = LogManager
	        .getLogger(EmployeeDaoImpl.class);

	@Autowired
	private NamedParameterJdbcTemplate namedParameterTemplate;

	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Override
	public ArrayList<Employee> list() throws Exception {
		final ArrayList<Employee> employeeList = new ArrayList<Employee>();
		Map<String, Object> paramsMap = new HashMap<String, Object>();
		String sql = "SELECT EMPLOYEE_ID, FIRST_NM, LAST_NM, DT_OF_BIRTH, "
		        + "EMAIL_ID, HIRE_DT " + "FROM EMPLOYEE";
		try {
			namedParameterTemplate.query(sql, paramsMap,
			        new ResultSetExtractor<List<Employee>>() {
				        @Override
				        public List<Employee> extractData(
				                ResultSet rs) throws SQLException {
					        while (rs.next()) {
						        Employee employee = new Employee();
						        employee.setEmployeeId(
						                rs.getInt("EMPLOYEE_ID"));
						        employee.setFirstName(
						                rs.getString("FIRST_NM"));
						        employee.setLastName(
						                rs.getString("LAST_NM"));
						        employee.setDateofBirth(
						                rs.getDate("DT_OF_BIRTH"));
						        employee.setEmailId(
						                rs.getString("EMAIL_ID"));
						        employee.setHireDate(
						                rs.getDate("HIRE_DT"));
						        employeeList.add(employee);
					        }
					        return employeeList;
				        }
			        });
		} catch (Exception e) {
			throw e;
		}
		LOGGER.debug(employeeList);
		return employeeList;
	}

	@Override
	public Employee get(Employee param) throws Exception {
		final Employee employee = new Employee();
		Map<String, Object> paramsMap = new HashMap<String, Object>();
		String sql = "SELECT EMPLOYEE_ID, FIRST_NM, LAST_NM, DT_OF_BIRTH, "
		        + "EMAIL_ID, HIRE_DT " + "FROM EMPLOYEE "
		        + "WHERE EMPLOYEE_ID = :EMPLOYEE_ID ";
		paramsMap.put("EMPLOYEE_ID", param.getEmployeeId());

		try {
			namedParameterTemplate.query(sql, paramsMap,
			        new ResultSetExtractor<Employee>() {
				        @Override
				        public Employee extractData(ResultSet rs)
				                throws SQLException {
					        while (rs.next()) {
						        employee.setEmployeeId(
						                rs.getInt("EMPLOYEE_ID"));
						        employee.setFirstName(
						                rs.getString("FIRST_NM"));
						        employee.setLastName(
						                rs.getString("LAST_NM"));
						        employee.setDateofBirth(
						                rs.getDate("DT_OF_BIRTH"));
						        employee.setEmailId(
						                rs.getString("EMAIL_ID"));
						        employee.setHireDate(
						                rs.getDate("HIRE_DT"));
					        }
					        return employee;
				        }
			        });
		} catch (Exception e) {
			throw e;
		}
		LOGGER.debug(employee);
		return employee;
	}

	@Override
	public void insert(Employee param) throws Exception {
		String sql = "INSERT INTO EMPLOYEE "
		        + "(FIRST_NM, LAST_NM, DT_OF_BIRTH, HIRE_DT, EMAIL_ID) "
		        + "VALUES " + "(?,?,?,?,?)";
		int recordsInserted = jdbcTemplate.update(sql,
		        new PreparedStatementSetter() {
			        public void setValues(PreparedStatement ps)
			                throws SQLException {
				        ps.setString(1, param.getFirstName());
				        ps.setString(2, param.getLastName());
				        ps.setDate(3, new Date(
				                param.getDateofBirth().getTime()));
				        ps.setDate(4, new Date(
				                param.getHireDate().getTime()));
				        ps.setString(5, param.getEmailId());
			        }
		        });
		LOGGER.debug("recordsInserted=" + recordsInserted);
	}

	@Override
	public void update(Employee param) throws Exception {
		String sql = "UPDATE EMPLOYEE SET "
		        + "FIRST_NM = ?, LAST_NM = ?, "
		        + "DT_OF_BIRTH = ?, HIRE_DT = ?, " + "EMAIL_ID = ? "
		        + "WHERE EMPLOYEE_ID = ?";
		int recordsUpated = jdbcTemplate.update(sql,
		        new PreparedStatementSetter() {
			        public void setValues(PreparedStatement ps)
			                throws SQLException {
				        ps.setString(1, param.getFirstName());
				        ps.setString(2, param.getLastName());
				        ps.setDate(3, new Date(
				                param.getDateofBirth().getTime()));
				        ps.setDate(4, new Date(
				                param.getHireDate().getTime()));
				        ps.setString(5, param.getEmailId());
				        ps.setInt(6, param.getEmployeeId());
			        }
		        });
		LOGGER.debug("recordsUpated=" + recordsUpated);
	}

	@Override
	public void delete(Employee param) throws Exception {
		String sql = "DELETE FROM EMPLOYEE WHERE EMPLOYEE_ID = ?";
		int recordsDeleted = jdbcTemplate.update(sql,
		        new PreparedStatementSetter() {
			        public void setValues(PreparedStatement ps)
			                throws SQLException {
				        ps.setInt(1, param.getEmployeeId());
			        }
		        });
		LOGGER.debug("recordsDeleted=" + recordsDeleted);
	}
}

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">

<head>
    <title>React 15 + Spring 5 + REST</title>
</head>

<body>

    <div class='container'>
        <div id='root'></div>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react.min.js"></script>
    <script src="https://fb.me/react-dom-15.0.1.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.3/toastr.min.js"></script>

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.3/toastr.min.css"/>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"/>

    <script type="text/babel" src="<%=request.getContextPath()%>/public/app.js"></script>

</body>

</html>
var Employee = React.createClass({

    getInitialState: function() {
        this.handleChange = this.handleChange.bind(this);
        return {display: true,employee: this.props.employee };
    },
    handleDelete(employeeIdDelete) {
        var self = this;
        var formData = {
                "employeeId": employeeIdDelete
        };
        console.log('handleDelete().......................');
        // console.log(this.props);

        $.ajax({
            url: "http://localhost:83/Example201712/service/employee",
            type: 'DELETE',
            contentType: 'application/json',
            dataType: 'json',
            data: JSON.stringify(formData),
            success: function(data) {
                self.setState({display: false});
            },
            error: function(xhr, ajaxOptions, thrownError) {
                toastr.error(xhr.responseJSON.message);
            }
        });
    },
    handleUpdate(employeeIdUpdate) {
        var self = this;
        console.log('handleUpdate().......................');
        // console.log(this.state.employee);
        $.ajax({
            url: "http://localhost:83/Example201712/service/employee",
            type: 'PUT',
            contentType: 'application/json',
            dataType: 'json',
            data: JSON.stringify(this.state.employee),
            success: function(result) {
            },
            error: function(xhr, ajaxOptions, thrownError) {
                toastr.error(xhr.responseJSON.message);
            }
        });
    },
    handleChange(event) {
        // console.log(event);
        // console.log(event.target.name);
        var employee = this.state.employee;
        if(event.target.name == 'firstName') {
            employee.firstName = event.target.value;
        } else if(event.target.name == 'lastName') {
            employee.lastName = event.target.value;
        } else if(event.target.name == 'emailId') {
            employee.emailId = event.target.value;
        } else if(event.target.name == 'dateofBirth') {
            employee.dateofBirth = event.target.value;
        } else if(event.target.name == 'hireDate') {
            employee.hireDate = event.target.value;
        } 
        this.setState({employee: employee});
    },  
    render: function() {

        if (this.state.display==false) return null;
        else return (
             <tr>
                <td>{this.state.employee.employeeId}
                </td>
                <td>
                    <input type='text' name='firstName' id='firstName' value={this.state.employee.firstName} 
                    class="form-control InputField" maxlength="100" placeholder="First Name" onChange={this.handleChange} />
                </td>
                <td>
                    <input type='text' name='lastName' id='lastName' value={this.state.employee.lastName} 
                    class="form-control InputField" maxlength="100" placeholder="Last Name"  />
                </td>
                <td>
                    <input type='text' name='emailId' id='emailId' value={this.state.employee.emailId} 
                    class="form-control InputField" maxlength="100" placeholder="Email ID"  />
                </td>
                <td>
                    <input type='text' name='dateofBirth' id='dateofBirth' value={this.state.employee.dateofBirth} 
                    class="form-control InputField" maxlength="100" placeholder="Date of Birth"  />
                </td>
                <td>
                    <input type='text' name='hireDate' id='hireDate' value={this.state.employee.hireDate} 
                    class="form-control InputField" maxlength="100" placeholder="Hire Date"  />
                </td>
                <td>
                    <button className="btn btn-info" 
                    onClick={() => this.handleUpdate(this.state.employee.employeeId)}>
                    Update : ID {this.state.employee.employeeId}</button>
                </td>
                <td>
                    <button className="btn btn-info" 
                    onClick={() => this.handleDelete(this.state.employee.employeeId)}>
                    Delete : ID {this.state.employee.employeeId}</button>
                </td>
            </tr>
        );
    }
});


var EmployeeTable = React.createClass({
    handleSubmit(event) {
        event.preventDefault();
    },
    getInitialState: function() {
        var employeeObj = {
                "employeeId": ""
        };
        return {employee : employeeObj};
    },
    handleChange(event) {
        var employee = this.state.employee;
        if(event.target.name == 'firstNameIns') {
            employee.firstName = event.target.value;
        } else if(event.target.name == 'lastNameIns') {
            employee.lastName = event.target.value;
        } else if(event.target.name == 'emailIdIns') {
            employee.emailId = event.target.value;
        } else if(event.target.name == 'dateofBirthIns') {
            employee.dateofBirth = event.target.value;
        } else if(event.target.name == 'hireDateIns') {
            employee.hireDate = event.target.value;
        } 
        this.setState({employee: employee});
    },  
    handleInsert() {
        var self = this;
        console.log('handleInsert().......................');
        // console.log(this.state.employee);
        // console.log(JSON.stringify(this.state.employee));
        $.ajax({
            url: 'http://localhost:83/Example201712/service/employee',
            type: 'POST',
            contentType: 'application/json',
            dataType: 'json',
            data: JSON.stringify(this.state.employee),
            success: function(result) {
                self.props.handleGridRefresh();
            },
            error: function(xhr, ajaxOptions, thrownError) {
                toastr.error(xhr.responseJSON.message);
            }
        });
    },
    render: function() {

        var rows = [];
        this.props.employees.forEach(function(employee) {
            rows.push(
                    <Employee employee={employee} key={employee.employeeId} />);
        });

        return (
                <form onSubmit={this.handleSubmit}>
                <table className="table table-striped">
                    <thead>
                        <tr>
                            <th>Employee ID</th>
                            <th>First Name</th>
                            <th>Last Name</th>
                            <th>Email ID</th>
                            <th>Date of Birth</th>
                            <th>Hire Date</th>
                            <th>Action</th>
                            <th>Action</th>
                        </tr>
                    </thead>
                    <tbody>{rows}

                        <tr>
                            <td>
                            &nbsp;
                            </td>
                            <td>
                                <input type='text' name='firstNameIns' id='firstNameIns' 
                                value={this.state.employee.firstName} class="form-control InputField" 
                                maxlength="100" placeholder="First Name" onChange={this.handleChange}/>
                            </td>
                            <td>
                                <input type='text' name='lastNameIns' id='lastNameIns' 
                                value={this.state.employee.lastName} class="form-control InputField" 
                                maxlength="100" placeholder="Last Name" onChange={this.handleChange}/>
                            </td>
                            <td>
                                <input type='text' name='emailIdIns' id='emailIdIns' 
                                value={this.state.employee.emailId} class="form-control InputField" 
                                maxlength="100" placeholder="Email ID" onChange={this.handleChange}/>
                            </td>
                            <td>
                                <input type='text' name='dateofBirthIns' id='dateofBirthIns' 
                                value={this.state.employee.dateofBirth} class="form-control InputField" 
                                maxlength="100" placeholder="Date of Birth" onChange={this.handleChange}/>
                            </td>
                            <td>
                                <input type='text' name='hireDateIns' id='hireDateIns' 
                                value={this.state.employee.hireDate} class="form-control InputField" 
                                maxlength="100" placeholder="Hire Date" onChange={this.handleChange}/>
                            </td>
                            <td>
                                <button className="btn btn-info" 
                                onClick={() => this.handleInsert()}>Insert</button>
                            </td>
                            <td>
                            &nbsp;
                            </td>
                        </tr>
                    </tbody>
                </table>
            </form>
        );
    }
});

var App = React.createClass({

    loadEmployeesFromServer: function() {

        var self = this;
        $.ajax({
            url: "http://localhost:83/Example201712/service/employee/list",
            type: 'POST',
            data : '{}',
        }).then(function(data) {
            self.setState({ employees: data });
        });

    },

    handleGridRefresh() {
        var self = this;
        console.log('handleGridRefresh().......................');
        this.loadEmployeesFromServer();
    },

    getInitialState: function() {
        return { employees: [] };
    },

    componentDidMount: function() {
        this.loadEmployeesFromServer();
    },

    render() {
        return ( 
            <div class="container-fluid">
                <div class="row">
                    <div class="col-md-8">
                        <div class="panel panel-primary">
                        <div class="panel-heading"><h3>Employee List</h3></div>
                        <div class="panel-body">
                        <EmployeeTable employees={this.state.employees} handleGridRefresh={this.handleGridRefresh} />
                        </div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
});

ReactDOM.render(<App />, document.getElementById('root') );

TEST using Rest client

End pointRequest methodInput JSONDescription
/service/employee/{employeeId}GET/employee/1Get employee
/service/employeePOST {
"firstName": "Abhijit",
"lastName": "Penekar",
"emailId": "a@a.com",
"dateofBirth": "1988-02-02",
"hireDate": "2014-02-02"
}
Insert employee
/service/employeePUT {
"employeeId": 2,
"firstName": "Abhijit1",
"lastName": "Penekar",
"emailId": "a@a.com",
"dateofBirth": "1988-02-02",
"hireDate": "2014-02-02"
}
Update employee
/service/employeeDELETE {
"employeeId": 2
}
Delete employee
/service/employee/listPOST{}Get employee list

TEST using cURL

curl -H “Content-Type: application/json” -X GET http://localhost:83/Example201712/employee/2

curl -H “Content-Type: application/json” -X POST -d {\”firstName\”: \”Abhijit\”,\”lastName\”: \”Penekar\”,\”emailId\”: \”a@a.com\”,\”dateofBirth\”: \”1988-02-02\”,\”hireDate\”: \”2014-02-02\”}
http://localhost:83/Example201712/employee

curl -H “Content-Type: application/json” -X PUT -d {\”employeeId\”:2,\”firstName\”: \”Abhijit\”,\”lastName\”: \”Penekar\”,\”emailId\”: \”a@a.com\”,\”dateofBirth\”: \”1988-02-02\”,\”hireDate\”: \”2014-02-02\”}
http://localhost:83/Example201711/employee

curl -H “Content-Type: application/json” -X DELETE -d {\”employeeId\”:2} http://localhost:83/Example201712/employee

curl -H “Content-Type: application/json” -X POST -d {} http://localhost:83/Example201712/employee/list

Download example source and eclipse project

Tags: , , , , ,

by , on February 6th, 2017

  • Categories