diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e73647a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +FROM openjdk:8-jdk-alpine +RUN addgroup -S spring && adduser -S spring -G spring +USER spring:spring +RUN mvn clean && mvn package +COPY target/workaround-1.0.0.jar app.jar +EXPOSE 8080 +ENTRYPOINT ["java","-jar","/app.jar"] \ No newline at end of file diff --git a/Readme.md b/Readme.md index dd07c08..e69de29 100644 --- a/Readme.md +++ b/Readme.md @@ -1,67 +0,0 @@ -# Spring Boot, MySQL, JPA, Hibernate Rest API Tutorial - -Build Restful CRUD API for a simple Note-Taking application using Spring Boot, Mysql, JPA and Hibernate. - -## Requirements - -1. Java - 1.8.x - -2. Maven - 3.x.x - -3. Mysql - 5.x.x - -## Steps to Setup - -**1. Clone the application** - -```bash -git clone https://github.com/callicoder/spring-boot-mysql-rest-api-tutorial.git -``` - -**2. Create Mysql database** -```bash -create database notes_app -``` - -**3. Change mysql username and password as per your installation** - -+ open `src/main/resources/application.properties` - -+ change `spring.datasource.username` and `spring.datasource.password` as per your mysql installation - -**4. Build and run the app using maven** - -```bash -mvn package -java -jar target/easy-notes-1.0.0.jar -``` - -Alternatively, you can run the app without packaging it using - - -```bash -mvn spring-boot:run -``` - -The app will start running at . - -## Explore Rest APIs - -The app defines following CRUD APIs. - - GET /api/notes - - POST /api/notes - - GET /api/notes/{noteId} - - PUT /api/notes/{noteId} - - DELETE /api/notes/{noteId} - -You can test them using postman or any other rest client. - -## Learn more - -You can find the tutorial for this application on my blog - - - diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..e9e928b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,37 @@ +version: '3' +services: + workaround-mysql: + container_name: workaround-mysql + image: mysql:5.7.22 + environment: + MYSQL_DATABASE: workaround + MYSQL_USER: admin + MYSQL_PASSWORD: admin + MYSQL_ROOT_PASSWORD: admin + ports: + - "3306:3306" + networks: + - my-network + workaround: + container_name: workaround + depends_on: + - workaround-mysql + build: + context: . + dockerfile: Dockerfile + working_dir: /workaround + volumes: + - ./:/workaround + - ~/.m2:/root/.m2 + expose: + - "8080" + links: + - workaround-mysql + networks: + - my-network +# restart: always + ports: + - "8080:8080" +networks: + my-network: + driver: bridge \ No newline at end of file diff --git a/pom.xml b/pom.xml index 1145d6d..85a538a 100644 --- a/pom.xml +++ b/pom.xml @@ -4,12 +4,12 @@ 4.0.0 com.example - easy-notes + workaround 1.0.0 jar - easy-notes - Rest API for a Simple Note Taking Application + workaround + Rest API for a Simple workaround Application org.springframework.boot diff --git a/src/main/java/com/example/easynotes/EasyNotesApplication.java b/src/main/java/com/example/easynotes/EasyNotesApplication.java deleted file mode 100644 index af3b8dd..0000000 --- a/src/main/java/com/example/easynotes/EasyNotesApplication.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.example.easynotes; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.data.jpa.repository.config.EnableJpaAuditing; - -@SpringBootApplication -@EnableJpaAuditing -public class EasyNotesApplication { - - public static void main(String[] args) { - SpringApplication.run(EasyNotesApplication.class, args); - } -} diff --git a/src/main/java/com/example/easynotes/controller/NoteController.java b/src/main/java/com/example/easynotes/controller/NoteController.java deleted file mode 100644 index 52f2ef0..0000000 --- a/src/main/java/com/example/easynotes/controller/NoteController.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.example.easynotes.controller; - -import com.example.easynotes.exception.ResourceNotFoundException; -import com.example.easynotes.model.Note; -import com.example.easynotes.repository.NoteRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; -import java.util.List; - -/** - * Created by rajeevkumarsingh on 27/06/17. - */ -@RestController -@RequestMapping("/api") -public class NoteController { - - @Autowired - NoteRepository noteRepository; - - @GetMapping("/notes") - public List getAllNotes() { - return noteRepository.findAll(); - } - - @PostMapping("/notes") - public Note createNote(@Valid @RequestBody Note note) { - return noteRepository.save(note); - } - - @GetMapping("/notes/{id}") - public Note getNoteById(@PathVariable(value = "id") Long noteId) { - return noteRepository.findById(noteId) - .orElseThrow(() -> new ResourceNotFoundException("Note", "id", noteId)); - } - - @PutMapping("/notes/{id}") - public Note updateNote(@PathVariable(value = "id") Long noteId, - @Valid @RequestBody Note noteDetails) { - - Note note = noteRepository.findById(noteId) - .orElseThrow(() -> new ResourceNotFoundException("Note", "id", noteId)); - - note.setTitle(noteDetails.getTitle()); - note.setContent(noteDetails.getContent()); - - Note updatedNote = noteRepository.save(note); - return updatedNote; - } - - @DeleteMapping("/notes/{id}") - public ResponseEntity deleteNote(@PathVariable(value = "id") Long noteId) { - Note note = noteRepository.findById(noteId) - .orElseThrow(() -> new ResourceNotFoundException("Note", "id", noteId)); - - noteRepository.delete(note); - - return ResponseEntity.ok().build(); - } -} diff --git a/src/main/java/com/example/easynotes/model/Note.java b/src/main/java/com/example/easynotes/model/Note.java deleted file mode 100644 index 4f8b6b1..0000000 --- a/src/main/java/com/example/easynotes/model/Note.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.example.easynotes.model; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import org.springframework.data.annotation.CreatedDate; -import org.springframework.data.annotation.LastModifiedDate; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; - -import javax.persistence.*; -import javax.validation.constraints.NotBlank; -import java.util.Date; - -/** - * Created by rajeevkumarsingh on 27/06/17. - */ -@Entity -@Table(name = "notes") -@EntityListeners(AuditingEntityListener.class) -@JsonIgnoreProperties(value = {"createdAt", "updatedAt"}, - allowGetters = true) -public class Note { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotBlank - private String title; - - @NotBlank - private String content; - - @Column(nullable = false, updatable = false) - @Temporal(TemporalType.TIMESTAMP) - @CreatedDate - private Date createdAt; - - @Column(nullable = false) - @Temporal(TemporalType.TIMESTAMP) - @LastModifiedDate - private Date updatedAt; - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - public Date getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(Date createdAt) { - this.createdAt = createdAt; - } - - public Date getUpdatedAt() { - return updatedAt; - } - - public void setUpdatedAt(Date updatedAt) { - this.updatedAt = updatedAt; - } - -} diff --git a/src/main/java/com/example/workaround/WorkaroundApplication.java b/src/main/java/com/example/workaround/WorkaroundApplication.java new file mode 100644 index 0000000..1fbf1f1 --- /dev/null +++ b/src/main/java/com/example/workaround/WorkaroundApplication.java @@ -0,0 +1,30 @@ +package com.example.workaround; + +import com.example.workaround.model.User; +import com.example.workaround.repository.UserRepository; + +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; + +@SpringBootApplication +@EnableJpaAuditing +public class WorkaroundApplication { + + + public static void main(String[] args) { + + + SpringApplication.run(WorkaroundApplication.class, args); + } + + @Bean + public CommandLineRunner insertDemoData(UserRepository userRepository) { + return args -> { + User user1 = new User(new Long(1), "admin"); + userRepository.save(user1); + }; + } +} diff --git a/src/main/java/com/example/easynotes/controller/IndexController.java b/src/main/java/com/example/workaround/controller/IndexController.java similarity index 52% rename from src/main/java/com/example/easynotes/controller/IndexController.java rename to src/main/java/com/example/workaround/controller/IndexController.java index f9c5ea4..794ec68 100644 --- a/src/main/java/com/example/easynotes/controller/IndexController.java +++ b/src/main/java/com/example/workaround/controller/IndexController.java @@ -1,4 +1,4 @@ -package com.example.easynotes.controller; +package com.example.workaround.controller; import org.springframework.web.bind.annotation.GetMapping; @@ -9,8 +9,8 @@ @RequestMapping("/") public class IndexController { - @GetMapping - public String sayHello() { - return "Hello and Welcome to the EasyNotes application. You can create a new Note by making a POST request to /api/notes endpoint."; - } + @GetMapping + public String sayHello() { + return "Hello and Welcome to the workaround application. You can create a new Note by making a POST request to /api/notes endpoint."; + } } diff --git a/src/main/java/com/example/workaround/controller/LoginController.java b/src/main/java/com/example/workaround/controller/LoginController.java new file mode 100644 index 0000000..68f6683 --- /dev/null +++ b/src/main/java/com/example/workaround/controller/LoginController.java @@ -0,0 +1,32 @@ +package com.example.workaround.controller; + +import com.example.workaround.model.User; +import com.example.workaround.repository.UserRepository; + +import javax.validation.Valid; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api") +public class LoginController { + + @Autowired + UserRepository userRepository; + + + @PostMapping("/login") + public User loginUser(@Valid @RequestBody User user) { + User u = userRepository.findById(user.getId()).get(); + if (u.getPassword().equals(user.getPassword())) + return user; + else { + throw new RuntimeException("Invalid User !!"); + } + } + +} diff --git a/src/main/java/com/example/workaround/controller/NoteController.java b/src/main/java/com/example/workaround/controller/NoteController.java new file mode 100644 index 0000000..f436b78 --- /dev/null +++ b/src/main/java/com/example/workaround/controller/NoteController.java @@ -0,0 +1,52 @@ +package com.example.workaround.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api") +public class NoteController { + // + // @Autowired + // NoteRepository noteRepository; + // + // @GetMapping("/notes") + // public List getAllNotes() { + // return noteRepository.findAll(); + // } + // + // @PostMapping("/notes") + // public Note createNote(@Valid @RequestBody Note note) { + // return noteRepository.save(note); + // } + // + // @GetMapping("/notes/{id}") + // public Note getNoteById(@PathVariable(value = "id") Long noteId) { + // return noteRepository.findById(noteId) + // .orElseThrow(() -> new ResourceNotFoundException("Note", "id", noteId)); + // } + // + // @PutMapping("/notes/{id}") + // public Note updateNote(@PathVariable(value = "id") Long noteId, + // @Valid @RequestBody Note noteDetails) { + // + // Note note = noteRepository.findById(noteId) + // .orElseThrow(() -> new ResourceNotFoundException("Note", "id", noteId)); + // + // note.setTitle(noteDetails.getTitle()); + // note.setContent(noteDetails.getContent()); + // + // Note updatedNote = noteRepository.save(note); + // return updatedNote; + // } + // + // @DeleteMapping("/notes/{id}") + // public ResponseEntity deleteNote(@PathVariable(value = "id") Long noteId) { + // Note note = noteRepository.findById(noteId) + // .orElseThrow(() -> new ResourceNotFoundException("Note", "id", noteId)); + // + // noteRepository.delete(note); + // + // return ResponseEntity.ok().build(); + // } +} diff --git a/src/main/java/com/example/easynotes/exception/ResourceNotFoundException.java b/src/main/java/com/example/workaround/exception/ResourceNotFoundException.java similarity index 95% rename from src/main/java/com/example/easynotes/exception/ResourceNotFoundException.java rename to src/main/java/com/example/workaround/exception/ResourceNotFoundException.java index 4e4c4f2..c7c02c9 100644 --- a/src/main/java/com/example/easynotes/exception/ResourceNotFoundException.java +++ b/src/main/java/com/example/workaround/exception/ResourceNotFoundException.java @@ -1,4 +1,4 @@ -package com.example.easynotes.exception; +package com.example.workaround.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/src/main/java/com/example/workaround/model/Note.java b/src/main/java/com/example/workaround/model/Note.java new file mode 100644 index 0000000..befd085 --- /dev/null +++ b/src/main/java/com/example/workaround/model/Note.java @@ -0,0 +1,87 @@ +package com.example.workaround.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EntityListeners; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.validation.constraints.NotBlank; + +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +@Entity +@Table(name = "notes") +@EntityListeners(AuditingEntityListener.class) +@JsonIgnoreProperties(value = { "createdAt", "updatedAt" }, allowGetters = true) +public class Note { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotBlank + private String title; + + @NotBlank + private String content; + + @Column(nullable = false, updatable = false) + @Temporal(TemporalType.TIMESTAMP) + @CreatedDate + private Date createdAt; + + @Column(nullable = false) + @Temporal(TemporalType.TIMESTAMP) + @LastModifiedDate + private Date updatedAt; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public Date getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + } + +} diff --git a/src/main/java/com/example/workaround/model/User.java b/src/main/java/com/example/workaround/model/User.java new file mode 100644 index 0000000..cf020e4 --- /dev/null +++ b/src/main/java/com/example/workaround/model/User.java @@ -0,0 +1,44 @@ +package com.example.workaround.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "user") +public class User { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String password; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public User() { + super(); + } + + public User(Long id, String password) { + super(); + this.id = id; + this.password = password; + } + +} diff --git a/src/main/java/com/example/easynotes/repository/NoteRepository.java b/src/main/java/com/example/workaround/repository/NoteRepository.java similarity index 59% rename from src/main/java/com/example/easynotes/repository/NoteRepository.java rename to src/main/java/com/example/workaround/repository/NoteRepository.java index 4b7b8b3..23a0181 100644 --- a/src/main/java/com/example/easynotes/repository/NoteRepository.java +++ b/src/main/java/com/example/workaround/repository/NoteRepository.java @@ -1,13 +1,10 @@ -package com.example.easynotes.repository; +package com.example.workaround.repository; + +import com.example.workaround.model.Note; -import com.example.easynotes.model.Note; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -/** - * Created by rajeevkumarsingh on 27/06/17. - */ - @Repository public interface NoteRepository extends JpaRepository { diff --git a/src/main/java/com/example/workaround/repository/UserRepository.java b/src/main/java/com/example/workaround/repository/UserRepository.java new file mode 100644 index 0000000..01fc78f --- /dev/null +++ b/src/main/java/com/example/workaround/repository/UserRepository.java @@ -0,0 +1,11 @@ +package com.example.workaround.repository; + +import com.example.workaround.model.User; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserRepository extends JpaRepository { + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index d357d46..861b4d0 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,13 +1,12 @@ ## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties) -spring.datasource.url = jdbc:mysql://localhost:3306/notes_app?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false -spring.datasource.username = root -spring.datasource.password = callicoder - +spring.datasource.url = jdbc:mysql://127.0.0.1:3306/workaround?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false&allowPublicKeyRetrieval=true +spring.datasource.username = admin +spring.datasource.password = admin ## Hibernate Properties -# The SQL dialect makes Hibernate generate better SQL for the chosen database +## The SQL dialect makes Hibernate generate better SQL for the chosen database spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect - -# Hibernate ddl auto (create, create-drop, validate, update) +# +## Hibernate ddl auto (create, create-drop, validate, update) spring.jpa.hibernate.ddl-auto = update \ No newline at end of file diff --git a/src/test/java/com/example/easynotes/EasyNotesApplicationTests.java b/src/test/java/com/example/easynotes/EasyNotesApplicationTests.java deleted file mode 100644 index 4bf539c..0000000 --- a/src/test/java/com/example/easynotes/EasyNotesApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.example.easynotes; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class EasyNotesApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/src/test/java/com/example/workaround/WorkaroundApplicationTests.java b/src/test/java/com/example/workaround/WorkaroundApplicationTests.java new file mode 100644 index 0000000..2bb6405 --- /dev/null +++ b/src/test/java/com/example/workaround/WorkaroundApplicationTests.java @@ -0,0 +1,11 @@ +package com.example.workaround; + +// @RunWith(SpringRunner.class) +// @SpringBootTest +public class WorkaroundApplicationTests { + + // @Test + // public void contextLoads() { + // } + +}