Skip to content

Commit 4859954

Browse files
author
hospel
authored
BENCH-207: Bench 207 (#92)
* initial changes * find products by categories id * adding some integration tests * syntax improvement * type removal * initial changes * find products by categories id * adding some integration tests * syntax improvement * type removal * move code to categoryservice * initial changes * find products by categories id * adding some integration tests * syntax improvement * type removal * rebase * rebase * rebase * syntax improvement * type removal * rebase * rebase * query rename * refactoring for ProductResponse * rebase * rebase * syntax improvement * type removal * rebase * syntax improvement * type removal * rebase * query rename * rebase * refactoring * removing unneccesary validation * remove imports * field rename * initial changes * find products by categories id * adding some integration tests * syntax improvement * type removal * rebase * rebase * rebase * syntax improvement * type removal * rebase * rebase * rebase * rebase * syntax improvement * type removal * rebase * syntax improvement * type removal * rebase * query rename * rebase * rebase * rebase * rebase * type removal * rebase * rebase * rebase * type removal * rebase * rebase * rebase * removing unneccesary validation * remove imports * field rename * test checkstyle * rebase * small syntax optimization
1 parent a109dd6 commit 4859954

31 files changed

+388
-153
lines changed

src/main/java/com/answerdigital/answerking/config/SecurityConfig.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,12 @@ public InMemoryUserDetailsManager userDetailsManager() {
4949
return new InMemoryUserDetailsManager(
5050
List.of("paul", "john", "ringo", "george")
5151
.stream()
52-
.map(user -> {
53-
return User.withUsername(user)
54-
.password(COMMON_PASSWORD)
55-
.authorities(COMMON_ROLE)
56-
.build();
57-
}).toList()
52+
.map(user ->
53+
User.withUsername(user)
54+
.password(COMMON_PASSWORD)
55+
.authorities(COMMON_ROLE)
56+
.build()
57+
).toList()
5858
);
5959
}
6060

src/main/java/com/answerdigital/answerking/controller/CategoryController.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.answerdigital.answerking.model.Category;
55
import com.answerdigital.answerking.request.CategoryRequest;
66
import com.answerdigital.answerking.response.CategoryResponse;
7+
import com.answerdigital.answerking.response.ProductResponse;
78
import com.answerdigital.answerking.service.CategoryService;
89
import io.swagger.v3.oas.annotations.Operation;
910
import io.swagger.v3.oas.annotations.media.Content;
@@ -76,6 +77,18 @@ public ResponseEntity<Category> getCategoryById(@PathVariable @NotNull final Lon
7677
return new ResponseEntity<>(categoryService.findById(categoryId), HttpStatus.OK);
7778
}
7879

80+
@Operation(summary = "Get all products in a category.")
81+
@ApiResponses(value = {
82+
@ApiResponse(responseCode = "200", description = "When all the products have been returned.",
83+
content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Category.class)) }),
84+
@ApiResponse(responseCode = "404", description = "When the category with the given id does not exist.",
85+
content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class)) })
86+
})
87+
@GetMapping("/{categoryId}/products")
88+
public ResponseEntity<Collection<ProductResponse>> fetchProductsByCategory(@PathVariable @NotNull final Long categoryId) {
89+
return new ResponseEntity<>(categoryService.findProductsByCategoryId(categoryId), HttpStatus.OK);
90+
}
91+
7992
@Operation(summary = "Add product to a category.")
8093
@ApiResponses(value = {
8194
@ApiResponse(responseCode = "200", description = "Add product to a category.",

src/main/java/com/answerdigital/answerking/mapper/CategoryMapper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public interface CategoryMapper {
2020
@Mapping(target = "lastUpdated", expression = "java(DateTimeUtility.getDateTimeAsString())")
2121
Category updateRequestToCategory(@MappingTarget Category category, CategoryRequest updateCategoryRequest);
2222

23-
@Mapping(target = "productIds",
23+
@Mapping(target = "products",
2424
expression = "java(category.getProducts().stream().map(product -> product.getId()).collect(Collectors.toList()) )")
2525
CategoryResponse convertCategoryEntityToCategoryResponse(Category category);
2626

src/main/java/com/answerdigital/answerking/mapper/ProductMapper.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,20 @@
22

33
import com.answerdigital.answerking.model.Product;
44
import com.answerdigital.answerking.request.ProductRequest;
5+
import com.answerdigital.answerking.response.ProductResponse;
56
import org.mapstruct.Mapper;
67
import org.mapstruct.Mapping;
78
import org.mapstruct.MappingTarget;
9+
import java.util.List;
810

9-
@Mapper(componentModel = "spring")
11+
@Mapper(componentModel = "spring", imports = {List.class})
1012
public interface ProductMapper {
1113
@Mapping(target = "retired", constant = "false")
1214
Product addRequestToProduct(ProductRequest productRequest);
1315

1416
Product updateRequestToProduct(@MappingTarget Product product, ProductRequest productRequest);
17+
18+
@Mapping(target = "categories", expression = "java(List.of(product.getCategory().getId()))")
19+
ProductResponse convertProductEntityToProductResponse(Product product);
20+
1521
}

src/main/java/com/answerdigital/answerking/model/Category.java

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,12 @@
99
import lombok.NoArgsConstructor;
1010
import lombok.Setter;
1111

12-
import javax.persistence.Entity;
12+
import javax.persistence.OneToMany;
1313
import javax.persistence.FetchType;
14+
import javax.persistence.Entity;
1415
import javax.persistence.GeneratedValue;
1516
import javax.persistence.GenerationType;
1617
import javax.persistence.Id;
17-
import javax.persistence.JoinColumn;
18-
import javax.persistence.JoinTable;
19-
import javax.persistence.ManyToMany;
2018
import javax.validation.constraints.NotBlank;
2119
import javax.validation.constraints.Pattern;
2220
import java.util.HashSet;
@@ -54,11 +52,7 @@ public class Category {
5452

5553
private boolean retired;
5654

57-
@ManyToMany(fetch = FetchType.EAGER)
58-
@JoinTable(
59-
name = "product_category",
60-
joinColumns = {@JoinColumn(name = "category_id")},
61-
inverseJoinColumns = {@JoinColumn(name = "product_id")})
55+
@OneToMany(mappedBy="category", fetch = FetchType.EAGER)
6256
@JsonIgnore
6357
private Set<Product> products = new HashSet<>();
6458

src/main/java/com/answerdigital/answerking/model/Product.java

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@
1010
import lombok.NoArgsConstructor;
1111
import lombok.Setter;
1212

13-
import javax.persistence.CascadeType;
1413
import javax.persistence.Column;
14+
import javax.persistence.PreRemove;
15+
import javax.persistence.CascadeType;
16+
import javax.persistence.OneToMany;
17+
import javax.persistence.ManyToOne;
18+
import javax.persistence.JoinColumn;
19+
import javax.persistence.GenerationType;
1520
import javax.persistence.Entity;
16-
import javax.persistence.FetchType;
1721
import javax.persistence.GeneratedValue;
18-
import javax.persistence.GenerationType;
1922
import javax.persistence.Id;
20-
import javax.persistence.ManyToMany;
21-
import javax.persistence.OneToMany;
22-
import javax.persistence.PreRemove;
2323
import javax.persistence.Table;
2424
import java.math.BigDecimal;
2525
import java.math.RoundingMode;
@@ -51,9 +51,9 @@ public class Product {
5151
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
5252
private boolean retired;
5353

54-
@JsonIgnore
55-
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "products")
56-
private Set<Category> categories = new HashSet<>();
54+
@ManyToOne
55+
@JoinColumn(name="category_id", nullable=false)
56+
private Category category;
5757

5858
@OneToMany(mappedBy = "product", cascade = CascadeType.ALL)
5959
@JsonIgnore
@@ -63,13 +63,12 @@ public Product(final String name, final String description, final BigDecimal pri
6363
this.name = name;
6464
this.description = description;
6565
this.price = price;
66-
this.categories = new HashSet<>();
6766
this.retired = isRetired;
6867
}
6968

7069
@PreRemove
7170
private void removeProductsFromCategories() {
72-
categories.forEach(category -> category.removeProduct(this));
71+
category.removeProduct(this);
7372
}
7473

7574
public BigDecimal getPrice() {

src/main/java/com/answerdigital/answerking/repository/CategoryRepository.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import com.answerdigital.answerking.model.Category;
44
import org.springframework.data.repository.PagingAndSortingRepository;
55
import org.springframework.stereotype.Repository;
6-
76
import java.util.Set;
87

98
@Repository
@@ -13,4 +12,5 @@ public interface CategoryRepository extends PagingAndSortingRepository<Category,
1312
boolean existsByNameAndIdIsNot(String name, Long id);
1413

1514
Set<Category> findAll();
15+
1616
}

src/main/java/com/answerdigital/answerking/repository/ProductRepository.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,7 @@ public interface ProductRepository extends PagingAndSortingRepository<Product, L
1313
boolean existsByNameAndIdIsNot(String name, Long id);
1414

1515
List<Product> findAll();
16+
17+
List<Product> findProductsByCategoryId(Long categoryId);
18+
1619
}

src/main/java/com/answerdigital/answerking/response/CategoryResponse.java

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55
import lombok.Builder;
66
import lombok.Data;
77
import lombok.NoArgsConstructor;
8-
9-
import javax.validation.constraints.NotBlank;
10-
import javax.validation.constraints.Pattern;
118
import java.util.List;
129

1310
@Data
@@ -16,27 +13,23 @@
1613
@AllArgsConstructor
1714
public class CategoryResponse {
1815

16+
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
1917
private Long id;
2018

21-
@NotBlank
22-
@Pattern(regexp = "^[a-zA-Z\s-]*",
23-
message = "Category name must only contain letters, spaces and dashes")
2419
private String name;
2520

26-
@NotBlank
27-
@Pattern(regexp = "^[a-zA-Z\s.,!?0-9-']*",
28-
message = "Category description can only contain letters, numbers, spaces and !?-.,' punctuation")
2921
private String description;
3022

3123
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
32-
private List<Long> productIds;
24+
private List<Long> products;
3325

3426
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
3527
private String createdOn;
3628

3729
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
3830
private String lastUpdated;
3931

32+
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
4033
private boolean retired;
4134

4235
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.answerdigital.answerking.response;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Data;
7+
import lombok.NoArgsConstructor;
8+
9+
import javax.validation.constraints.NotNull;
10+
import javax.validation.constraints.DecimalMin;
11+
import javax.validation.constraints.Digits;
12+
import javax.validation.constraints.NotBlank;
13+
import javax.validation.constraints.Pattern;
14+
import java.math.BigDecimal;
15+
import java.util.List;
16+
17+
@Data
18+
@Builder
19+
@NoArgsConstructor
20+
@AllArgsConstructor
21+
public class ProductResponse {
22+
23+
@NotBlank
24+
private Long id;
25+
26+
@Pattern(regexp = "^[a-zA-Z\s-]*",
27+
message = "Product name must only contain letters, spaces and dashes")
28+
private String name;
29+
30+
@NotBlank
31+
@Pattern(regexp = "^[a-zA-Z\s.,!?0-9-']*",
32+
message = "Product description can only contain letters, numbers, spaces and !?-.,' punctuation")
33+
private String description;
34+
35+
@Digits(integer = 12, fraction = 2, message = "Product price is invalid")
36+
@DecimalMin(value = "0.0", inclusive = false, message = "Product price cannot be less than 0")
37+
@NotNull
38+
private BigDecimal price;
39+
40+
private List<Long> categories;
41+
42+
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
43+
private boolean retired;
44+
45+
}

0 commit comments

Comments
 (0)