-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
making some progress rename methods names, modify router.get path and price logic modify SHOPLIS1_URL to d it simpler include vertx-web-validation in README pass @observes Router router to the validateHandlerSoppingList remove reactive routes in pom , they are deprecated improve readability in README adapt method without @route reactive improve tests add handling error and test parameter missing in request rm quarkus-resteasy-reactive dependency use static final variables and include error tests validations include /filterByArrayItem and /createShoppingList logic and test coverage and modify README extend of VertxWebValidationIT on OpenshiftVertxWebValidationIT rename OpenShift class and fix/rename failed RestService name for openshift deployment to lowercase valid
- Loading branch information
1 parent
168efff
commit a122069
Showing
8 changed files
with
502 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>io.quarkus.ts.qe</groupId> | ||
<artifactId>parent</artifactId> | ||
<version>1.0.0-SNAPSHOT</version> | ||
<relativePath>../..</relativePath> | ||
</parent> | ||
<artifactId>vertx-web-validation</artifactId> | ||
<packaging>jar</packaging> | ||
<name>Quarkus QE TS: HTTP: Vert.x-Web-Validation</name> | ||
<dependencies> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-resteasy-reactive-jackson</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.vertx</groupId> | ||
<artifactId>vertx-web-validation</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.vertx</groupId> | ||
<artifactId>vertx-json-schema</artifactId> | ||
</dependency> | ||
</dependencies> | ||
</project> |
36 changes: 36 additions & 0 deletions
36
http/vertx-web-validation/src/main/java/io/quarkus/ts/vertx/web/validation/ShopResource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package io.quarkus.ts.vertx.web.validation; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.UUID; | ||
|
||
import jakarta.ws.rs.GET; | ||
import jakarta.ws.rs.Path; | ||
import jakarta.ws.rs.Produces; | ||
import jakarta.ws.rs.core.MediaType; | ||
|
||
@Path("/shoppinglist") | ||
@Produces(MediaType.APPLICATION_JSON) | ||
public class ShopResource { | ||
|
||
private List<ShoppingList> shoppingList; | ||
|
||
private List<ShoppingList> createSampleProductList() { | ||
shoppingList = new ArrayList<>(); | ||
shoppingList.add(new ShoppingList(UUID.randomUUID(), "ListName1", 25, | ||
new ArrayList<>(Arrays.asList("Carrots", "Water", "Cheese", "Beer")))); | ||
shoppingList.add(new ShoppingList(UUID.randomUUID(), "ListName2", 80, | ||
new ArrayList<>(Arrays.asList("Meat", "Wine", "Almonds", "Potatoes", "Cake")))); | ||
return shoppingList; | ||
} | ||
|
||
@GET | ||
public List<ShoppingList> get() { | ||
if (shoppingList == null) { | ||
createSampleProductList(); | ||
} | ||
return shoppingList; | ||
} | ||
|
||
} |
60 changes: 60 additions & 0 deletions
60
http/vertx-web-validation/src/main/java/io/quarkus/ts/vertx/web/validation/ShoppingList.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package io.quarkus.ts.vertx.web.validation; | ||
|
||
import java.util.ArrayList; | ||
import java.util.UUID; | ||
|
||
public class ShoppingList { | ||
|
||
public UUID id; | ||
|
||
public String name; | ||
|
||
public ArrayList<String> products; | ||
|
||
public double price; | ||
|
||
public ShoppingList(UUID id, String name, double price, ArrayList<String> products) { | ||
this.id = id; | ||
this.name = name; | ||
this.price = price; | ||
this.products = products; | ||
} | ||
|
||
public ArrayList<String> getProducts() { | ||
return products; | ||
} | ||
|
||
public void setProducts(ArrayList<String> products) { | ||
this.products = products; | ||
} | ||
|
||
public UUID getId() { | ||
return id; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public void setName(String name) { | ||
this.name = name; | ||
} | ||
|
||
public double getPrice() { | ||
return price; | ||
} | ||
|
||
public void setPrice(double price) { | ||
this.price = price; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return String.format( | ||
"Shopping list{id=%s, name=%s, products=%s, price=%s}", | ||
getId(), | ||
getName(), | ||
getProducts().toString(), | ||
getPrice()); | ||
} | ||
} |
159 changes: 159 additions & 0 deletions
159
...alidation/src/main/java/io/quarkus/ts/vertx/web/validation/ValidationHandlerOnRoutes.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
package io.quarkus.ts.vertx.web.validation; | ||
|
||
import static io.vertx.ext.web.validation.builder.Parameters.param; | ||
import static io.vertx.json.schema.common.dsl.Schemas.arraySchema; | ||
import static io.vertx.json.schema.common.dsl.Schemas.numberSchema; | ||
import static io.vertx.json.schema.common.dsl.Schemas.objectSchema; | ||
import static io.vertx.json.schema.common.dsl.Schemas.stringSchema; | ||
import static io.vertx.json.schema.draft7.dsl.Keywords.maximum; | ||
|
||
import java.util.List; | ||
import java.util.concurrent.atomic.AtomicReference; | ||
import java.util.stream.Collectors; | ||
|
||
import jakarta.annotation.PostConstruct; | ||
import jakarta.enterprise.context.ApplicationScoped; | ||
import jakarta.enterprise.event.Observes; | ||
import jakarta.inject.Inject; | ||
import jakarta.ws.rs.core.HttpHeaders; | ||
import jakarta.ws.rs.core.MediaType; | ||
|
||
import io.netty.handler.codec.http.HttpResponseStatus; | ||
import io.vertx.core.Vertx; | ||
import io.vertx.core.json.Json; | ||
import io.vertx.core.json.JsonArray; | ||
import io.vertx.ext.web.Router; | ||
import io.vertx.ext.web.handler.BodyHandler; | ||
import io.vertx.ext.web.validation.BadRequestException; | ||
import io.vertx.ext.web.validation.BodyProcessorException; | ||
import io.vertx.ext.web.validation.ParameterProcessorException; | ||
import io.vertx.ext.web.validation.RequestParameters; | ||
import io.vertx.ext.web.validation.RequestPredicate; | ||
import io.vertx.ext.web.validation.RequestPredicateException; | ||
import io.vertx.ext.web.validation.ValidationHandler; | ||
import io.vertx.ext.web.validation.builder.Bodies; | ||
import io.vertx.ext.web.validation.builder.Parameters; | ||
import io.vertx.ext.web.validation.builder.ValidationHandlerBuilder; | ||
import io.vertx.json.schema.SchemaParser; | ||
import io.vertx.json.schema.SchemaRouter; | ||
import io.vertx.json.schema.SchemaRouterOptions; | ||
import io.vertx.json.schema.common.dsl.ObjectSchemaBuilder; | ||
|
||
@ApplicationScoped | ||
public class ValidationHandlerOnRoutes { | ||
//TODO when Quarkus use vert.x version 4.4.6 we can use SchemaRepository instead of SchemaParser with SchemaRouter | ||
//private SchemaRepository schemaRepository =SchemaRepository.create(new JsonSchemaOptions().setDraft(Draft.DRAFT7).setBaseUri(BASEURI)); | ||
private SchemaParser schemaParser; | ||
private SchemaRouter schemaRouter; | ||
|
||
@Inject | ||
Vertx vertx; | ||
|
||
private Router router; | ||
|
||
@Inject | ||
ShopResource shopResource; | ||
|
||
private static final String ERROR_MESSAGE = "{\"error\": \"%s\"}"; | ||
private static final String SHOPPINGLIST_NOT_FOUND = "Shopping list not found in the list or does not exist with that name or price"; | ||
|
||
@PostConstruct | ||
void initialize() { | ||
router = Router.router(vertx); | ||
router.route().handler(BodyHandler.create()); | ||
schemaParser = createSchema(); | ||
validateHandlerSoppingList(router); | ||
} | ||
|
||
private SchemaParser createSchema() { | ||
schemaRouter = SchemaRouter.create(vertx, new SchemaRouterOptions()); | ||
schemaParser = SchemaParser.createDraft7SchemaParser(schemaRouter); | ||
return schemaParser; | ||
} | ||
|
||
public void validateHandlerSoppingList(@Observes Router router) { | ||
AtomicReference<String> queryAnswer = new AtomicReference<>(); | ||
router.get("/filterList") | ||
.handler(ValidationHandlerBuilder | ||
.create(schemaParser) | ||
.queryParameter(param("shoppingListName", stringSchema())) | ||
.queryParameter(param("shoppingListPrice", numberSchema().with(maximum(100)))).build()) | ||
.handler(routingContext -> { | ||
RequestParameters parameters = routingContext.get(ValidationHandler.REQUEST_CONTEXT_KEY); | ||
String shoppingListName = parameters.queryParameter("shoppingListName").getString(); | ||
Double totalPrice = parameters.queryParameter("shoppingListPrice").getDouble(); | ||
|
||
// Logic to list shoppingList based on shoppingListName and totalPrice | ||
String shoppingListFound = fetchProductDetailsFromQuery(shoppingListName, totalPrice); | ||
queryAnswer.set(shoppingListFound); | ||
|
||
if (queryAnswer.get().equalsIgnoreCase(SHOPPINGLIST_NOT_FOUND)) { | ||
routingContext.response().setStatusCode(HttpResponseStatus.NOT_FOUND.code()); | ||
} | ||
|
||
routingContext.response().putHeader(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN).end(queryAnswer.get()); | ||
}).failureHandler(routingContext -> { | ||
// Error handling: | ||
if (routingContext.failure() instanceof BadRequestException || | ||
routingContext.failure() instanceof ParameterProcessorException || | ||
routingContext.failure() instanceof BodyProcessorException || | ||
routingContext.failure() instanceof RequestPredicateException) { | ||
|
||
String errorMessage = routingContext.failure().toString(); | ||
routingContext.response() | ||
.setStatusCode(HttpResponseStatus.BAD_REQUEST.code()) | ||
.putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) | ||
.end(String.format(ERROR_MESSAGE, errorMessage)); | ||
} | ||
}); | ||
// Create a ValidationHandlerBuilder with explodedParam and arraySchema to filter by array items | ||
ObjectSchemaBuilder bodySchemaBuilder = objectSchema() | ||
.property("shoppingListName", stringSchema()); | ||
ValidationHandlerBuilder | ||
.create(schemaParser) | ||
.body(Bodies.json(bodySchemaBuilder)); | ||
router.get("/filterByArrayItem") | ||
.handler( | ||
ValidationHandlerBuilder | ||
.create(schemaParser) | ||
.queryParameter(Parameters.explodedParam("shoppingArray", arraySchema().items(stringSchema()))) | ||
.body(Bodies.json(bodySchemaBuilder)) | ||
.build()) | ||
.handler(routingContext -> { | ||
RequestParameters parameters = routingContext.get(ValidationHandler.REQUEST_CONTEXT_KEY); | ||
JsonArray myArray = parameters.queryParameter("shoppingArray").getJsonArray(); | ||
// Retrieve the list of all shoppingLists | ||
List<ShoppingList> shoppingLists = fetchProductDetailsFromArrayQuery(myArray); | ||
|
||
routingContext.response().putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) | ||
.end(Json.encodeToBuffer(shoppingLists)); | ||
}); | ||
// Let's allow to create a new item | ||
router.post("/createShoppingList").handler( | ||
ValidationHandlerBuilder | ||
.create(schemaParser) | ||
.predicate(RequestPredicate.BODY_REQUIRED) | ||
.queryParameter(param("shoppingListName", stringSchema())) | ||
.queryParameter(param("shoppingListPrice", numberSchema().with(maximum(100)))) | ||
.build()) | ||
.handler(routingContext -> { | ||
routingContext.response().setStatusCode(HttpResponseStatus.OK.code()).end("Shopping list created"); | ||
}); | ||
|
||
} | ||
|
||
public List<ShoppingList> fetchProductDetailsFromArrayQuery(JsonArray myArray) { | ||
return shopResource.get().stream() | ||
.filter(shoppingList -> myArray.contains(shoppingList.getName())) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
public String fetchProductDetailsFromQuery(String name, Double price) { | ||
return shopResource.get().stream() | ||
.filter(product -> name.equalsIgnoreCase(product.getName()) && price.equals(product.getPrice())) | ||
.map(ShoppingList::toString) | ||
.findFirst() | ||
.orElse(SHOPPINGLIST_NOT_FOUND); | ||
} | ||
|
||
} |
7 changes: 7 additions & 0 deletions
7
...ation/src/test/java/io/quarkus/ts/vertx/web/validation/OpenShiftVertxWebValidationIT.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package io.quarkus.ts.vertx.web.validation; | ||
|
||
import io.quarkus.test.scenarios.OpenShiftScenario; | ||
|
||
@OpenShiftScenario | ||
public class OpenShiftVertxWebValidationIT extends VertxWebValidationIT { | ||
} |
Oops, something went wrong.