├── mongo-init.js ├── Makefile ├── Dockerfile ├── .github ├── dependabot.yml └── workflows │ └── mvn-build.yml ├── src ├── main │ ├── java │ │ └── com │ │ │ └── inventory │ │ │ ├── dao │ │ │ ├── InventoryRepositoryCustom.java │ │ │ ├── InventoryRepository.java │ │ │ └── InventoryRepositoryImpl.java │ │ │ ├── InventoryAppApplication.java │ │ │ ├── configuration │ │ │ └── KafkaConfiguration.java │ │ │ ├── external │ │ │ └── producer │ │ │ │ └── UpdatePriceProducer.java │ │ │ ├── controller │ │ │ ├── InventoryRestController.java │ │ │ └── InventoryController.java │ │ │ └── model │ │ │ └── Inventory.java │ └── resources │ │ ├── application.yml │ │ └── templates │ │ ├── index.ftlh │ │ ├── create_inventory.ftlh │ │ ├── updatePrice.ftlh │ │ └── updateStock.ftlh └── test │ └── java │ └── com │ └── inventory │ └── InventoryAppApplicationTests.java ├── README.md ├── .gitignore ├── docker-compose.yml └── pom.xml /mongo-init.js: -------------------------------------------------------------------------------- 1 | db.createUser({ 2 | user: "user", 3 | pwd: "user", 4 | roles: [ 5 | { 6 | role: "readWrite", 7 | db: "inventory_db" 8 | } 9 | ] 10 | }) -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | run-app: 2 | docker images -f "label=app-name=inventory-app" -q | xargs docker rmi -f 3 | docker-compose -f docker-compose.yml up -d 4 | 5 | stop-app: 6 | docker-compose -f docker-compose.yml down -v 7 | 8 | .phony: run-app stop-app -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:21 2 | 3 | WORKDIR /app 4 | 5 | copy target/inventory_app-1.0.0-SNAPSHOT.jar /app/inventory-app.jar 6 | 7 | LABEL app-name="inventory-app" 8 | EXPOSE 8080 9 | 10 | CMD ["java", "-jar", "inventory-app.jar"] -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: maven 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: '21:00' 8 | timezone: Asia/Jakarta 9 | open-pull-requests-limit: 10 10 | -------------------------------------------------------------------------------- /src/main/java/com/inventory/dao/InventoryRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.inventory.dao; 2 | 3 | /** 4 | * Created by eko.j.manurung on 6/2/2016. 5 | */ 6 | public interface InventoryRepositoryCustom { 7 | 8 | long updateStockProduct(String id, int stock); 9 | 10 | long updatePriceProduct(String id, double price); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/inventory/dao/InventoryRepository.java: -------------------------------------------------------------------------------- 1 | package com.inventory.dao; 2 | 3 | import com.inventory.model.Inventory; 4 | import org.springframework.data.mongodb.repository.MongoRepository; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Created by eko.j.manurung on 6/2/2016. 10 | */ 11 | public interface InventoryRepository extends MongoRepository, InventoryRepositoryCustom { 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/inventory/InventoryAppApplication.java: -------------------------------------------------------------------------------- 1 | package com.inventory; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class InventoryAppApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(InventoryAppApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/com/inventory/InventoryAppApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.inventory; 2 | 3 | import org.junit.jupiter.api.Disabled; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | 7 | 8 | @Disabled 9 | @SpringBootTest(classes = InventoryAppApplication.class) 10 | public class InventoryAppApplicationTests { 11 | 12 | @Disabled 13 | @Test 14 | public void contextLoads() { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/inventory/configuration/KafkaConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.inventory.configuration; 2 | 3 | import org.apache.kafka.clients.admin.NewTopic; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | /** 8 | * Created by eko.j.manurung on 6/6/2016. 9 | */ 10 | @Configuration 11 | public class KafkaConfiguration { 12 | 13 | public static final String PRICE_CHANGE_TOPIC_NAME = "com.inventory.update.price"; 14 | 15 | @Bean 16 | public NewTopic updateInventoryPrice() { 17 | return new NewTopic(PRICE_CHANGE_TOPIC_NAME, 1, (short) 1); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | kafka: 3 | producer: 4 | key-serializer: org.apache.kafka.common.serialization.StringSerializer 5 | value-serializer: org.apache.kafka.common.serialization.StringSerializer 6 | bootstrap-servers: kafka:9092 7 | data: 8 | mongodb: 9 | username: user 10 | password: user 11 | host: mongo 12 | port: 27017 13 | database: inventory_db 14 | 15 | springdoc: 16 | api-docs: 17 | path: /api-docs 18 | swagger-ui: 19 | path: /swagger-ui.html 20 | 21 | logging: 22 | level: 23 | com: 24 | inventory: 25 | org: 26 | apache: 27 | kafka: warn 28 | root: info -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Build Status](https://github.com/ekomanurung/spring-boot-web-kafka-producer-mongoDB/actions/workflows/mvn-build.yml/badge.svg) 2 | 3 | # spring-boot-web-kafka-producer 4 | Simple Inventory CRUD Application using spring-boot and kafka 5 | 6 | ## Prerequisites 7 | - Docker installed on local machine 8 | - Java 21 9 | - already compatible with Java 17++ (tested on Java 17) 10 | - for running springboot 3 11 | - Maven 12 | 13 | ## How to run 14 | - ensure you already run maven build using `mvn clean install` or `mvn clean package` 15 | - run make `run-app` to start the application 16 | - run make `stop-app` to stop the application 17 | 18 | ## Using the application 19 | - open in browser http://localhost:8080 20 | - use `Add` to add new inventory 21 | - to see the data sent to kafka, click updatePrice button 22 | - update price with new price less than old price 23 | - logs will appear in the console 24 | 25 | ## Open Swagger 26 | - open in browser http://localhost:8080/swagger-ui/index.html 27 | - now you can use apps using swagger 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### JetBrains template 3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 4 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 5 | 6 | .idea 7 | *.iml 8 | 9 | # Mongo Explorer plugin: 10 | .idea/mongoSettings.xml 11 | 12 | ## File-based project format: 13 | *.iws 14 | 15 | ## Plugin-specific files: 16 | 17 | # IntelliJ 18 | # mpeltonen/sbt-idea plugin 19 | .idea_modules/ 20 | 21 | # JIRA plugin 22 | atlassian-ide-plugin.xml 23 | 24 | # Crashlytics plugin (for Android Studio and IntelliJ) 25 | com_crashlytics_export_strings.xml 26 | crashlytics.properties 27 | crashlytics-build.properties 28 | fabric.properties 29 | 30 | 31 | target/ 32 | mvnw 33 | mvnw.cmd 34 | .mvn 35 | pom.xml.tag 36 | pom.xml.releaseBackup 37 | pom.xml.versionsBackup 38 | pom.xml.next 39 | release.properties 40 | dependency-reduced-pom.xml 41 | buildNumber.properties 42 | .mvn/timing.properties 43 | 44 | #Eclipse Configuration Files 45 | /.project 46 | /.settings 47 | */.settings 48 | *.classpath 49 | *.project 50 | *.orig 51 | 52 | tomcat/* 53 | -------------------------------------------------------------------------------- /src/main/resources/templates/index.ftlh: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Simple Inventory System 6 | 7 | 8 | 9 |

Data Product List

10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | <#list inventories as inventory> 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
Product NameStockPriceAction
${inventory.productName}${inventory.stock}${inventory.price}
35 | 36 | 37 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | app: 3 | build: . 4 | ports: 5 | - "8080:8080" 6 | depends_on: 7 | - mongo 8 | - kafka 9 | mongo: 10 | image: mongo 11 | ports: 12 | - "27017:27017" 13 | restart: always 14 | environment: 15 | MONGODB_USERNAME: user 16 | MONGODB_PASSWORD: user 17 | MONGO_INITDB_DATABASE: inventory_db 18 | volumes: 19 | - ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro 20 | zookeeper: 21 | image: confluentinc/cp-zookeeper:7.4.4 22 | environment: 23 | ZOOKEEPER_CLIENT_PORT: 2181 24 | ZOOKEEPER_TICK_TIME: 2000 25 | ports: 26 | - "2181:2181" 27 | kafka: 28 | image: confluentinc/cp-kafka:7.4.4 29 | depends_on: 30 | - zookeeper 31 | ports: 32 | - "9092:9092" 33 | - "29092:29092" 34 | environment: 35 | KAFKA_BROKER_ID: 1 36 | KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 37 | KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://kafka:9092 38 | KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT 39 | KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT 40 | KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 -------------------------------------------------------------------------------- /src/main/resources/templates/create_inventory.ftlh: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Simple Inventory System 6 | 7 | 8 |

Add Product Inventory

9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |


31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/resources/templates/updatePrice.ftlh: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Simple Inventory System 6 | 7 | 8 |

Update Price Product Inventory

9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |


31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/resources/templates/updateStock.ftlh: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Simple Inventory System 6 | 7 | 8 |

Update Stock Product Inventory

9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |


31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/java/com/inventory/external/producer/UpdatePriceProducer.java: -------------------------------------------------------------------------------- 1 | package com.inventory.external.producer; 2 | 3 | import com.inventory.configuration.KafkaConfiguration; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.kafka.core.KafkaTemplate; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * Created by eko.j.manurung on 6/6/2016. 11 | */ 12 | @Component 13 | public class UpdatePriceProducer { 14 | 15 | private static final Logger log = LoggerFactory.getLogger(UpdatePriceProducer.class); 16 | 17 | private KafkaTemplate kafkaTemplate; 18 | 19 | public UpdatePriceProducer(KafkaTemplate kafkaTemplate) { 20 | this.kafkaTemplate = kafkaTemplate; 21 | } 22 | 23 | public void publishPriceChange(String id, double price) { 24 | try { 25 | kafkaTemplate.send(KafkaConfiguration.PRICE_CHANGE_TOPIC_NAME, id, Double.toString(price)).get(); 26 | 27 | log.info("Price change successfully published for product {} with new price {}", id, price); 28 | } catch (Exception e) { 29 | log.error("Error publishing price change for product {} with new price {}", id, price, e); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.github/workflows/mvn-build.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: build app 10 | 11 | on: 12 | push: 13 | branches: [ "master" ] 14 | pull_request: 15 | branches: [ "master" ] 16 | 17 | jobs: 18 | build: 19 | 20 | runs-on: ubuntu-latest 21 | 22 | steps: 23 | - uses: actions/checkout@v4 24 | - name: Set up JDK 21 25 | uses: actions/setup-java@v4 26 | with: 27 | java-version: '21' 28 | distribution: 'temurin' 29 | cache: maven 30 | - name: Build with Maven 31 | run: mvn -B package --file pom.xml 32 | 33 | # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive 34 | - name: Update dependency graph 35 | uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 36 | -------------------------------------------------------------------------------- /src/main/java/com/inventory/controller/InventoryRestController.java: -------------------------------------------------------------------------------- 1 | package com.inventory.controller; 2 | 3 | import com.inventory.dao.InventoryRepository; 4 | import com.inventory.model.Inventory; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.data.domain.PageRequest; 7 | import org.springframework.data.domain.Pageable; 8 | import org.springframework.http.HttpStatus; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * Created by eko.j.manurung on 9/13/2016. 16 | */ 17 | @RequestMapping(value = "/api/v1/inventories") 18 | @RestController 19 | public class InventoryRestController { 20 | 21 | @Autowired 22 | private InventoryRepository repository; 23 | 24 | @GetMapping(value = "/{id}") 25 | public ResponseEntity getInventory(@PathVariable("id") String id) { 26 | repository 27 | .findById(id) 28 | .ifPresent(inventory -> new ResponseEntity<>(inventory, HttpStatus.OK)); 29 | 30 | return new ResponseEntity<>(HttpStatus.NOT_FOUND); 31 | } 32 | 33 | @GetMapping 34 | public ResponseEntity> findAll(@RequestParam int page, @RequestParam int size) { 35 | return new ResponseEntity<>(repository.findAll(PageRequest.of(page, size)).getContent(), HttpStatus.OK); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/inventory/model/Inventory.java: -------------------------------------------------------------------------------- 1 | package com.inventory.model; 2 | 3 | import org.springframework.data.annotation.Id; 4 | 5 | /** 6 | * Created by eko.j.manurung on 6/2/2016. 7 | */ 8 | public class Inventory { 9 | 10 | public static final String COLLECTION_NAME = "inventory"; 11 | 12 | @Id 13 | private String id; 14 | 15 | private String productName; 16 | private int stock; 17 | private double price; 18 | 19 | public Inventory() { 20 | } 21 | 22 | public String getId() { 23 | return id; 24 | } 25 | 26 | public void setId(String id) { 27 | this.id = id; 28 | } 29 | 30 | public String getProductName() { 31 | return productName; 32 | } 33 | 34 | public void setProductName(String productName) { 35 | this.productName = productName; 36 | } 37 | 38 | public int getStock() { 39 | return stock; 40 | } 41 | 42 | public void setStock(int stock) { 43 | this.stock = stock; 44 | } 45 | 46 | public double getPrice() { 47 | return price; 48 | } 49 | 50 | public void setPrice(double price) { 51 | this.price = price; 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return "Inventory{" + 57 | "id='" + id + '\'' + 58 | ", productName='" + productName + '\'' + 59 | ", stock=" + stock + 60 | ", price=" + price + 61 | '}'; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/inventory/dao/InventoryRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.inventory.dao; 2 | 3 | import com.inventory.model.Inventory; 4 | import com.mongodb.client.result.UpdateResult; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.data.mongodb.core.MongoTemplate; 7 | import org.springframework.data.mongodb.core.query.Criteria; 8 | import org.springframework.data.mongodb.core.query.Query; 9 | import org.springframework.data.mongodb.core.query.Update; 10 | 11 | /** 12 | * Created by eko.j.manurung on 6/2/2016. 13 | */ 14 | public class InventoryRepositoryImpl implements InventoryRepositoryCustom { 15 | 16 | @Autowired 17 | private MongoTemplate mongoTemplate; 18 | 19 | @Override 20 | public long updateStockProduct(String id, int stock) { 21 | 22 | Query query = new Query(); 23 | query.addCriteria(Criteria.where("id").is(id)); 24 | 25 | Update update = new Update(); 26 | update.set("stock", stock); 27 | 28 | UpdateResult updateResult = mongoTemplate.updateFirst(query, update, Inventory.class, Inventory.COLLECTION_NAME); 29 | 30 | return updateResult.getModifiedCount(); 31 | } 32 | 33 | @Override 34 | public long updatePriceProduct(String id, double price) { 35 | Query query = new Query(); 36 | query.addCriteria(Criteria.where("id").is(id)); 37 | 38 | Update update = new Update(); 39 | update.set("price", price); 40 | 41 | UpdateResult updateResult = mongoTemplate.updateFirst(query, update, Inventory.class, Inventory.COLLECTION_NAME); 42 | 43 | return updateResult.getModifiedCount(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.inventory 7 | inventory_app 8 | 1.0.0-SNAPSHOT 9 | jar 10 | 11 | inventory_app 12 | Demo project Simple CRUD Inventory 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 3.3.2 18 | 19 | 20 | 21 | 22 | UTF-8 23 | 21 24 | 25 | 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-data-mongodb 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-freemarker 34 | 35 | 36 | org.springframework.kafka 37 | spring-kafka 38 | 3.2.2 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-web 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-starter-logging 47 | 48 | 49 | 50 | 51 | org.webjars 52 | bootstrap 53 | 4.1.2 54 | 55 | 56 | org.webjars 57 | jquery 58 | 3.5.0 59 | 60 | 61 | org.springdoc 62 | springdoc-openapi-starter-webmvc-ui 63 | 2.5.0 64 | 65 | 66 | org.springframework.boot 67 | spring-boot-starter-test 68 | test 69 | 70 | 71 | org.freemarker 72 | freemarker 73 | 2.3.31 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | org.springframework.boot 82 | spring-boot-maven-plugin 83 | 84 | com.inventory.InventoryAppApplication 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /src/main/java/com/inventory/controller/InventoryController.java: -------------------------------------------------------------------------------- 1 | package com.inventory.controller; 2 | 3 | import com.inventory.dao.InventoryRepository; 4 | import com.inventory.external.producer.UpdatePriceProducer; 5 | import com.inventory.model.Inventory; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.ui.Model; 10 | import org.springframework.web.bind.annotation.*; 11 | import org.springframework.web.servlet.ModelAndView; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * Created by eko.j.manurung on 6/2/2016. 17 | */ 18 | @Controller 19 | public class InventoryController { 20 | 21 | private static final Logger log = LoggerFactory.getLogger(InventoryController.class); 22 | private InventoryRepository repository; 23 | private UpdatePriceProducer updatePriceProducer; 24 | 25 | public InventoryController(InventoryRepository repository, UpdatePriceProducer updatePriceProducer) { 26 | this.repository = repository; 27 | this.updatePriceProducer = updatePriceProducer; 28 | } 29 | 30 | @GetMapping("/") 31 | public String home(Model model) { 32 | List result = repository.findAll(); 33 | model.addAttribute("inventories", result); 34 | 35 | return "index"; 36 | } 37 | 38 | @GetMapping("/create") 39 | public String addInventory(Model model) { 40 | return "create_inventory"; 41 | } 42 | 43 | @GetMapping("stocks/edit/{id}") 44 | public String updateStockInventory(Model model, @PathVariable String id) { 45 | repository 46 | .findById(id) 47 | .ifPresent(model::addAttribute); 48 | 49 | return "updateStock"; 50 | } 51 | 52 | @GetMapping("prices/edit/{id}") 53 | public String updatePriceInventory(Model model, @PathVariable String id) { 54 | repository 55 | .findById(id) 56 | .ifPresent(model::addAttribute); 57 | 58 | return "updatePrice"; 59 | } 60 | 61 | @RequestMapping(value = "/updateStock", method = RequestMethod.POST) 62 | public ModelAndView updateStockInventory(@ModelAttribute("id") String id, @ModelAttribute("stock") int stock) { 63 | long retval = repository.updateStockProduct(id, stock); 64 | 65 | return new ModelAndView("redirect:/"); 66 | } 67 | 68 | @RequestMapping(value = "/updatePrice", method = RequestMethod.POST) 69 | public ModelAndView updatePriceInventory(@ModelAttribute("id") String id, @ModelAttribute("price") double newPrice) { 70 | repository 71 | .findById(id) 72 | .ifPresent(inventory -> { 73 | if (newPrice < inventory.getPrice()) { 74 | updatePriceProducer.publishPriceChange(id, newPrice); 75 | } 76 | long modifiedRows = repository.updatePriceProduct(id, newPrice); 77 | log.info("{} rows updated when update price", modifiedRows); 78 | }); 79 | 80 | 81 | return new ModelAndView("redirect:/"); 82 | } 83 | 84 | @RequestMapping(value = "/create", method = RequestMethod.POST) 85 | public ModelAndView addInventory(@ModelAttribute("inventory") Inventory inventory, Model model) { 86 | repository.save(inventory); 87 | log.info("Inventory {} successfully added", inventory); 88 | 89 | return new ModelAndView("redirect:/"); 90 | } 91 | 92 | @RequestMapping(value = "delete/{id}", method = RequestMethod.GET) 93 | public ModelAndView deleteProduct(@PathVariable String id) { 94 | repository.deleteById(id); 95 | 96 | return new ModelAndView("redirect:/"); 97 | } 98 | } 99 | --------------------------------------------------------------------------------