diff --git a/build.gradle b/build.gradle index fb070c4..04b5153 100644 --- a/build.gradle +++ b/build.gradle @@ -31,3 +31,15 @@ dependencies { tasks.named('test') { useJUnitPlatform() } + +jar { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + manifest { + attributes 'Main-Class': 'com.booleanuk.api.Main' + } + + from { + configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } + } +} + diff --git a/dockers/Dockerfile.txt b/dockers/Dockerfile.txt new file mode 100644 index 0000000..2708b87 --- /dev/null +++ b/dockers/Dockerfile.txt @@ -0,0 +1,9 @@ +FROM eclipse-temurin:18 + +WORKDIR /app + +COPY docker2.jar /app/docker2.jar + +EXPOSE 4000 + +ENTRYPOINT ["java", "-jar", "docker2"] \ No newline at end of file diff --git a/dockers/docker-compose.yml b/dockers/docker-compose.yml new file mode 100644 index 0000000..300214b --- /dev/null +++ b/dockers/docker-compose.yml @@ -0,0 +1,21 @@ +services: + app: + image: 'docker2:latest' + container_name: app + depends_on: + - db + ports: + - '4000:4000' + environment: + - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/mypostgresuser + - SPRING_DATASOURCE_USERNAME=mypostgresuser + - SPRING_DATASOURCE_PASSWORD=mypostgrespassword + - SPRING_JPA_HIBERNATE_DDL_AUTO=update + + db: + image: 'postgres:latest' + container_name: db + environment: + - POSTGRES_USER=mypostgresuser + - POSTGRES_DATABASE=mypostgresuser + - POSTGRES_PASSWORD=mypostgrespassword \ No newline at end of file diff --git a/dockers/docker2.jar b/dockers/docker2.jar new file mode 100644 index 0000000..fe33f61 Binary files /dev/null and b/dockers/docker2.jar differ diff --git a/src/main/java/com/booleanuk/api/Main.java b/src/main/java/com/booleanuk/api/Main.java new file mode 100644 index 0000000..8e749e0 --- /dev/null +++ b/src/main/java/com/booleanuk/api/Main.java @@ -0,0 +1,11 @@ +package com.booleanuk.api; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Main { + public static void main(String[] args) { + SpringApplication.run(Main.class, args); + } +} diff --git a/src/main/java/com/booleanuk/api/controller/TweetController.java b/src/main/java/com/booleanuk/api/controller/TweetController.java new file mode 100644 index 0000000..937e2ee --- /dev/null +++ b/src/main/java/com/booleanuk/api/controller/TweetController.java @@ -0,0 +1,63 @@ +package com.booleanuk.api.controller; + +import com.booleanuk.api.model.Tweet; +import com.booleanuk.api.model.User; +import com.booleanuk.api.repository.TweetRepository; +import com.booleanuk.api.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; + +@RestController +@RequestMapping("tweets") +public class TweetController { + @Autowired + private TweetRepository tweetRepository; + private UserRepository userRepository; + + @GetMapping + public ResponseEntity> getTweets() { + Iterable tweets = tweetRepository.findAll(); + return ResponseEntity.ok(tweets); + } + + @PostMapping + public ResponseEntity createTweet(@PathVariable int userId, @RequestBody Tweet tweet) { + + User user = this.userRepository.findById(userId).orElseThrow( + () -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No User with that ID found") + ); + return new ResponseEntity<>(this.tweetRepository.save(tweet), HttpStatus.CREATED); + } + + @GetMapping("{id}") + public ResponseEntity getTweetById(@PathVariable int id) { + Tweet tweet = null; + tweet = this.tweetRepository.findById(id).orElseThrow( + () -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No Tweet with that ID found") + ); + return ResponseEntity.ok(tweet); + } + + @DeleteMapping("{id}") + public ResponseEntity deleteTweet(@PathVariable int id) { + Tweet tweet = this.tweetRepository.findById(id).orElseThrow( + () -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No Tweet with that ID found") + ); + this.tweetRepository.delete(tweet); + return ResponseEntity.ok(tweet); + } + + @PutMapping("{id}") + public ResponseEntity updateTweet(@PathVariable int id, @RequestBody Tweet tweet) { + Tweet tweetToUpdate = this.tweetRepository.findById(id).orElseThrow( + () -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No Tweet with that ID found") + ); + tweet.setId(tweetToUpdate.getId()); + return new ResponseEntity<>(this.tweetRepository.save(tweet), HttpStatus.CREATED); + } + + +} diff --git a/src/main/java/com/booleanuk/api/controller/UserController.java b/src/main/java/com/booleanuk/api/controller/UserController.java new file mode 100644 index 0000000..4181a0e --- /dev/null +++ b/src/main/java/com/booleanuk/api/controller/UserController.java @@ -0,0 +1,59 @@ +package com.booleanuk.api.controller; + +import com.booleanuk.api.model.User; +import com.booleanuk.api.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; + +@RestController +@RequestMapping("users") +public class UserController { + @Autowired + private UserRepository userRepository; + + public UserController(UserRepository userRepository) { + this.userRepository = userRepository; + } + + @GetMapping + public ResponseEntity> getUsers() { + Iterable users = userRepository.findAll(); + return ResponseEntity.ok(users); + } + + @PostMapping + public ResponseEntity createUser(@RequestBody User user) { + return ResponseEntity.ok(userRepository.save(user)); + + } + + @GetMapping("{id}") + public ResponseEntity getUserById(@PathVariable int id) { + User user = userRepository.findById(id).orElseThrow( + () -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No User with that ID found") + ); + return ResponseEntity.ok(user); + } + + @PutMapping("{id}") + public ResponseEntity updateUser(@PathVariable int id, @RequestBody User user) { + User userToUpdate = userRepository.findById(id).orElseThrow( + () -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No User with that ID found") + ); + user.setId(userToUpdate.getId()); + return new ResponseEntity<>(userRepository.save(user), HttpStatus.CREATED); + } + + @DeleteMapping("{id}") + public ResponseEntity deleteUser(@PathVariable int id) { + User user = userRepository.findById(id).orElseThrow( + () -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No User with that ID found") + ); + userRepository.delete(user); + return ResponseEntity.ok(user); + } + +} diff --git a/src/main/java/com/booleanuk/api/model/Tweet.java b/src/main/java/com/booleanuk/api/model/Tweet.java new file mode 100644 index 0000000..23ee4b4 --- /dev/null +++ b/src/main/java/com/booleanuk/api/model/Tweet.java @@ -0,0 +1,43 @@ +package com.booleanuk.api.model; + +import jakarta.persistence.*; + +@Entity +@Table(name = "Tweets") +public class Tweet { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + @Column + private String tweetContent; + + @ManyToOne + @JoinColumn(name = "user_id", referencedColumnName = "id") + private User user; + + public Tweet() { + } + + public Tweet(String tweetContent, User user) { + this.tweetContent = tweetContent; + this.user = user; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getTweetContent() { + return tweetContent; + } + + public void setTweetContent(String tweetContent) { + this.tweetContent = tweetContent; + } + +} diff --git a/src/main/java/com/booleanuk/api/model/User.java b/src/main/java/com/booleanuk/api/model/User.java new file mode 100644 index 0000000..8711221 --- /dev/null +++ b/src/main/java/com/booleanuk/api/model/User.java @@ -0,0 +1,50 @@ +package com.booleanuk.api.model; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.persistence.*; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Table(name = "Users") +public class User { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + @Column + private String username; + + @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) + @JsonIgnore + private List tweets = new ArrayList<>(); + + public User() { + } + + public User(String username) { + this.username = username; + } + // Getters and Setters + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + + +} diff --git a/src/main/java/com/booleanuk/api/repository/TweetRepository.java b/src/main/java/com/booleanuk/api/repository/TweetRepository.java new file mode 100644 index 0000000..c817153 --- /dev/null +++ b/src/main/java/com/booleanuk/api/repository/TweetRepository.java @@ -0,0 +1,7 @@ +package com.booleanuk.api.repository; + +import com.booleanuk.api.model.Tweet; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TweetRepository extends JpaRepository { +} diff --git a/src/main/java/com/booleanuk/api/repository/UserRepository.java b/src/main/java/com/booleanuk/api/repository/UserRepository.java new file mode 100644 index 0000000..ac04762 --- /dev/null +++ b/src/main/java/com/booleanuk/api/repository/UserRepository.java @@ -0,0 +1,11 @@ +package com.booleanuk.api.repository; + +import com.booleanuk.api.model.Tweet; +import com.booleanuk.api.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface UserRepository extends JpaRepository { + List findByUser(User user); +} diff --git a/src/main/java/com/booleanuk/api/response/ErrorResponse.java b/src/main/java/com/booleanuk/api/response/ErrorResponse.java new file mode 100644 index 0000000..349625d --- /dev/null +++ b/src/main/java/com/booleanuk/api/response/ErrorResponse.java @@ -0,0 +1,16 @@ +package com.booleanuk.api.response; +public class ErrorResponse { + private String message; + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public ErrorResponse(String message) { + this.message = message; + } +} \ No newline at end of file diff --git a/src/main/java/com/booleanuk/api/response/Response.java b/src/main/java/com/booleanuk/api/response/Response.java new file mode 100644 index 0000000..c8c4ee2 --- /dev/null +++ b/src/main/java/com/booleanuk/api/response/Response.java @@ -0,0 +1,20 @@ +package com.booleanuk.api.response; + +public class Response { + private String status; + private T data; + + public Response(String status, T data) { + this.status = status; + this.data = data; + } + + public String getStatus() { + return status; + } + + public T getData() { + return data; + } + +} \ No newline at end of file