diff --git a/eureka/discovery-server/src/main/java/com/example/discovery/DiscoveryServer.java b/eureka/discovery-server/src/main/java/com/example/discovery/DiscoveryServer.java index 15d783c..9e6e7d0 100644 --- a/eureka/discovery-server/src/main/java/com/example/discovery/DiscoveryServer.java +++ b/eureka/discovery-server/src/main/java/com/example/discovery/DiscoveryServer.java @@ -4,9 +4,11 @@ import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; import java.io.IOException; +@EnableEurekaServer @SpringBootApplication public class DiscoveryServer { diff --git a/eureka/discovery-server/src/main/resources/discovery-server.yml b/eureka/discovery-server/src/main/resources/discovery-server.yml index b55b43b..3ebf58f 100644 --- a/eureka/discovery-server/src/main/resources/discovery-server.yml +++ b/eureka/discovery-server/src/main/resources/discovery-server.yml @@ -11,3 +11,10 @@ logging: root: INFO org.springframework: DEBUG com.apress.cems: DEBUG + +server: + port: 3000 +eureka: + client: + registerWithEureka: false + fetchRegistry: false diff --git a/eureka/persons-server/src/main/java/com/eureka/persons/PersonsController.java b/eureka/persons-server/src/main/java/com/eureka/persons/PersonsController.java index ff4acb5..c0c23c0 100644 --- a/eureka/persons-server/src/main/java/com/eureka/persons/PersonsController.java +++ b/eureka/persons-server/src/main/java/com/eureka/persons/PersonsController.java @@ -1,5 +1,6 @@ package com.eureka.persons; +import com.eureka.persons.ex.NotFoundException; import com.eureka.persons.person.Person; import com.eureka.persons.services.PersonService; import org.springframework.http.HttpStatus; @@ -8,6 +9,7 @@ import org.springframework.web.bind.annotation.*; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; @RestController @@ -26,7 +28,15 @@ public PersonsController(PersonService personService) { @ResponseStatus(HttpStatus.OK) @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) public List list() { - return new ArrayList<>(); + List persons = personService.findAll(); + persons.sort(new Comparator() { + @Override + public int compare(Person person1, Person person2) { + return person1.getId().compareTo(person2.getId()); + } + }); + + return persons; } /** @@ -36,6 +46,11 @@ public List list() { @ResponseStatus(HttpStatus.CREATED) @PostMapping public void create(@RequestBody Person person, BindingResult result) { + if(result.hasErrors()) { + throw new PersonsException(HttpStatus.BAD_REQUEST, "Error when saving a person!."); + } + + personService.save(person); } /** @@ -48,7 +63,7 @@ public void create(@RequestBody Person person, BindingResult result) { @ResponseStatus(HttpStatus.OK) @GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE) public Person show(@PathVariable Long id) { - return new Person(); + return personService.findById(id).orElseThrow(() -> new NotFoundException(Person.class, id)); } /** @@ -62,6 +77,15 @@ public Person show(@PathVariable Long id) { @ResponseStatus(HttpStatus.NO_CONTENT) @PutMapping("/{id}") public void update(@RequestBody Person updatedPerson, @PathVariable Long id) { + Person person = personService.findById(id).orElseThrow(() -> new NotFoundException(Person.class, id)); + person.setUsername(updatedPerson.getUsername()); + person.setFirstName(updatedPerson.getFirstName()); + person.setLastName(updatedPerson.getLastName()); + person.setPassword(updatedPerson.getPassword()); + person.setHiringDate(updatedPerson.getHiringDate()); + person.setNewPassword(updatedPerson.getNewPassword()); + + personService.save(person); } /** @@ -73,5 +97,6 @@ public void update(@RequestBody Person updatedPerson, @PathVariable Long id) { @ResponseStatus(HttpStatus.NO_CONTENT) @DeleteMapping("/{id}") public void delete(@PathVariable Long id) { + personService.delete(personService.findById(id).orElseThrow(() -> new NotFoundException(Person.class, id))); } } \ No newline at end of file diff --git a/eureka/persons-server/src/main/java/com/eureka/persons/PersonsServer.java b/eureka/persons-server/src/main/java/com/eureka/persons/PersonsServer.java index f2098ae..957226c 100644 --- a/eureka/persons-server/src/main/java/com/eureka/persons/PersonsServer.java +++ b/eureka/persons-server/src/main/java/com/eureka/persons/PersonsServer.java @@ -5,11 +5,13 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; import java.io.IOException; @EntityScan(basePackages = "com.eureka.persons") @SpringBootApplication +@EnableEurekaServer public class PersonsServer { private static Logger logger = LoggerFactory.getLogger(PersonsServer.class); diff --git a/eureka/persons-server/src/main/resources/persons-server.yml b/eureka/persons-server/src/main/resources/persons-server.yml index b2b466d..ae83478 100644 --- a/eureka/persons-server/src/main/resources/persons-server.yml +++ b/eureka/persons-server/src/main/resources/persons-server.yml @@ -25,6 +25,11 @@ server: # Discovery Server Access #TODO here you add configurations for eureka client +eureka: + client: + serviceUrl: + defaultZone: http://localhost:3000/eureka/ + fetchRegistry: true info: app: diff --git a/lab-6-api-gateway/service1/pom.xml b/lab-6-api-gateway/service1/pom.xml index 478fe3f..f6942a5 100644 --- a/lab-6-api-gateway/service1/pom.xml +++ b/lab-6-api-gateway/service1/pom.xml @@ -36,6 +36,14 @@ spring-boot-starter-test test + + org.springframework.cloud + spring-cloud-netflix-eureka-client + + + org.springframework.cloud + spring-cloud-netflix-eureka-client + diff --git a/lab-6-api-gateway/service1/src/main/java/com/example/service1/Service1Application.java b/lab-6-api-gateway/service1/src/main/java/com/example/service1/Service1Application.java index 27128b5..c241266 100644 --- a/lab-6-api-gateway/service1/src/main/java/com/example/service1/Service1Application.java +++ b/lab-6-api-gateway/service1/src/main/java/com/example/service1/Service1Application.java @@ -2,8 +2,13 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; @SpringBootApplication +@EnableEurekaClient +@RequestMapping("api/greeting") public class Service1Application { public static void main(String[] args) { @@ -16,5 +21,10 @@ public static void main(String[] args) { // 3. print request headers // 4. register the service in eureka + @GetMapping + public String getGreeting(String name) { + return "Hello " + name; + } + } diff --git a/lab-6-api-gateway/service1/src/main/resources/application.yml b/lab-6-api-gateway/service1/src/main/resources/application.yml index 54b155f..3dca8c4 100644 --- a/lab-6-api-gateway/service1/src/main/resources/application.yml +++ b/lab-6-api-gateway/service1/src/main/resources/application.yml @@ -1,2 +1,11 @@ +spring: + application: + name: spring-cloud-eureka-client + server: - port: 8081 \ No newline at end of file + port: 8081 + +eureka: + client: + serviceUrl: + defaultZone: ${EUREKA_URI:http://localhost:3000/eureka} \ No newline at end of file diff --git a/recipes-rest-service/pom.xml b/recipes-rest-service/pom.xml new file mode 100644 index 0000000..0cb0d2f --- /dev/null +++ b/recipes-rest-service/pom.xml @@ -0,0 +1,49 @@ + + + + programare-cloud-java + com.unitbv + 1.0-SNAPSHOT + + 4.0.0 + + recipes-rest-service + + + 11 + 11 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + com.fasterxml.jackson.core + jackson-databind + 2.13.1 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/recipes-rest-service/src/main/java/com/recipes/RecipesRestServiceApplication.java b/recipes-rest-service/src/main/java/com/recipes/RecipesRestServiceApplication.java new file mode 100644 index 0000000..37c03b8 --- /dev/null +++ b/recipes-rest-service/src/main/java/com/recipes/RecipesRestServiceApplication.java @@ -0,0 +1,10 @@ +package com.recipes; + +import org.springframework.boot.SpringApplication; + +public class RecipesRestServiceApplication { + public static void main( String[] args ) + { + SpringApplication.run(RecipesRestServiceApplication.class, args); + } +} diff --git a/recipes-rest-service/src/main/java/com/recipes/config/AppConfig.java b/recipes-rest-service/src/main/java/com/recipes/config/AppConfig.java new file mode 100644 index 0000000..4186e4f --- /dev/null +++ b/recipes-rest-service/src/main/java/com/recipes/config/AppConfig.java @@ -0,0 +1,14 @@ +package com.recipes.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AppConfig { + + @Bean + public ObjectMapper objectMapper(){ + return new ObjectMapper(); + } +} diff --git a/recipes-rest-service/src/main/java/com/recipes/controller/RecipesController.java b/recipes-rest-service/src/main/java/com/recipes/controller/RecipesController.java new file mode 100644 index 0000000..fd584f3 --- /dev/null +++ b/recipes-rest-service/src/main/java/com/recipes/controller/RecipesController.java @@ -0,0 +1,43 @@ +package com.recipes.controller; + +import com.recipes.model.Ingredient; +import com.recipes.model.Recipe; +import com.recipes.service.RecipesService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + + +@RestController +@RequestMapping("/recipe") +public class RecipesController { + private final RecipesService recipesService; + + @Autowired + public RecipesController(RecipesService recipesService){ + this.recipesService = recipesService; + } + + @GetMapping() + public ResponseEntity> getAllRecipes(){ + return ResponseEntity.ok(recipesService.getAllRecipes()); + } + + @PostMapping + public ResponseEntity addRecipe(@RequestBody Recipe recipe) { + if(recipe.getName().trim().isEmpty() || recipe.getName() == null) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Recipe name cannot be empty or null!"); + } + + for(Ingredient ingredient : recipe.getIngredients()) { + if(ingredient.getName().trim().isEmpty() || ingredient.getName() == null) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Ingredient name cannot be empty or null!"); + } + } + + return ResponseEntity.ok(recipesService.addRecipe(recipe)); + } +} diff --git a/recipes-rest-service/src/main/java/com/recipes/datasource/MyRecipes.java b/recipes-rest-service/src/main/java/com/recipes/datasource/MyRecipes.java new file mode 100644 index 0000000..91e7c04 --- /dev/null +++ b/recipes-rest-service/src/main/java/com/recipes/datasource/MyRecipes.java @@ -0,0 +1,29 @@ +package com.recipes.datasource; + +import com.recipes.model.Recipe; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +@Component +public class MyRecipes { + private List recipes; + + public MyRecipes() { recipes = new ArrayList<>(); } + + public List getAllRecipes() { + return recipes; + } + + public Optional findRecipeByName(String name) { + return recipes.stream().filter(recipe -> recipe.getName().equals(name)).findFirst(); + } + + public Recipe addRecipe(Recipe recipe) { + this.recipes.add(recipe); + + return recipe; + } +} diff --git a/recipes-rest-service/src/main/java/com/recipes/model/Ingredient.java b/recipes-rest-service/src/main/java/com/recipes/model/Ingredient.java new file mode 100644 index 0000000..35c8e6a --- /dev/null +++ b/recipes-rest-service/src/main/java/com/recipes/model/Ingredient.java @@ -0,0 +1,14 @@ +package com.recipes.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Ingredient { + private String name; + private double quantity; + private String unitOfMeasurement; +} diff --git a/recipes-rest-service/src/main/java/com/recipes/model/Recipe.java b/recipes-rest-service/src/main/java/com/recipes/model/Recipe.java new file mode 100644 index 0000000..6864f86 --- /dev/null +++ b/recipes-rest-service/src/main/java/com/recipes/model/Recipe.java @@ -0,0 +1,15 @@ +package com.recipes.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Recipe { + private String name; + private List ingredients; +} diff --git a/recipes-rest-service/src/main/java/com/recipes/service/RecipesService.java b/recipes-rest-service/src/main/java/com/recipes/service/RecipesService.java new file mode 100644 index 0000000..8ac6d39 --- /dev/null +++ b/recipes-rest-service/src/main/java/com/recipes/service/RecipesService.java @@ -0,0 +1,11 @@ +package com.recipes.service; + +import com.recipes.model.Recipe; + +import java.util.List; + +public interface RecipesService { + List getAllRecipes(); + + Recipe addRecipe(Recipe recipe); +} diff --git a/recipes-rest-service/src/main/java/com/recipes/service/RecipesServiceImpl.java b/recipes-rest-service/src/main/java/com/recipes/service/RecipesServiceImpl.java new file mode 100644 index 0000000..044e051 --- /dev/null +++ b/recipes-rest-service/src/main/java/com/recipes/service/RecipesServiceImpl.java @@ -0,0 +1,28 @@ +package com.recipes.service; + +import com.recipes.datasource.MyRecipes; +import com.recipes.model.Recipe; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class RecipesServiceImpl implements RecipesService{ + private final MyRecipes myRecipes; + + @Autowired + public RecipesServiceImpl(MyRecipes myRecipes) { + this.myRecipes = myRecipes; + } + + @Override + public List getAllRecipes() { + return myRecipes.getAllRecipes(); + } + + @Override + public Recipe addRecipe(Recipe recipe) { + return myRecipes.addRecipe(recipe); + } +} diff --git a/recipes-rest-service/src/main/resources/application.properties b/recipes-rest-service/src/main/resources/application.properties new file mode 100644 index 0000000..bafddce --- /dev/null +++ b/recipes-rest-service/src/main/resources/application.properties @@ -0,0 +1 @@ +server.port=8081 \ No newline at end of file diff --git a/recipes-rest-service/src/test/java/RecipesApplicationTests.java b/recipes-rest-service/src/test/java/RecipesApplicationTests.java new file mode 100644 index 0000000..b1a39d9 --- /dev/null +++ b/recipes-rest-service/src/test/java/RecipesApplicationTests.java @@ -0,0 +1,11 @@ +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +public class RecipesApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/recipes-rest-service/target/classes/application.properties b/recipes-rest-service/target/classes/application.properties new file mode 100644 index 0000000..bafddce --- /dev/null +++ b/recipes-rest-service/target/classes/application.properties @@ -0,0 +1 @@ +server.port=8081 \ No newline at end of file diff --git a/rest-service/src/main/java/com/unitbv/config/AppConfig.java b/rest-service/src/main/java/com/unitbv/config/AppConfig.java index 5f6539e..aad8365 100644 --- a/rest-service/src/main/java/com/unitbv/config/AppConfig.java +++ b/rest-service/src/main/java/com/unitbv/config/AppConfig.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; @Configuration public class AppConfig { @@ -11,4 +12,9 @@ public class AppConfig { public ObjectMapper objectMapper(){ return new ObjectMapper(); } + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } } diff --git a/rest-service/src/main/java/com/unitbv/controller/PantryController.java b/rest-service/src/main/java/com/unitbv/controller/PantryController.java index 323e656..e3dce37 100644 --- a/rest-service/src/main/java/com/unitbv/controller/PantryController.java +++ b/rest-service/src/main/java/com/unitbv/controller/PantryController.java @@ -23,4 +23,19 @@ public PantryController(PantryService pantryService){ public ResponseEntity> getAllIngredients(){ return ResponseEntity.ok(pantryService.getAllIngredients()); } + + @PostMapping + public void saveIngredient(@RequestBody Ingredient ingredient) { + pantryService.saveIngredient(ingredient); + } + + @PutMapping("/ingredient") + public void updateIngredient(@RequestBody Ingredient ingredient) { + pantryService.updateIngredient(ingredient); + } + + @DeleteMapping("/ingredient/{ingredientName}") + public void deleteIngredient(@PathVariable String ingredientName) { + pantryService.deleteIngredient(ingredientName); + } } diff --git a/rest-service/src/main/java/com/unitbv/controller/RecipeController.java b/rest-service/src/main/java/com/unitbv/controller/RecipeController.java new file mode 100644 index 0000000..6962700 --- /dev/null +++ b/rest-service/src/main/java/com/unitbv/controller/RecipeController.java @@ -0,0 +1,35 @@ +package com.unitbv.controller; + +import com.unitbv.request.CreateRecipeRequest; +import com.unitbv.service.RecipesService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/recipe") +public class RecipeController { + private final RecipesService recipesService; + + @Autowired + public RecipeController(RecipesService recipesService) { + this.recipesService = recipesService; + } + + @PostMapping("/new") + public ResponseEntity addRecipe(@RequestBody CreateRecipeRequest recipe) { + try { + return ResponseEntity.ok(recipesService.addRecipe(recipe)); + } catch (RuntimeException exception) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(exception.getMessage()); + } + } + + @GetMapping("/all") + public ResponseEntity> getAllRecipes() { + return ResponseEntity.ok(recipesService.getAllRecipes()); + } +} diff --git a/rest-service/src/main/java/com/unitbv/service/PantryService.java b/rest-service/src/main/java/com/unitbv/service/PantryService.java index af3b315..5e19699 100644 --- a/rest-service/src/main/java/com/unitbv/service/PantryService.java +++ b/rest-service/src/main/java/com/unitbv/service/PantryService.java @@ -6,4 +6,12 @@ public interface PantryService { List getAllIngredients(); + + Ingredient saveIngredient(Ingredient ingredient); + + List saveAllIngredients(List ingredients); + + Ingredient updateIngredient(Ingredient ingredient); + + boolean deleteIngredient(String name); } diff --git a/rest-service/src/main/java/com/unitbv/service/PantryServiceImpl.java b/rest-service/src/main/java/com/unitbv/service/PantryServiceImpl.java index 8e1ead8..2379ffb 100644 --- a/rest-service/src/main/java/com/unitbv/service/PantryServiceImpl.java +++ b/rest-service/src/main/java/com/unitbv/service/PantryServiceImpl.java @@ -17,8 +17,23 @@ public PantryServiceImpl(MyPantry pantry){ this.pantry = pantry; } + @Override + public Ingredient saveIngredient(Ingredient ingredient) { return pantry.saveIngredient(ingredient); } + + @Override + public List saveAllIngredients(List ingredientsToAdd) { + return pantry.saveAllIngredients(ingredientsToAdd); + } + @Override public List getAllIngredients(){ return pantry.getAllIngredients(); } + + + @Override + public Ingredient updateIngredient(Ingredient ingredient) { return pantry.updateIngredient(ingredient); } + + @Override + public boolean deleteIngredient(String name) { return pantry.deleteIngredient(name); } } diff --git a/rest-service/src/main/java/com/unitbv/service/RecipesService.java b/rest-service/src/main/java/com/unitbv/service/RecipesService.java new file mode 100644 index 0000000..3fdf924 --- /dev/null +++ b/rest-service/src/main/java/com/unitbv/service/RecipesService.java @@ -0,0 +1,11 @@ +package com.unitbv.service; + +import com.unitbv.request.CreateRecipeRequest; + +import java.util.List; + +public interface RecipesService { + List getAllRecipes(); + + CreateRecipeRequest addRecipe(CreateRecipeRequest recipe); +} diff --git a/rest-service/src/main/java/com/unitbv/service/RecipesServiceImpl.java b/rest-service/src/main/java/com/unitbv/service/RecipesServiceImpl.java new file mode 100644 index 0000000..99d71fd --- /dev/null +++ b/rest-service/src/main/java/com/unitbv/service/RecipesServiceImpl.java @@ -0,0 +1,43 @@ +package com.unitbv.service; + +import com.unitbv.datasource.MyPantry; +import com.unitbv.request.CreateRecipeRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.util.Arrays; +import java.util.List; + +@Service +public class RecipesServiceImpl implements RecipesService { + private final RestTemplate restTemplate; + private final MyPantry pantry; + + @Autowired + public RecipesServiceImpl(RestTemplate restTemplate, MyPantry pantry) { + this.restTemplate = restTemplate; + this.pantry = pantry; + } + + @Override + public List getAllRecipes() { + ResponseEntity response = + restTemplate.getForEntity( + "http://localhost:8081/api/recipe", + CreateRecipeRequest[].class); + return Arrays.asList(response.getBody()); + } + + @Override + public CreateRecipeRequest addRecipe(CreateRecipeRequest recipe) { + ResponseEntity response = + restTemplate.postForEntity( + "http://localhost:8081/api/recipe", + recipe, + CreateRecipeRequest.class); + pantry.saveAllIngredients(recipe.getIngredients()); + return response.getBody(); + } +}