diff --git a/h2/db.mv.db b/h2/db.mv.db
index 512981c..af12566 100644
Binary files a/h2/db.mv.db and b/h2/db.mv.db differ
diff --git a/pom.xml b/pom.xml
index 3111293..2944e27 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,6 +11,10 @@
11
11
+
+
+
+ 4.13.2
junit
junit
- 4.13.2
+ ${junit.version}
diff --git a/src/main/java/Controller/Controller.java b/src/main/java/Controller/Controller.java
index 191086a..ef71151 100644
--- a/src/main/java/Controller/Controller.java
+++ b/src/main/java/Controller/Controller.java
@@ -9,6 +9,7 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.javalin.Javalin;
+import io.javalin.http.HttpStatus;
import java.sql.PreparedStatement;
import java.sql.SQLException;
@@ -17,12 +18,19 @@
public class Controller {
- VendorService vendorService;
- ProductService productService;
+ // Constants are useful when reusing strings so you only have to modify in one play when changing.
+ // This can go in a dedicated constants file if desired.
+ public static final String VENDOR_ID_QUERY_PARAM = "vendor_id";
+ private VendorService vendorService;
+ private ProductService productService;
+ private ObjectMapper objectMapper;
- public Controller(VendorService vendorService, ProductService productService){
+ public Controller(VendorService vendorService, ProductService productService) {
this.vendorService = vendorService;
this.productService = productService;
+ // Moving the initialization of object mapper to the constructor makes it get called once, instead of
+ // once per API request. More efficient code.
+ objectMapper = new ObjectMapper();
}
@@ -32,14 +40,14 @@ public Javalin getAPI() {
//VENDORS
app.post("vendor", context -> {
try {
- ObjectMapper om = new ObjectMapper();
- Vendor v = om.readValue(context.body(), Vendor.class);
- vendorService.saveVendor(v);
- context.status(201);
- context.json(v);
+ Vendor vendor = objectMapper.readValue(context.body(), Vendor.class);
+ vendorService.saveVendor(vendor);
+ // Using constants can help with clarity
+ context.status(HttpStatus.CREATED);
+ context.json(vendor);
} catch (JsonProcessingException e) {
context.result(e.getMessage());
- context.status(400);
+ context.status(HttpStatus.BAD_REQUEST);
}
});
@@ -49,39 +57,43 @@ public Javalin getAPI() {
});
app.get("vendor/{vendor_id}", context -> {
- int vendorID = Integer.parseInt(context.pathParam("vendor_id"));
- try{
+ int vendorID = Integer.parseInt(context.pathParam(VENDOR_ID_QUERY_PARAM));
+ try {
Vendor v = vendorService.getVendorById(vendorID);
context.json(v);
- }catch (VendorException e){
+ } catch (VendorException e) {
context.status(404);
context.result(e.getMessage());
}
});
app.put("vendor/{vendor_id}", context -> {
- ObjectMapper om = new ObjectMapper();
- Vendor v = om.readValue(context.body(), Vendor.class);
- int id = Integer.parseInt(context.pathParam("vendor_id"));
- try{
+ Vendor v = objectMapper.readValue(context.body(), Vendor.class);
+ int id = Integer.parseInt(context.pathParam(VENDOR_ID_QUERY_PARAM));
+ try {
vendorService.updateVendor(v, id);
context.json(v);
- }catch (VendorException e){
+ } catch (VendorException e) {
context.status(400);
context.result(e.getMessage());
}
});
- //PRODUCTS
+ // Separating out logically separate code can help organize and enhance readability
+ initializeProductEndpoints(app);
+
+ return app;
+ }
+
+ private void initializeProductEndpoints(Javalin app) {
app.post("product", context -> {
- ObjectMapper om = new ObjectMapper();
- Product p = om.readValue(context.body(), Product.class);
- try{
+ Product p = objectMapper.readValue(context.body(), Product.class);
+ try {
productService.saveProduct(p);
context.status(201);
context.json(p);
- }catch(ProductException e){
+ } catch (ProductException e) {
context.status(400);
context.result(e.getMessage());
}
@@ -94,10 +106,10 @@ public Javalin getAPI() {
app.get("product/{product_id}", context -> {
int productID = Integer.parseInt(context.pathParam("product_id"));
- try{
+ try {
Product p = productService.getProductById(productID);
context.json(p);
- }catch (ProductException e){
+ } catch (ProductException e) {
context.status(400);
context.result(e.getMessage());
}
@@ -106,23 +118,22 @@ public Javalin getAPI() {
///RETURNING ALL PRODUCTS
app.get("product?soldBy={sold_by}", context -> {
int soldBy = Integer.parseInt(context.pathParam("sold_by"));
- try{
+ try {
List p = productService.getProductByVendor(soldBy);
context.json(p);
- }catch (ProductException e){
+ } catch (ProductException e) {
context.status(400);
context.result(e.getMessage());
}
});
app.put("product/{product_id}", context -> {
- ObjectMapper om = new ObjectMapper();
- Product p = om.readValue(context.body(), Product.class);
+ Product p = objectMapper.readValue(context.body(), Product.class);
int id = Integer.parseInt(context.pathParam("product_id"));
- try{
+ try {
productService.updateProduct(p, id);
context.json(p);
- }catch (ProductException e){
+ } catch (ProductException e) {
context.status(400);
context.result(e.getMessage());
}
@@ -133,8 +144,5 @@ public Javalin getAPI() {
productService.deleteProduct(productID);
context.status(200);
});
-
-
- return app;
}
}
diff --git a/src/main/java/DAO/VendorDAO.java b/src/main/java/DAO/VendorDAO.java
index 7ead4c6..9b6bf65 100644
--- a/src/main/java/DAO/VendorDAO.java
+++ b/src/main/java/DAO/VendorDAO.java
@@ -29,6 +29,26 @@ public void insertVendor(Vendor v){
}
}
+ //get vendor from table "Vendor" with a matching name
+ public List getVendorsByName(String vendorName) {
+ List vendorList = new ArrayList<>();
+ try{
+ PreparedStatement ps = conn.prepareStatement("select * from Vendor where vendor_name = ?");
+ ps.setString(1, vendorName);
+ ResultSet resultSet = ps.executeQuery();
+ while (resultSet.next()) {
+ int resultID = resultSet.getInt("vendor_id");
+ String resultName = resultSet.getString("vendor_name");
+ Vendor v = new Vendor(resultID, resultName);
+ vendorList.add(v);
+ }
+ }catch (SQLException e) {
+ //add better messaging
+ e.printStackTrace();
+ }
+ return vendorList;
+ }
+
//get all vendors from table "Vendor"
public List getVendors(){
List vendorList = new ArrayList<>();
diff --git a/src/main/java/Model/Vendor.java b/src/main/java/Model/Vendor.java
index a4a273a..dc3edaa 100644
--- a/src/main/java/Model/Vendor.java
+++ b/src/main/java/Model/Vendor.java
@@ -3,8 +3,10 @@
import java.util.Objects;
public class Vendor {
- public int vendorId;
- public String vendorName;
+ // We have getters and setter so that we can control how these fields are accessed. Making them
+ // private forces consumers to use these methods instead of accessing the fields directly.
+ private int vendorId;
+ private String vendorName;
public Vendor(){
diff --git a/src/main/java/Service/VendorService.java b/src/main/java/Service/VendorService.java
index 5f036d7..8cf0091 100644
--- a/src/main/java/Service/VendorService.java
+++ b/src/main/java/Service/VendorService.java
@@ -22,7 +22,9 @@ public VendorService() {
public void saveVendor(Vendor v) throws VendorException {
if (v.getVendorName().isEmpty()) {
throw new VendorException("Vendor Name cannot be null");
- } else if (vendorDAO.getVendors().contains(v)){ //update to be only name and not both params
+
+ // More efficient to not pull the whole database and instead pull a small subset as needed.
+ } else if (!vendorDAO.getVendorsByName(v.getVendorName()).isEmpty()){ //update to be only name and not both params
throw new VendorException("Vendor already exists");
}
vendorDAO.insertVendor(v);
diff --git a/src/main/java/Util/ConnectionSingleton.java b/src/main/java/Util/ConnectionSingleton.java
index 1f6bc45..e196f05 100644
--- a/src/main/java/Util/ConnectionSingleton.java
+++ b/src/main/java/Util/ConnectionSingleton.java
@@ -19,7 +19,7 @@ public class ConnectionSingleton {
/**
* url will represent our connection string. Since this is an in-memory db, we will represent a file location to store the data
*/
- private static String url = "jdbc:h2:./h2/db";
+ private static String URL = "jdbc:h2:./h2/db"; // SCREAMING_SNAKE_CASE is standard for constants.
/**
* Default username for connecting to h2
*/
@@ -40,7 +40,7 @@ public class ConnectionSingleton {
public static Connection getConnection(){
if(connection == null){
try {
- connection = DriverManager.getConnection(url, username, password);
+ connection = DriverManager.getConnection(URL, username, password);
resetTestDatabase();
} catch (SQLException e) {
e.printStackTrace();
diff --git a/target/classes/Application.class b/target/classes/Application.class
deleted file mode 100644
index aa154d5..0000000
Binary files a/target/classes/Application.class and /dev/null differ
diff --git a/target/classes/Util/ConnectionSingleton.class b/target/classes/Util/ConnectionSingleton.class
deleted file mode 100644
index 52ddbad..0000000
Binary files a/target/classes/Util/ConnectionSingleton.class and /dev/null differ