diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml new file mode 100644 index 0000000..eac633f --- /dev/null +++ b/.github/workflows/docker-image.yml @@ -0,0 +1,18 @@ +name: Docker Image CI + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Build the Docker image + run: docker build . --file Dockerfile --tag my-image-name:$(date +%s) diff --git a/.gitignore b/.gitignore index 9aa6ee3..891014a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ .sts4-cache /*.log +.idea diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 9cc84ea..0000000 Binary files a/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index b573bb5..0000000 --- a/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1 +0,0 @@ -distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.3/apache-maven-3.5.3-bin.zip diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..930f267 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM openjdk:8-alpine +RUN mkdir -p /opt/app +ENV PROJECT_HOME /opt/app + +COPY target/spring-boot-crud-rest-0.0.1-SNAPSHOT.jar $PROJECT_HOME/spring-boot-crud-rest-0.0.1-SNAPSHOT.jar + +WORKDIR $PROJECT_HOME + +CMD ["java" ,"-jar","./spring-boot-crud-rest-0.0.1-SNAPSHOT.jar"] + + +## docker build -t narasimhavuppala/spring-boot-mongo . \ No newline at end of file diff --git a/README.md b/README.md index 2ff6a6c..25a1fef 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,293 @@ # Spring-boot-crud-step-by-step -mvn spring-boot:run + # Pre Req + - docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3.9-management + - http://localhost:15672/#/queues + - docker run -p 61616:61616 -p 8161:8161 rmohr/activemq + - Start Mongo Server + - mvn spring-boot:run + +# Rest Endpoints +- Add below Dependency + + + org.springframework.boot + spring-boot-starter-web + + +- HTTP Methods + - GET + - Pathparam + - RequestParam + - PUT + - POST + - DELETE + - HTTP Status codes + - Mediatypes + - Produces + - Consumes +# Messaging Integration with ActiveMQ +- add below Dependency + + org.springframework.boot + spring-boot-starter-activemq + +- Create a seperate configuration classes + + + @Bean + ActiveMQConnectionFactory getActiveMQ() { + ActiveMQConnectionFactory obj = new ActiveMQConnectionFactory("username", "password", ""); + obj.setBrokerURL(brokerUrl); + return obj; + } + + @Bean + JmsTemplate getJmsTemplate() { + return new JmsTemplate(getActiveMQ()); + } +# ORM Integration(hibenrate to Mysql/Oracle/Postgree/MS SQL/H2) +- Add below Dependency + + + org.springframework.boot + spring-boot-starter-data-jpa + +- Create a model with below Annotations + - @Entity + - @Id +- Create a Repository + + @Repository + public interface StudentRepository extends JpaRepository { + //Code Generation Technique: DSL + } + +# Swagger +- Add dependencies in pom.xml +- Swagger API depedency & Swagger UI dependency + + + io.springfox + springfox-swagger2 + 2.9.2 + + + + io.springfox + springfox-swagger-ui + 2.9.2 + + +- Add @ Bean for DocketAPI +- + @Bean + public Docket api() { + return new Docket(DocumentationType.SWAGGER_2) + .select() + .apis(RequestHandlerSelectors.any()) + .paths(PathSelectors.any()) + .build(); + } +- open url :http://localhost:port/context-path/swagger-ui.html + + +# Datasource creation +- @ Bean for Programatic Data Source +- Embedded will be created if you add depedency + + + com.h2database + h2 + runtime + +- Connection Pooling +- use for Hikari: spring.datasource.type=com.zaxxer.hikari.HikariDataSource +- use the below config for Datasource + + spring: + datasource: + url: jdbc:mysql://localhost:3306/mysql + username: root + password: root + driver-class-name: com.mysql.cj.jdbc.Driver + + +# Log level Details +- debug=false +- logging.file=application.log +- logging.level.org.springframework=INFO +- logging.level.org.org.hibernate=WARN + + +# Actuator Endpoints +- Add below Dependency in the pom.xml + + + org.springframework.boot + spring-boot-starter-actuator + +- By default all actuator endpoints can be seen : + "http://serveropaddress:port/context-path/actuator" +- By default Endpoints are disabled due to Secure data +- enable all endpoints by : management.endpoints.web.exposure.include: "*" +- Shutdown endpoint needs to be enabled. This will not be covered in all(*) + + + +# Spring Annotations +- @Component +- @RestController +- @RequestMapping +- @Service +- @Repository +- @SpringBootApplication +- @Bean +- @Autowired +- @Query +- @Transactional +# Dev tools +- HMR(Hot Module Replacement) + + + org.springframework.boot + spring-boot-devtools + runtime + +- Ensures Restart of Project upon save +- It does not detect the pom.xml changes +# YAML Usage +- Spring profiles active +- Server port +- Conext path : Different Application name +- usage of tab + +# Reading Properties Files inside the program +- for Multiple Properties + + @Autowired + Environment env; +- for single property + + @Value("property.name) + +# Bean Validation +- use @ Valid wherever it needs to be validated +- @NotNull +- @Email +- @Min +- @Max +- @Size +- @Past/@Future +- @Negative/@Positive +# Oracle Database connectivtity + +- download JAR freom below: + + https://www.oracle.com/technetwork/apps-tech/jdbc-112010-090769.html + +- Install to local repo: + + mvn install:install-file -Dfile=ojdbc6.jar -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=12.1.0.1 -Dpackaging=jar +- Add pom dependency + + + com.oracle + ojdbc6 + 12.1.0.1 + +- create a user and give privilages + + CREATE USER crud IDENTIFIED BY crud; + + GRANT CONNECT TO crud; + + GRANT CONNECT, RESOURCE, DBA TO crud; + + GRANT CREATE SESSION TO crud; + + + GRANT UNLIMITED TABLESPACE TO crud; + + +- CREATE SEQUENCE student_seq + MINVALUE 1 + MAXVALUE 9999999999 + START WITH 4 + INCREMENT BY 1; + +# MongoDB Integration +- Add below dependency in pom.xml + + + org.springframework.boot + spring-boot-starter-data-mongodb + +- mention connection details in .yml file or(application.properties) + + spring: + data: + mongodb: + host: localhost + port: 27017 + database: courses +- create a mongo Repository + + public interface CourseRepository extends MongoRepository { + + } +- + +# Rest Consumers +- http://www.groupkt.com/post/c9b0ccb9/country-and-other-related-rest-webservices.htm + +# Open API integration +- http://localhost:8090/crudapp/swagger-ui.html +- username is : admin& admin +- yet to implement documentation Tasks + +# Features Awaiting + - Exception Handling + - Controller Specific + - AOP + - Auditing...Added Auditing + - Oauth2 Integration + - password flow + - Authorization Code + - Client Credentials + - Vault Service Integration + - Spring Cloud Config Integration + - Resilient 4J integration + - CQRS integration + - Native Queries + - JDBC and Batch Support + - Spring Cloud Sleuth support + - Spring Micrometer integration + - Dockerized this app + - K8S integration + - Making external calls to the app + - Jmeter Test cases + - API Integrations + - GraphQL + - WebFlux + + - Caching Using Redis and EHcache + - Open Shift Integration + # Rest + - File Upload + - Web Socket + - Encryption utilities + - Base 64 encryption + - HAL Media types + - Actuator End points + - Encrypting + - Custom Logging: Specifying the logger + - Many to Many mapping + - two data sources in the same project + - Unit Test cases + - Spring AOP + + - Before + - After + - Around + + diff --git a/pom.xml b/pom.xml index 9e09511..7b78744 100644 --- a/pom.xml +++ b/pom.xml @@ -15,57 +15,108 @@ org.springframework.boot spring-boot-starter-parent - 2.0.4.RELEASE + 2.5.4 UTF-8 UTF-8 - 1.8 + 11 + org.springframework.boot spring-boot-starter-actuator + + + org.springframework.boot spring-boot-starter-data-jpa + + org.springframework.boot spring-boot-starter-web - + + org.springframework.boot spring-boot-devtools runtime + + com.h2database h2 runtime + + org.springframework.boot spring-boot-starter-test test + + + + org.springdoc + springdoc-openapi-ui + 1.5.2 + + - io.springfox - springfox-swagger2 - 2.9.2 + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + - io.springfox - springfox-swagger-ui - 2.9.2 + mysql + mysql-connector-java + 8.0.13 + + + org.springframework.boot + spring-boot-starter-activemq + + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + + org.springframework.boot + spring-boot-starter-aop + + + + org.springframework.boot + spring-boot-starter-security + + + + org.springframework.boot + spring-boot-starter-validation + + + + org.projectlombok + lombok + true + + @@ -77,5 +128,4 @@ - diff --git a/src/main/java/com/university/crud/springbootcrudrest/SpringBootCrudRestApplication.java b/src/main/java/com/university/crud/springbootcrudrest/SpringBootCrudRestApplication.java index fc336ec..370ac74 100644 --- a/src/main/java/com/university/crud/springbootcrudrest/SpringBootCrudRestApplication.java +++ b/src/main/java/com/university/crud/springbootcrudrest/SpringBootCrudRestApplication.java @@ -1,12 +1,15 @@ package com.university.crud.springbootcrudrest; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.info.Info; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication +@OpenAPIDefinition(info = @Info(title = "Crud APP", version = "1.0", description = "sample APP")) public class SpringBootCrudRestApplication { - public static void main(String[] args) { - SpringApplication.run(SpringBootCrudRestApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(SpringBootCrudRestApplication.class, args); + } } diff --git a/src/main/java/com/university/crud/springbootcrudrest/aop/StudentAspect.java b/src/main/java/com/university/crud/springbootcrudrest/aop/StudentAspect.java new file mode 100644 index 0000000..2f42f54 --- /dev/null +++ b/src/main/java/com/university/crud/springbootcrudrest/aop/StudentAspect.java @@ -0,0 +1,25 @@ +package com.university.crud.springbootcrudrest.aop; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.After; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.springframework.stereotype.Component; + +@Aspect +@Component +public class StudentAspect { + @Before(value = "execution(* com.university.crud.springbootcrudrest.service.StudentService.*(..))") + public void beforeAdvice(JoinPoint joinPoint) { + System.out.println("Before method:" + joinPoint.getSignature()); + + //System.out.println("Creating Employee with name - " + name + " and id - " + empId); + } + + @After(value = "execution(* com.university.crud.springbootcrudrest.service.StudentService.*(..))") + public void afterAdvice(JoinPoint joinPoint) { + System.out.println("After method:" + joinPoint.getSignature()); + + //System.out.println("Successfully created Employee with name - " + name + " and id - " + empId); + } +} diff --git a/src/main/java/com/university/crud/springbootcrudrest/config/ActiveMQConfiguration.java b/src/main/java/com/university/crud/springbootcrudrest/config/ActiveMQConfiguration.java new file mode 100644 index 0000000..9cb19bc --- /dev/null +++ b/src/main/java/com/university/crud/springbootcrudrest/config/ActiveMQConfiguration.java @@ -0,0 +1,36 @@ +package com.university.crud.springbootcrudrest.config; + +import org.apache.activemq.ActiveMQConnectionFactory; +import org.apache.activemq.command.ActiveMQQueue; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jms.core.JmsTemplate; + +import javax.jms.Queue; + +@Configuration +public class ActiveMQConfiguration { + + @Value("${spring.activemq.broker-url}") + private String brokerUrl; + + @Bean + ActiveMQConnectionFactory getActiveMQ() { + ActiveMQConnectionFactory obj = new ActiveMQConnectionFactory("guest", "guest", ""); + obj.setBrokerURL(brokerUrl); + return obj; + + } + + @Bean + JmsTemplate getJmsTemplate() { + return new JmsTemplate(getActiveMQ()); + } + + @Bean + public Queue queue() { + return new ActiveMQQueue("testqueue"); + } + +} diff --git a/src/main/java/com/university/crud/springbootcrudrest/config/AppConfiguration.java b/src/main/java/com/university/crud/springbootcrudrest/config/AppConfiguration.java new file mode 100644 index 0000000..c3c3f69 --- /dev/null +++ b/src/main/java/com/university/crud/springbootcrudrest/config/AppConfiguration.java @@ -0,0 +1,27 @@ +package com.university.crud.springbootcrudrest.config; + +import org.springframework.context.annotation.Configuration; + + + +@Configuration +public class AppConfiguration { + + /*@Bean + public DataSource getDatasource() { + return DataSourceBuilder.create() + .driverClassName("com.mysql.cj.jdbc.Driver") + .username("root") + .password("root") + .url("jdbc:mysql://localhost:3306/mysql") + .build(); + /*EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); + builder.setType(EmbeddedDatabaseType.H2); + + EmbeddedDatabase db = builder.build(); + + + }*/ + + +} diff --git a/src/main/java/com/university/crud/springbootcrudrest/config/SecurityConfiguration.java b/src/main/java/com/university/crud/springbootcrudrest/config/SecurityConfiguration.java new file mode 100644 index 0000000..8752479 --- /dev/null +++ b/src/main/java/com/university/crud/springbootcrudrest/config/SecurityConfiguration.java @@ -0,0 +1,32 @@ +package com.university.crud.springbootcrudrest.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.factory.PasswordEncoderFactories; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + + PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); + + auth.inMemoryAuthentication().withUser("user").password(encoder.encode("user")).roles("USER").and() + .withUser("admin") + .password(encoder.encode("admin")) + .roles("USER", "ADMIN"); + + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + + http.httpBasic().and().authorizeRequests().antMatchers("/students/**").hasRole("USER").antMatchers("/**") + .hasRole("ADMIN").and().csrf().disable(); + } + +} diff --git a/src/main/java/com/university/crud/springbootcrudrest/controller/StudentController.java b/src/main/java/com/university/crud/springbootcrudrest/controller/StudentController.java index 42ec1a5..11bef48 100644 --- a/src/main/java/com/university/crud/springbootcrudrest/controller/StudentController.java +++ b/src/main/java/com/university/crud/springbootcrudrest/controller/StudentController.java @@ -1,46 +1,62 @@ package com.university.crud.springbootcrudrest.controller; +import com.university.crud.springbootcrudrest.model.Student; +import com.university.crud.springbootcrudrest.service.StudentService; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -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.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.*; -import com.university.crud.springbootcrudrest.model.Student; -import com.university.crud.springbootcrudrest.service.StudentService; +import javax.validation.Valid; +import java.util.HashMap; +import java.util.List; +import java.util.Map; @RestController @RequestMapping("/student") +@Tag(name = "student service for API", description = "controller for the service ") public class StudentController { - @Autowired - private StudentService service; - - @GetMapping(value="/{id}",produces=MediaType.APPLICATION_JSON_VALUE) - public Student getStudent(@PathVariable("id") int id) { - System.out.println(id); - - return service.getStudent(id); - } - - @PostMapping("/") - public Student save(Student obj) { - return service.save(obj); - - } - - @PutMapping("/") - public Student updateStudent(Student obj) { - return obj; - } - - @DeleteMapping("/{id}") - public void deleteStudent(@PathVariable("id") int id) { + @Autowired + private StudentService service; + + @GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = " Successful"), + @ApiResponse(responseCode = "401", description = "UnAuthorized") + }) + public Student getStudent(@PathVariable("id") int id) { + System.out.println(id); + + return service.getStudent(id); + } + + @PostMapping(value = "/{id}", consumes = MediaType.APPLICATION_JSON_VALUE) + public Student save(@Valid @RequestBody Student obj) throws Exception { + System.out.println(obj.getId()); + return service.save(obj); + } + + @PutMapping("/{id}") + public Student updateStudent(@Valid Student obj, @PathVariable("id") int studentId) throws Exception { + return service.update(studentId, obj); + } + + @DeleteMapping("/{id}") + public boolean deleteStudent(@PathVariable("id") int id) throws Exception { + return service.delete(id); + } + + @GetMapping("/{name}/{age}") + public List findByNameOrAge(@PathVariable("name") String studentName, @PathVariable("age") int studentAge) throws Exception { + return service.findByNameOrAge(studentName, studentAge); + } - } } diff --git a/src/main/java/com/university/crud/springbootcrudrest/exceptionhandler/GlobalExceptionHandler.java b/src/main/java/com/university/crud/springbootcrudrest/exceptionhandler/GlobalExceptionHandler.java new file mode 100644 index 0000000..8510ff8 --- /dev/null +++ b/src/main/java/com/university/crud/springbootcrudrest/exceptionhandler/GlobalExceptionHandler.java @@ -0,0 +1,37 @@ +package com.university.crud.springbootcrudrest.exceptionhandler; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.ControllerAdvice; + +import javax.annotation.Priority; +import java.util.HashMap; +import java.util.Map; + +@ControllerAdvice +public class GlobalExceptionHandler { + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(value = MethodArgumentNotValidException.class) + public Map handleClientSideException(MethodArgumentNotValidException ex) { + Map errors = new HashMap<>(); + ex.getBindingResult().getAllErrors().forEach((error) -> { + String fieldName = ((FieldError) error).getField(); + String errorMessage = error.getDefaultMessage(); + errors.put(fieldName, errorMessage); + }); + return errors; + } + + /* @ExceptionHandler(value = {Exception.class}) + public ResponseEntity getExceptions(Throwable t) { + System.out.println(t.getMessage()); + System.out.println("Error Occureded"); + t.printStackTrace(); + return new ResponseEntity("Error occured: " + t.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + }*/ +} diff --git a/src/main/java/com/university/crud/springbootcrudrest/messaging/StudentJmsSender.java b/src/main/java/com/university/crud/springbootcrudrest/messaging/StudentJmsSender.java new file mode 100644 index 0000000..6171f65 --- /dev/null +++ b/src/main/java/com/university/crud/springbootcrudrest/messaging/StudentJmsSender.java @@ -0,0 +1,31 @@ +package com.university.crud.springbootcrudrest.messaging; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.university.crud.springbootcrudrest.model.Student; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jms.core.JmsTemplate; +import org.springframework.stereotype.Component; + +@Component +public class StudentJmsSender { + @Autowired + JmsTemplate jmsTemplate; + + public void pushStudentSave(Student obj) { + ObjectMapper mapper = new ObjectMapper(); + try { + String studentObjJson = mapper.writeValueAsString(obj); + this.jmsTemplate.convertAndSend("testQueue", studentObjJson); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + + } + + public void pushStringMessage(String message) { + this.jmsTemplate.convertAndSend("testQueue", message); + + } + +} diff --git a/src/main/java/com/university/crud/springbootcrudrest/messaging/StudentSaveListner.java b/src/main/java/com/university/crud/springbootcrudrest/messaging/StudentSaveListner.java new file mode 100644 index 0000000..c14b120 --- /dev/null +++ b/src/main/java/com/university/crud/springbootcrudrest/messaging/StudentSaveListner.java @@ -0,0 +1,14 @@ +package com.university.crud.springbootcrudrest.messaging; + +import org.springframework.jms.annotation.JmsListener; +import org.springframework.stereotype.Component; + +@Component +public class StudentSaveListner { + + @JmsListener(destination = "testQueue") + public void consume(String message) { + System.out.println("Received Message: " + message); + } + +} diff --git a/src/main/java/com/university/crud/springbootcrudrest/model/Student.java b/src/main/java/com/university/crud/springbootcrudrest/model/Student.java index 0b8711b..81f8a58 100644 --- a/src/main/java/com/university/crud/springbootcrudrest/model/Student.java +++ b/src/main/java/com/university/crud/springbootcrudrest/model/Student.java @@ -1,33 +1,42 @@ package com.university.crud.springbootcrudrest.model; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.university.crud.springbootcrudrest.model.base.BaseEntity; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + import javax.persistence.Entity; import javax.persistence.Id; +import javax.validation.constraints.Email; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.PastOrPresent; +import java.time.LocalDate; + @Entity -public class Student { - @Id - int id; - String name; - String dob; - public int getId() { - return id; - } - public void setId(int id) { - this.id = id; - } - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - public String getDob() { - return dob; - } - public void setDob(String dob) { - this.dob = dob; - } - - +@Data +@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) +@AllArgsConstructor +@NoArgsConstructor +public class Student extends BaseEntity { + @Id + //@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "student_seq") + //@SequenceGenerator(sequenceName = "student_seq", allocationSize = 1, name = "student_seq") + // @GeneratedValue(strategy = GenerationType.AUTO) + private int id; + + @NotNull + private String name; + + @PastOrPresent + private LocalDate dob; + + @Email + private String email; + + @Min(value = 18, message = "Age must be greater than 18 to get admission") + private int age; } diff --git a/src/main/java/com/university/crud/springbootcrudrest/model/base/BaseEntity.java b/src/main/java/com/university/crud/springbootcrudrest/model/base/BaseEntity.java new file mode 100644 index 0000000..b8d3ac5 --- /dev/null +++ b/src/main/java/com/university/crud/springbootcrudrest/model/base/BaseEntity.java @@ -0,0 +1,41 @@ +package com.university.crud.springbootcrudrest.model.base; + + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Column; +import javax.persistence.MappedSuperclass; +import javax.persistence.PrePersist; +import javax.persistence.PreUpdate; +import java.io.Serializable; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; + +@MappedSuperclass +@Getter +@Setter +public class BaseEntity implements Serializable { + + @Column(name = "created_on", updatable = false) + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private OffsetDateTime createdOn; + + @Column(name = "modified_on", updatable = false) + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private OffsetDateTime modifiedOn; + + @PrePersist + public void preInsert() { + OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); + createdOn = now; + modifiedOn = now; + } + + @PreUpdate + public void preUpdate() { + modifiedOn = OffsetDateTime.now(ZoneOffset.UTC); + } + +} diff --git a/src/main/java/com/university/crud/springbootcrudrest/mongo/controller/CourseController.java b/src/main/java/com/university/crud/springbootcrudrest/mongo/controller/CourseController.java new file mode 100644 index 0000000..613d768 --- /dev/null +++ b/src/main/java/com/university/crud/springbootcrudrest/mongo/controller/CourseController.java @@ -0,0 +1,44 @@ +package com.university.crud.springbootcrudrest.mongo.controller; + +import com.university.crud.springbootcrudrest.mongo.model.Course; +import com.university.crud.springbootcrudrest.mongo.service.CourseService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController("/course") +public class CourseController { + + private Logger logger=LoggerFactory.getLogger(CourseController.class.getName()); + @Autowired + private CourseService courseService; + + @PostMapping + public void addCourse(@RequestBody Course Course){ + courseService.addCourse(Course); + } + + @PutMapping + public void updateCourse(@RequestBody Course Course){ + logger.info(Course.toString()); + courseService.addCourse(Course); + } + + @GetMapping("/get/all") + public List getAllCourses(){ + return courseService.getAllCourse(); + } + + @DeleteMapping("/{id}") + public void deleteCourse(@PathVariable("id") String CourseId){ + courseService.deleteCourse(CourseId); + } + + @GetMapping("/get/{name}") + public Course getCourseById(@PathVariable("name") String CourseName){ + return courseService.getCourseByName(CourseName); +} +} diff --git a/src/main/java/com/university/crud/springbootcrudrest/mongo/model/Course.java b/src/main/java/com/university/crud/springbootcrudrest/mongo/model/Course.java new file mode 100644 index 0000000..36e7bf4 --- /dev/null +++ b/src/main/java/com/university/crud/springbootcrudrest/mongo/model/Course.java @@ -0,0 +1,67 @@ +package com.university.crud.springbootcrudrest.mongo.model; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document(collection = "courses") //Annotation +public class Course { + + @Id + private String id; + private String name; + + private int duration; + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + private String category; + + public Course() { + } + + public Course(String id, String name, String category) { + this.id = id; + this.name = name; + this.category = category; + } + + 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; + } + + @Override + public String toString() { + return "Course [id=" + id + ", name=" + name + ", category=" + category + "]"; + } + + public int getDuration() { + return duration; + } + + public void setDuration(int duration) { + this.duration = duration; + } + + + + + +} diff --git a/src/main/java/com/university/crud/springbootcrudrest/mongo/repository/CourseRepository.java b/src/main/java/com/university/crud/springbootcrudrest/mongo/repository/CourseRepository.java new file mode 100644 index 0000000..10727da --- /dev/null +++ b/src/main/java/com/university/crud/springbootcrudrest/mongo/repository/CourseRepository.java @@ -0,0 +1,8 @@ +package com.university.crud.springbootcrudrest.mongo.repository; + +import com.university.crud.springbootcrudrest.mongo.model.Course; +import org.springframework.data.mongodb.repository.MongoRepository; + +public interface CourseRepository extends MongoRepository { + Course findCourseByName(String name); +} diff --git a/src/main/java/com/university/crud/springbootcrudrest/mongo/service/CourseService.java b/src/main/java/com/university/crud/springbootcrudrest/mongo/service/CourseService.java new file mode 100644 index 0000000..c27bbdb --- /dev/null +++ b/src/main/java/com/university/crud/springbootcrudrest/mongo/service/CourseService.java @@ -0,0 +1,35 @@ +package com.university.crud.springbootcrudrest.mongo.service; + +import com.university.crud.springbootcrudrest.mongo.model.Course; +import com.university.crud.springbootcrudrest.mongo.repository.CourseRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class CourseService { + + @Autowired + private CourseRepository courseRepository; + + public void addCourse(Course Course) { + courseRepository.save(Course); + } + + public void updateCourse(Course Course) { + courseRepository.save(Course); + } + + public List getAllCourse() { + return courseRepository.findAll(); + } + + public void deleteCourse(String id) { + courseRepository.deleteById(id); + } + + public Course getCourseByName(String name) { + return courseRepository.findCourseByName(name); + } +} diff --git a/src/main/java/com/university/crud/springbootcrudrest/repository/StudentRepository.java b/src/main/java/com/university/crud/springbootcrudrest/repository/StudentRepository.java index 9322ed4..80cf0a4 100644 --- a/src/main/java/com/university/crud/springbootcrudrest/repository/StudentRepository.java +++ b/src/main/java/com/university/crud/springbootcrudrest/repository/StudentRepository.java @@ -1,11 +1,16 @@ package com.university.crud.springbootcrudrest.repository; +import com.university.crud.springbootcrudrest.model.Student; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import com.university.crud.springbootcrudrest.model.Student; +import java.util.List; @Repository public interface StudentRepository extends JpaRepository { - + //Code Generation Technique: DSL + //DSL: Domain Specific Language + public void deleteById(int id); + + public List findByNameOrAge(String name,int age); } diff --git a/src/main/java/com/university/crud/springbootcrudrest/service/StudentService.java b/src/main/java/com/university/crud/springbootcrudrest/service/StudentService.java index 7710db1..317b869 100644 --- a/src/main/java/com/university/crud/springbootcrudrest/service/StudentService.java +++ b/src/main/java/com/university/crud/springbootcrudrest/service/StudentService.java @@ -1,28 +1,62 @@ package com.university.crud.springbootcrudrest.service; +import com.university.crud.springbootcrudrest.messaging.StudentJmsSender; +import com.university.crud.springbootcrudrest.model.Student; +import com.university.crud.springbootcrudrest.repository.StudentRepository; +import lombok.NoArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Isolation; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; -import com.university.crud.springbootcrudrest.model.Student; -import com.university.crud.springbootcrudrest.repository.StudentRepository; +import java.util.List; @Service +@NoArgsConstructor public class StudentService { - @Autowired - private StudentRepository repository; + @Autowired + Environment env; + + @Autowired + StudentJmsSender jmsStudent; + + @Autowired + private StudentRepository repository; + + @Transactional(readOnly = true) + public Student getStudent(int id) { + + return repository.findById(id).get(); - public Student getStudent(int id) { + } - return repository.getOne(id); + @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class) + public Student save(Student obj) throws Exception { + Student persitedObject = repository.save(obj); + jmsStudent.pushStudentSave(persitedObject); + return persitedObject; + } - } - @Transactional - public Student save(Student obj) { + @Transactional + public Student update(int id, Student obj) throws Exception { + obj.setId(id); + Student persitedObject = repository.save(obj); + jmsStudent.pushStudentSave(persitedObject); + return persitedObject; + } - return repository.save(obj); + @Transactional + public boolean delete(int id) throws Exception { + repository.deleteById(id); + jmsStudent.pushStringMessage("deleted Student with Id=" + 1); + return true; + } - } + public List findByNameOrAge(String name, int age) { + return repository.findByNameOrAge(name, age); + } } diff --git a/src/main/java/com/university/crud/springbootcrudrest/spring/AppConfiguration.java b/src/main/java/com/university/crud/springbootcrudrest/spring/AppConfiguration.java deleted file mode 100644 index 72a3840..0000000 --- a/src/main/java/com/university/crud/springbootcrudrest/spring/AppConfiguration.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.university.crud.springbootcrudrest.spring; - -import javax.sql.DataSource; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; - -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; - -@Configuration -@EnableSwagger2 -public class AppConfiguration { - - @Bean - public DataSource getDatasource() { - // DataSourceBuilder.create().build(); - // DataSourceBuilder.create().driverClassName("").username("").password("").url("").build(); - EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); - builder.setType(EmbeddedDatabaseType.H2); - - EmbeddedDatabase db = builder.build(); - - return db; - - } - @Bean - public Docket api() { - return new Docket(DocumentationType.SWAGGER_2) - .select() - .apis(RequestHandlerSelectors.any()) - .paths(PathSelectors.any()) - .build(); - } - -} diff --git a/src/main/resources/DDL.sql b/src/main/resources/DDL.sql new file mode 100644 index 0000000..e0a521d --- /dev/null +++ b/src/main/resources/DDL.sql @@ -0,0 +1,6 @@ +create table student( + id int, + name varchar(50), + dob varchar(50), + email varchar(50) +) \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index b499096..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1,15 +0,0 @@ -#logging settings -debug=false -logging.file=application.log -logging.level.org.springframework=INFO -logging.level.org.org.hibernate=WARN - - - -server.servlet.context-path=/myapp - -#Data Source creation -spring.datasource.url="" -spring.datasource.username=""; -spring.datasource.password="" -spring.datasource.driver-class-name="" diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..76b0266 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,76 @@ +logging: + file: application.log +server: + servlet: + context-path: /crudapp + port: 8090 +spring: + jpa: + show-sql: true + datasource: + type: com.zaxxer.hikari.HikariDataSource + hikari: + maximum-pool-size: 15 + minimum-idle: 1500 + pool-name: mypoolname + activemq: + broker-url: tcp://localhost:61616 + data: + mongodb: + host: localhost + port: 27017 + database: courses + +management: + endpoints: + web: + exposure: + include: "*" + +--- +spring: + profiles: dev + datasource: + url: jdbc:mysql://localhost:3306/mysql + username: root + password: root + driver-class-name: com.mysql.cj.jdbc.Driver + jpa: + properties: + hibernate.dialect: org.hibernate.dialect.MySQL5Dialect + show-sql: true + generate-ddl: false + hibernate: + ddl-auto: none + + +server: + port: 8089 + + +--- +spring: + profiles: test + datasource: + url: jdbc:oracle:thin:@localhost:1521:xe + username: crud + password: crud + driver-class-name: oracle.jdbc.driver.OracleDriver + jpa: + properties: + hibernate.dialect: org.hibernate.dialect.OracleDialect + show-sql: true + generate-ddl: false + hibernate: + ddl-auto: none +debug: false +server: + port: 8091 +springdoc: + packagesToScan: com.university.crud.springbootcrudrest +--- +spring: + profiles: prod +debug: false +server: + port: 8091 \ No newline at end of file diff --git a/src/test/java/com/university/crud/springbootcrudrest/SpringBootCrudRestApplicationTests.java b/src/test/java/com/university/crud/springbootcrudrest/SpringBootCrudRestApplicationTests.java index 2377771..2c75c9f 100644 --- a/src/test/java/com/university/crud/springbootcrudrest/SpringBootCrudRestApplicationTests.java +++ b/src/test/java/com/university/crud/springbootcrudrest/SpringBootCrudRestApplicationTests.java @@ -1,11 +1,8 @@ package com.university.crud.springbootcrudrest; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) @SpringBootTest public class SpringBootCrudRestApplicationTests {