diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml index 4c8102f1c8..cd8703f7f3 100644 --- a/spring-boot-modules/pom.xml +++ b/spring-boot-modules/pom.xml @@ -111,6 +111,7 @@ spring-boot-3-url-matching spring-boot-graalvm-docker spring-boot-validations + spring-boot-openapi diff --git a/spring-boot-modules/spring-boot-openapi/pom.xml b/spring-boot-modules/spring-boot-openapi/pom.xml new file mode 100644 index 0000000000..6612a429f9 --- /dev/null +++ b/spring-boot-modules/spring-boot-openapi/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + spring-boot-openapi + spring-boot-openapi + jar + OpenAPI Generator module + + + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-validation + + + javax.validation + validation-api + + + io.swagger.core.v3 + swagger-annotations + ${swagger-annotations.version} + + + + + + + org.openapitools + openapi-generator-maven-plugin + ${openapi-generator.version} + + + + generate + + + true + ${project.basedir}/src/main/resources/api/quotes.yaml + spring + ApiUtil.java + + custom + false + true + com.baeldung.tutorials.openapi.quotes.api + com.baeldung.tutorials.openapi.quotes.api.model + source + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + 7.3.0 + 2.2.20 + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/QuotesApplication.java b/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/QuotesApplication.java new file mode 100644 index 0000000000..6a7e5fce12 --- /dev/null +++ b/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/QuotesApplication.java @@ -0,0 +1,14 @@ +package com.baeldung.tutorials.openapi.quotes; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +import com.baeldung.tutorials.openapi.quotes.service.BrokerService; + +@SpringBootApplication +public class QuotesApplication { + + public static void main(String[] args) { + SpringApplication.run(QuotesApplication.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/controller/OrdersApiImpl.java b/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/controller/OrdersApiImpl.java new file mode 100644 index 0000000000..991d765b97 --- /dev/null +++ b/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/controller/OrdersApiImpl.java @@ -0,0 +1,9 @@ +package com.baeldung.tutorials.openapi.quotes.controller; + +import org.springframework.stereotype.Component; + +import com.baeldung.tutorials.openapi.quotes.api.OrdersApiDelegate; + +@Component +public class OrdersApiImpl implements OrdersApiDelegate { +} diff --git a/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/controller/QuotesApiImpl.java b/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/controller/QuotesApiImpl.java new file mode 100644 index 0000000000..40a583d960 --- /dev/null +++ b/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/controller/QuotesApiImpl.java @@ -0,0 +1,42 @@ +package com.baeldung.tutorials.openapi.quotes.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; + +import com.baeldung.tutorials.openapi.quotes.api.QuotesApiDelegate; +import com.baeldung.tutorials.openapi.quotes.api.model.QuoteResponse; +import com.baeldung.tutorials.openapi.quotes.service.BrokerService; + +@Component +public class QuotesApiImpl implements QuotesApiDelegate { + private final BrokerService broker; + + public QuotesApiImpl(BrokerService broker) { + this.broker = broker; + } + + + /** + * GET /quotes/{symbol} : Get current quote for a security + * + * @param symbol Security's symbol (required) + * @return OK (status code 200) + * @see QuotesApi#getQuote + */ + @Override + public ResponseEntity getQuote(String symbol) { + + var price = broker.getSecurityPrice(symbol); + + if ( price.isPresent()) { + var quote = new QuoteResponse(); + quote.setSymbol(symbol); + quote.setPrice(price.get()); + return ResponseEntity.ok(quote); + } + else { + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); + } + } +} diff --git a/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/service/BrokerService.java b/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/service/BrokerService.java new file mode 100644 index 0000000000..f55c0a8656 --- /dev/null +++ b/spring-boot-modules/spring-boot-openapi/src/main/java/com/baeldung/tutorials/openapi/quotes/service/BrokerService.java @@ -0,0 +1,29 @@ +package com.baeldung.tutorials.openapi.quotes.service; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Random; + +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Service; + +@Service +public class BrokerService { + + private Map securities = new HashMap<>(); + + public BrokerService() { + Random rnd = new Random(); + securities.put("GOOG", BigDecimal.valueOf(rnd.nextDouble() * 1000.00).setScale(4, RoundingMode.DOWN)); + securities.put("AA", BigDecimal.valueOf(rnd.nextDouble() * 1000.00).setScale(4, RoundingMode.DOWN)); + securities.put("BAEL", BigDecimal.valueOf(rnd.nextDouble() * 1000.00).setScale(4, RoundingMode.DOWN)); + } + + + public Optional getSecurityPrice(@NonNull String symbol) { + return Optional.ofNullable(securities.get(symbol)); + } +} diff --git a/spring-boot-modules/spring-boot-openapi/src/main/resources/api/quotes.yaml b/spring-boot-modules/spring-boot-openapi/src/main/resources/api/quotes.yaml new file mode 100644 index 0000000000..283395e27a --- /dev/null +++ b/spring-boot-modules/spring-boot-openapi/src/main/resources/api/quotes.yaml @@ -0,0 +1,130 @@ +openapi: 3.0.0 +info: + title: Quotes API + version: 1.0.0 +servers: + - description: Test server + url: http://localhost:8080 +paths: + /quotes/{symbol}: + get: + tags: + - quotes + summary: Get current quote for a security + operationId: getQuote + security: + - ApiKey: + - Quotes.Read + parameters: + - name: symbol + in: path + required: true + description: Security's symbol + schema: + type: string + pattern: '[A-Z0-9]+' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/QuoteResponse' + /orders/{symbol}: + post: + tags: + - orders + operationId: createOrder + security: + - ApiKey: + - Orders.Write + summary: Places a new order to buy a security + parameters: + - name: symbol + in: path + required: true + description: Security's symbol + schema: + type: string + pattern: '[A-Z0-9]' + requestBody: + required: true + description: Order info + content: + 'application/json': + schema: + $ref: '#'#/components/schemas/OrderRequest' + responses: + '201': + description: Order accepted + content: + 'application/json': + schema: + $ref: '#/components/schemas/OrderResponse' + +components: + securitySchemes: + ApiKey: + type: apiKey + in: header + name: X-API-KEY + + schemas: + OrderType: + type: string + enum: + - BUY + - SELL + OrderStatus: + type: string + enum: + - PENDING + - REJECTED + - FULFILLED + QuoteResponse: + description: Quote response + type: object + properties: + symbol: + type: string + description: security's symbol + price: + type: number + description: Quote value + OrderRequest: + description: Buy/Sell order details + type: object + properties: + clientRef: + type: string + orderType: + $ref: '#/components/schemas/OrderType' + symbol: + type: string + description: security's symbol + quantity: + type: number + price: + type: number + OrderResponse: + description: Buy/Sell order response + properties: + clientRef: + type: string + orderType: + $ref: '#/components/schemas/OrderType' + symbol: + type: string + description: security's symbol + quantity: + type: number + price: + type: number + orderStatus: + $ref: '#/components/schemas/OrderStatus' + + + + + + diff --git a/spring-boot-modules/spring-boot-openapi/src/main/resources/application.yaml b/spring-boot-modules/spring-boot-openapi/src/main/resources/application.yaml new file mode 100644 index 0000000000..7f074c3a3b --- /dev/null +++ b/spring-boot-modules/spring-boot-openapi/src/main/resources/application.yaml @@ -0,0 +1,4 @@ +logging: + level: + root: INFO + org.springframework: DEBUG \ No newline at end of file