Skip to content

Instantly share code, notes, and snippets.

@codinko
Created February 29, 2016 03:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save codinko/79986dbed38d0f2b2d1b to your computer and use it in GitHub Desktop.
Save codinko/79986dbed38d0f2b2d1b to your computer and use it in GitHub Desktop.
Spring REST API
package com.codinko.springrestapi.vo;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
// Generic class that can have data of generic type. See it's usage when an instance of this class is created
public class APIContract<T> {
private boolean success;
private String message;
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getTimeStamp() {
return new DateTime(DateTimeZone.UTC).toString();
}
}
Create a maven project with with 'maven-archetype-webapp'
[An archetype which contains a sample Maven Webapp project.]
and then add Spring capabilities.
- Add the required maven dependencies for a Spring REST project
- Code pom.xml,web.xml, spring-context.xml, and then the Rest Controller and other supported files as mentioned in this gist.
Look at your computer current drive/java/logs for two log files restapi.log and restapierror.log
restapi.log looks something like
2016-02-28 21:14:00,292 [http-bio-8080-exec-5] | INFO c.c.s.c.EmployeeController : getEmployees | get all employees
2016-02-28 21:16:18,411 [http-bio-8080-exec-9] | INFO c.c.s.c.EmployeeController : getEmployeeCertifications | get certifications of employeeID : 100
package com.codinko.springrestapi.vo;
public class Employee {
private String id;
private String name;
public Employee(String id, String name) {
super();
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.codinko.springrestapi.controllers;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
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.codinko.springrestapi.service.EmployeeService;
import com.codinko.springrestapi.vo.APIContract;
import com.codinko.springrestapi.vo.Employee;
@Configuration
@PropertySource("classpath:messages.properties")
@RestController
@RequestMapping(value = "/employee")
public class EmployeeController {
private static final Logger log = LoggerFactory.getLogger(EmployeeController.class);
@Autowired
private Environment env;
@Autowired
private EmployeeService employeeService;
@RequestMapping(value = "/all", method = RequestMethod.GET)
public APIContract<List<Employee>> getEmployees() {
//replace these logs with Spring AOP
log.info("get all employees");
List<Employee> employees = employeeService.getEmployees();
APIContract<List<Employee>> response = new APIContract<List<Employee>>();
response.setSuccess(true);
response.setMessage(env.getProperty("employee.all.fetch.success"));
response.setData(employees);
return response;
}
@RequestMapping(value = "/certifications/{employeeID}", method = RequestMethod.GET)
public APIContract<List<String>> getEmployeeCertifications(@PathVariable String employeeID){
log.info("get certifications of employeeID : {}", employeeID);
List<String> certifications = employeeService.getEmployeeCertifications(employeeID);
APIContract<List<String>> response = new APIContract<List<String>>();
response.setSuccess(true);
response.setMessage(env.getProperty("employee.certifications.fetch.success"));
response.setData(certifications);
return response;
}
// not tested. Let's test after swagger integration
@RequestMapping(value = "/edit", method = RequestMethod.POST)
public APIContract<Employee> updateEmployee(@RequestBody Employee employee) {
log.info("update employee: {}", employee);
Employee updatedEmp = employeeService.updateEmployee(employee);
APIContract<Employee> response = new APIContract<Employee>();
response.setSuccess(true);
response.setMessage(env.getProperty("employee.update.success"));
response.setData(updatedEmp);
return response;
}
}
package com.codinko.springrestapi.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import com.codinko.springrestapi.vo.Employee;
@Service("employeeService")
public class EmployeeService implements IEmployeeService {
public List<Employee> getEmployees() {
// call dao and getEmployees from Database
List<Employee> employees = new ArrayList<Employee>();
employees.add(new Employee("100", "Wolf"));
employees.add(new Employee("101", "Wall"));
employees.add(new Employee("102", "John"));
return employees;
}
public Employee updateEmployee(Employee emp) {
// call dao and updateEmployee in Database
return emp;
}
public List<String> getEmployeeCertifications(String employeeID) {
// call dao and get the certifications for this employeeID
List<String> certifications = new ArrayList<String>();
certifications.add("SCJP");
certifications.add("SCWCD");
certifications.add("OCP");
return certifications;
}
}
package com.codinko.springrestapi.service;
import java.util.List;
import com.codinko.springrestapi.vo.Employee;
public interface IEmployeeService {
public List<Employee> getEmployees();
public Employee updateEmployee(Employee emp);
public List<String> getEmployeeCertifications(String employeeID);
}
<!-- See Logback documention here : http://logback.qos.ch/documentation.html and
http://logback.qos.ch/manual/appenders.html
Make sure you read 'Size and time based archiving' : http://logback.qos.ch/manual/appenders.html#SizeAndTimeBasedFNATP
-->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<configuration>
<logger name="com.codinko">
<level value="TRACE" />
</logger>
<logger name="org.springframework">
<level value="INFO" />
</logger>
<appender name="LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/java/logs/restapi.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/java/logs/restapi_%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>10</maxHistory>
</rollingPolicy>
<encoder>
<charset>UTF-8</charset>
<pattern>%d [%thread] | %p %logger{5} : %M | %m %n</pattern>
</encoder>
</appender>
<!--
Sometimes you may wish to archive files essentially by date but at the same time limit the size of each log file,
in particular if post-processing tools impose size limits on the log files. In order to address this requirement,
logback ships with a sub-component for TimeBasedRollingPolicy called SizeAndTimeBasedFNATP,
where FNATP stands for File Naming And Triggering Policy.
Note the "%i" conversion token in addition to "%d". Both the %i and %d tokens are mandatory.
Each time the current log file reaches maxFileSize before the current time period ends,
it will be archived with an increasing index, starting at 0.
Size and time based archiving supports deletion of old archive files.
You need to specify the number of periods to preserve with the maxHistory property.
When your application is stopped and restarted, logging will continue at the correct location,
i.e. at the largest index number for the current period.
-->
<appender name="ERROR_LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
</filter>
<file>/java/logs/restapierror.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/java/logs/restapierror_%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>10</maxHistory>
</rollingPolicy>
<encoder>
<charset>UTF-8</charset>
<pattern>%d [%thread] | %p %logger{5} : %M | %m %n</pattern>
</encoder>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="LOG_FILE" />
<appender-ref ref="ERROR_LOG_FILE" />
</root>
</configuration>
employee.all.fetch.success=Employees fetched successfully
employee.certifications.fetch.success=Certifications of employee fetched successfully
employee.update.success=Employee updated successfully
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.codinko.springrestapi</groupId>
<artifactId>springrestapi</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>springrestapi Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<slf4j.version>1.7.16</slf4j.version>
<logback.version>1.1.3</logback.version>
<spring.version>4.1.1.RELEASE</spring.version>
<jackson.version>2.6.3</jackson.version>
<java.x.servlet.api>3.0.1</java.x.servlet.api>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
<version>${java.x.servlet.api}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.1</version>
</dependency>
</dependencies>
<build>
<finalName>springrest-api</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-4.0.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="com.codinko.springrestapi" />
<mvc:default-servlet-handler />
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>restapi</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<session-config>
<session-timeout>-1</session-timeout>
</session-config>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment