Skip to content

Commit

Permalink
Updated storage to Mongo DB
Browse files Browse the repository at this point in the history
  • Loading branch information
sainik73 committed Jan 20, 2021
1 parent 2f84107 commit cc268f1
Show file tree
Hide file tree
Showing 10 changed files with 243 additions and 47 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ target/
*.ipr
*.jar

### Java Log file
*.log

### NetBeans ###
/nbproject/private/
/nbbuild/
Expand Down
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ Any modification to students-api.yaml file, necessitates the build of the projec
regenerate the API and Model classes. This is done using the swagger-codegen-maven-plugin.
REST Controller 'StudentsApiController' consumes these generated classes.

v1.0:
The repository now supports Mongo DB as storage.
students-api repository connects to Mongo DB, which is run as a Docker container.
Java Logs (students-api-logger.log) are created under project root/logs directory.

Instructions
-----------------
Expand All @@ -19,13 +23,12 @@ Instructions

`git clone https://github.com/sainik73/students-api`

2. Build the project with Maven:
2. Run Mongo docker instance by following instructions in mongo-data\RunMongo.txt file
3. Build the project with Maven:

```
cd students-api/
mvn clean install
```

3. Run the spring boot application 'StudentsApplication'
4. Test the application using postman
[![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/04fec31e35710e9bdb41#?env%5Bstudents-api-local-env%5D=W3sia2V5IjoiYmFzZVVybCIsInZhbHVlIjoibG9jYWxob3N0OjgwODAiLCJlbmFibGVkIjp0cnVlfV0=)
4. Run the spring boot application 'StudentsApplication'
5. Test the application using postman [![Run in Postman](https://run.pstmn.io/button.svg)](https://god.postman.co/run-collection/04fec31e35710e9bdb41#?env%5Bstudents-api-local-env%5D=W3sia2V5IjoiYmFzZVVybCIsInZhbHVlIjoibG9jYWxob3N0OjgxODAiLCJlbmFibGVkIjp0cnVlfV0=)
10 changes: 10 additions & 0 deletions mongo-data/RunMongo.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Run Mongo DB docker container

# Create a Docker Volume
docker volume create mongo-data

# This will map 'mongo-data' directory under user profile to 'data/db' directory in container
docker run -d -p 27017:27017 -v mongo-data:/data/db --name mymongodb mongo:latest

# Check docker status to be running
docker container ls
12 changes: 11 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
Expand All @@ -34,11 +37,18 @@
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<!-- Mongo dependency-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>

<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,79 +5,81 @@
import com.example.openapi.StudentsByAgeApi;
import com.example.openapi.model.Student;
import com.example.openapi.model.Students;
import com.example.openapi.students.service.StudentsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;

/**
* This is the REST controller class for the Students API
*/
@RestController
@Slf4j
public class StudentsApiController implements StudentsApi , StudentsByAgeApi {
@Override
public ResponseEntity<Students> studentsGet(String studentName) {
//call DB to get resources by studentName
//for now, mock the call
Student s1 = new Student();
s1.setStudentid(101);
s1.setAge(23);
s1.setName(studentName);

Student s2 = new Student();
s2.setStudentid(102);
s2.setAge(22);
s2.setName(studentName);

Students studentsList = new Students();
studentsList.add(s1);
studentsList.add(s2);

return new ResponseEntity<>(studentsList, HttpStatus.OK);
}
@Autowired
private StudentsService studentsService;

@Override
public ResponseEntity<Void> studentsPost(Student body) {
//validate request and call DB to create resource
Student s = studentsService.create(body.getStudentid(), body.getName(), body.getAge());
log.debug("Successfully Created the student: {}",s.getStudentid());
return new ResponseEntity<>(HttpStatus.CREATED);
}

@Override
public ResponseEntity<Void> studentsPut(Student body) {
//validate request and call DB to create resource
Student s = studentsService.update(body.getStudentid(), body.getName(), body.getAge());
log.debug("Successfully Updated the student: {}",s.getStudentid());
return new ResponseEntity<>(HttpStatus.OK);
}

@Override
public ResponseEntity<Student> studentsStudentIdGet(Integer studentId) {
//call DB to get resource by studentId
//for now, mock the call
Student s = new Student();
s.setStudentid(studentId);
s.setAge(23);
s.setName("Alex");
Student s = studentsService.getById(studentId);
Predicate<Student> nonNullPredicate = Objects::nonNull;
ResponseEntity<Student> responseEntity = null;
if (nonNullPredicate.test(s)) {
log.debug("Got Students by Id: {}, Name:{} ", new Object[]{s.getStudentid(), s.getName()});
responseEntity = new ResponseEntity<>(s, HttpStatus.OK);
}else{
log.debug("Student not found by Id: {}", studentId);
responseEntity = new ResponseEntity<>(HttpStatus.NOT_FOUND);
}

return responseEntity;
}

return new ResponseEntity<>(s,HttpStatus.OK);
@Override
public ResponseEntity<Students> studentsGet(String studentName) {
//call DB to get resources by studentName
List<Student> studentsList = studentsService.getByName(studentName);
log.debug("Got Students by Name: {}, List Size:{} ", new Object[]{studentName,studentsList.size()});

Students students = new Students();
students.addAll(studentsList);
return new ResponseEntity<>(students, HttpStatus.OK);
}

@Override
public ResponseEntity<Students> studentsByAgeGet(@NotNull @Valid Integer studentAge) {
//call DB to get resources by studentAge
//for now, mock the call
Student s1 = new Student();
s1.setStudentid(101);
s1.setAge(studentAge);
s1.setName("Alex");

Student s2 = new Student();
s2.setStudentid(102);
s2.setAge(studentAge);
s2.setName("Robert");

Students studentsList = new Students();
studentsList.add(s1);
studentsList.add(s2);
List<Student> studentsList = studentsService.getByAge(studentAge);
log.debug("Got Students by Age: {}, List Size:{} ", new Object[]{studentAge,studentsList.size()});

return new ResponseEntity<>(studentsList,HttpStatus.OK);
Students students = new Students();
students.addAll(studentsList);
return new ResponseEntity<>(students, HttpStatus.OK);
}

}
35 changes: 35 additions & 0 deletions src/main/java/com/example/openapi/students/db/model/Student.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.example.openapi.students.db.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.Data;
/**
* This class represents the Student entity
*/
@Document
@Data
public class Student {
@Id
private Integer studentid;

private String name;

private Integer age;

/**
* Default constructor
*/
public Student(){}

/**
* Custom constructor
* @param id id of student
* @param name name of student
* @param age age of student
*/
public Student(Integer id, String name, Integer age) {
this.studentid = id;
this.name = name;
this.age = age;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.example.openapi.students.repository;

import com.example.openapi.students.db.model.Student;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface StudentsRepository extends MongoRepository<Student,Integer> {

List<Student> findByName(String studentName);

List<Student> findByAge(Integer studentAge);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.example.openapi.students.service;

import com.example.openapi.students.db.model.Student;
import com.example.openapi.students.repository.StudentsRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
* This class has the business logic to deal with requests and persist to storage
*/
@Service
@Slf4j
public class StudentsService {
@Autowired
private StudentsRepository studentsRepository;

public com.example.openapi.model.Student create(int id, String name, int age){
Student s = studentsRepository.insert(new Student(id, name, age));
log.debug("Create in StudentsService: id:: {}",s.getStudentid());
//wrap to json entity
return convertToJSON(s);
}

public com.example.openapi.model.Student update(int id, String name, int age){
Student s = studentsRepository.save(new Student(id, name, age));
//wrap to json entity
return convertToJSON(s);
}

public com.example.openapi.model.Student getById(Integer studentId){
Optional<Student> s = studentsRepository.findById(studentId);
if (s.isPresent()) {
return convertToJSON(s.get());
}
return null;
}

public List<com.example.openapi.model.Student> getByName(String studentName){
List<Student> studentsList = studentsRepository.findByName(studentName);
List<com.example.openapi.model.Student> jsonStudent = new ArrayList<>();
for(Student student:studentsList){
jsonStudent.add(convertToJSON(student));
}
return jsonStudent;
}

public List<com.example.openapi.model.Student> getByAge(Integer studentAge) {
List<Student> studentsList = studentsRepository.findByAge(studentAge);
List<com.example.openapi.model.Student> jsonStudent = new ArrayList<>();
for (Student student : studentsList) {
jsonStudent.add(convertToJSON(student));
}
return jsonStudent;
}

/**
* Method to convert the DB model object to json model
* @param student
* @return com.example.openapi.model.Student
*/
private com.example.openapi.model.Student convertToJSON(Student student) {
com.example.openapi.model.Student openapiStudent = new com.example.openapi.model.Student();
openapiStudent.setStudentid(student.getStudentid());
openapiStudent.setName(student.getName());
openapiStudent.setAge(student.getAge());
log.debug("convertToJSON Student id: {}", openapiStudent.getStudentid());
return openapiStudent;
}
}
2 changes: 2 additions & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@

server.port=8180
spring.data.mongodb.uri=mongodb://localhost:27017/studentsdb
42 changes: 42 additions & 0 deletions src/main/resources/logback-spring.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOGS" value="./logs" />
<appender name="Console"
class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
%black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable
</Pattern>
</layout>
</appender>
<appender name="RollingFile"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOGS}/students-api-logger.log</file>
<encoder
class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
</encoder>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily and when the file reaches 1 MegaBytes -->
<fileNamePattern>${LOGS}/archived/students-api-logger-%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>1MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>

<!-- LOG everything at INFO level -->
<root level="info">
<appender-ref ref="RollingFile" />
<appender-ref ref="Console" />
</root>

<logger name="com.example.openapi.students" level="debug" additivity="false">
<appender-ref ref="RollingFile" />
<appender-ref ref="Console" />
</logger>

</configuration>

0 comments on commit cc268f1

Please sign in to comment.