Posted In: Spring, Spring REST
Spring 5 + JDBC + REST + Maven – Complexity level 1
Technologies used
Maven 4.0.0
Spring 5.0.0.M4
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.
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
/employee/list method=POST
/employee/{employeeId} method=GET
/employee method=POST
/employee method=PUT
/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>Example201711</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> </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>Example201711</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
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
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>/*</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> </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; @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", method = { RequestMethod.POST }) public @ResponseBody Object insertEmployee(ServletRequest req, ServletResponse res, @RequestBody String requestJson) throws EmployeeException { LOGGER.debug("inside insert()"); 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 "{'response' : 'success'}"; } @RequestMapping(value = "/employee", method = { RequestMethod.PUT }) public @ResponseBody Object updateEmployee(ServletRequest req, ServletResponse res, @RequestBody String requestJson) throws EmployeeException { LOGGER.debug("inside update()"); 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 "{'response' : 'success'}"; } @RequestMapping(value = "/employee", method = { RequestMethod.DELETE }) public @ResponseBody Object deleteEmployee(ServletRequest req, ServletResponse res, @RequestBody String requestJson) throws EmployeeException { LOGGER.debug("inside update()"); 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 "{'response' : 'success'}"; } }
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); } }
TEST using Rest client
End point | Request method | Input JSON | Description |
---|---|---|---|
/employee/{employeeId} | GET | /employee/1 | Get employee |
/employee | POST | { "firstName": "Abhijit", "lastName": "Penekar", "emailId": "a@a.com", "dateofBirth": "1988-02-02", "hireDate": "2014-02-02" } | Insert employee |
/employee | PUT | { "employeeId": 2, "firstName": "Abhijit1", "lastName": "Penekar", "emailId": "a@a.com", "dateofBirth": "1988-02-02", "hireDate": "2014-02-02" } | Update employee |
/employee | DELETE | { "employeeId": 2 } | Delete employee |
/employee/list | POST | {} | Get employee list |
TEST using cURL
curl -H “Content-Type: application/json” -X GET http://localhost:83/Example201711/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/Example201711/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/Example201711/employee
curl -H “Content-Type: application/json” -X POST -d {} http://localhost:83/Example201711/employee/list
Download example source and eclipse project
Tags: CRUD, JDBCTemplate, MySQL, Rest, Spring5
- Apache (13)
- Build Tools (2)
- Gradle (2)
- Caching (1)
- cpanel (1)
- cURL (1)
- Database (7)
- Hibernate (5)
- Java Core (38)
- Java Script (15)
- Bootstrap (1)
- File Upload (7)
- jQuery (3)
- React (3)
- JEE (13)
- JSON (41)
- GSON (13)
- Jackson 1X (1)
- Jackson 2X (12)
- jsoniter (1)
- Logging (2)
- Apache Commons Logging (1)
- Apache Log4J (1)
- Logback (1)
- SLF4J (1)
- MongoDB (1)
- OS (1)
- Linux (1)
- Security (5)
- Server (4)
- Tomcat (4)
- Service (2)
- Micro (2)
- Spring (46)
- Pattern (2)
- Spring Boot (20)
- Spring Data (4)
- Spring MVC (8)
- Spring REST (13)
- Spring Security (7)
- Testing (11)
- XML (5)
- JDOM XML Parser (1)