Skip to content

Commit b4cd643

Browse files
committed
creating products
1 parent ebad2e5 commit b4cd643

File tree

13 files changed

+371
-33
lines changed

13 files changed

+371
-33
lines changed

src/main/java/app/domain/employees/EmployeeResource.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
public class EmployeeResource {
2424
@Inject
2525
Validator validator;
26+
2627
@Inject
2728
private EmployeeRepository employeeRepository;
29+
2830
@Inject
2931
private UserRepository userRepository;
3032

@@ -47,9 +49,8 @@ public TemplateInstance list() {
4749
public TemplateInstance createEmployee(CreateEmployeeForm form) {
4850
var violations = validator.validate(form);
4951
if (!violations.isEmpty()) {
50-
Map<String, String> errors = violations.stream()
51-
.collect(Collectors
52-
.toMap(v -> v.getPropertyPath().toString(),
52+
var errors = violations.stream()
53+
.collect(Collectors.toMap(v -> v.getPropertyPath().toString(),
5354
ConstraintViolation::getMessage));
5455
return Templates.create().data("errors", errors).data("form", form);
5556
}
@@ -74,7 +75,6 @@ public TemplateInstance createEmployee(CreateEmployeeForm form) {
7475
@CheckedTemplate(requireTypeSafeExpressions = false)
7576
public static class Templates {
7677
public static native TemplateInstance list(List<Employee> employees);
77-
7878
public static native TemplateInstance create();
7979
}
8080

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package app.domain.products;
2+
3+
import jakarta.validation.constraints.NotBlank;
4+
import jakarta.validation.constraints.NotEmpty;
5+
import jakarta.validation.constraints.NotNull;
6+
import jakarta.ws.rs.FormParam;
7+
import org.jboss.resteasy.reactive.multipart.FileUpload;
8+
9+
import java.math.BigDecimal;
10+
import java.util.List;
11+
12+
public record CreateProductForm(
13+
@FormParam("name") @NotBlank(message = "Name must not be empty") String name,
14+
@FormParam("description") @NotBlank(message = "Description must not be empty") String description,
15+
@FormParam("photos") @NotEmpty(message = "At least 1 image must be provided") List<FileUpload> photos,
16+
@FormParam("inStock") int inStock,
17+
@FormParam("price") @NotNull BigDecimal price) {
18+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package app.domain.products;
2+
3+
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
4+
import jakarta.persistence.*;
5+
6+
@Entity
7+
@Table(name = "photo")
8+
public class Photo extends PanacheEntityBase {
9+
@Id
10+
@GeneratedValue(strategy = GenerationType.IDENTITY)
11+
@Column(name = "id")
12+
private Long id;
13+
14+
@Column(name = "url", nullable = false)
15+
private String url;
16+
17+
@Column(name = "name", nullable = false)
18+
private String name;
19+
20+
@Column(name = "file_size", nullable = false)
21+
private long size;
22+
23+
@ManyToOne(fetch = FetchType.LAZY, optional = false)
24+
@JoinColumn(name = "product_id")
25+
private Product product;
26+
27+
public Photo() {
28+
}
29+
30+
public Photo(String url, String name, int size) {
31+
this.url = url;
32+
this.name = name;
33+
this.size = size;
34+
}
35+
36+
public Long getId() {
37+
return id;
38+
}
39+
40+
public void setId(Long id) {
41+
this.id = id;
42+
}
43+
44+
public String getUrl() {
45+
return url;
46+
}
47+
48+
public void setUrl(String url) {
49+
this.url = url;
50+
}
51+
52+
public String getName() {
53+
return name;
54+
}
55+
56+
public void setName(String name) {
57+
this.name = name;
58+
}
59+
60+
public long getSize() {
61+
return size;
62+
}
63+
64+
public void setSize(long size) {
65+
this.size = size;
66+
}
67+
68+
public void setProduct(Product product) {
69+
this.product = product;
70+
}
71+
72+
public Product getProduct() {
73+
return product;
74+
}
75+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package app.domain.products;
2+
3+
import io.quarkus.hibernate.orm.panache.PanacheRepository;
4+
import jakarta.enterprise.context.ApplicationScoped;
5+
6+
@ApplicationScoped
7+
public class PhotoRepository implements PanacheRepository<Photo> {
8+
9+
}

src/main/java/app/domain/products/Product.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import jakarta.persistence.*;
55

66
import java.math.BigDecimal;
7+
import java.util.ArrayList;
8+
import java.util.List;
79
import java.util.Objects;
810

911
@Entity
@@ -26,6 +28,13 @@ public class Product extends PanacheEntityBase {
2628
@Column(name = "stock")
2729
private int stock;
2830

31+
@OneToMany(
32+
mappedBy = "product",
33+
cascade = CascadeType.ALL,
34+
orphanRemoval = true
35+
)
36+
private final List<Photo> photos = new ArrayList<>();
37+
2938
public Product(){}
3039

3140
public Product(String name, String description, BigDecimal price, int stock){
@@ -75,6 +84,10 @@ public void setStock(int stock) {
7584
this.stock = stock;
7685
}
7786

87+
public List<Photo> getPhotos() {
88+
return photos;
89+
}
90+
7891
@Override
7992
public boolean equals(Object o) {
8093
if (o == null || getClass() != o.getClass()) return false;

src/main/java/app/domain/products/ProductController.java

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/main/java/app/domain/products/ProductRepository.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,15 @@
22

33
import io.quarkus.hibernate.orm.panache.PanacheRepository;
44
import jakarta.enterprise.context.ApplicationScoped;
5+
import jakarta.inject.Inject;
56

67
@ApplicationScoped
78
public class ProductRepository implements PanacheRepository<Product> {
89

10+
@Inject
11+
PhotoRepository photoRepository;
12+
13+
public void savePhoto(Photo photo) {
14+
this.photoRepository.persist(photo);
15+
}
916
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package app.domain.products;
2+
3+
import app.domain.employees.Employee;
4+
import app.domain.employees.EmployeeResource;
5+
import io.quarkus.qute.CheckedTemplate;
6+
import io.quarkus.qute.TemplateInstance;
7+
import io.smallrye.common.annotation.Blocking;
8+
import jakarta.inject.Inject;
9+
import jakarta.transaction.Transactional;
10+
import jakarta.validation.ConstraintViolation;
11+
import jakarta.validation.Validator;
12+
import jakarta.ws.rs.Consumes;
13+
import jakarta.ws.rs.GET;
14+
import jakarta.ws.rs.POST;
15+
import jakarta.ws.rs.Path;
16+
import jakarta.ws.rs.core.MediaType;
17+
import org.eclipse.microprofile.config.inject.ConfigProperty;
18+
import org.jboss.resteasy.reactive.multipart.FileUpload;
19+
20+
import java.io.IOException;
21+
import java.nio.file.Files;
22+
import java.nio.file.Paths;
23+
import java.util.List;
24+
import java.util.Map;
25+
import java.util.UUID;
26+
import java.util.stream.Collectors;
27+
28+
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
29+
30+
@Path("/products")
31+
@Blocking
32+
public class ProductResource {
33+
@Inject
34+
Validator validator;
35+
36+
@Inject
37+
ProductRepository repository;
38+
39+
@ConfigProperty(name = "photos.dir")
40+
String photosDir;
41+
42+
@GET
43+
public TemplateInstance findProducts() {
44+
List<Product> products = repository.findAll().list();
45+
return Templates.list(products);
46+
}
47+
48+
@GET
49+
@Path("/new")
50+
public TemplateInstance newProduct() {
51+
return Templates.create().data("form", null).data("errors", Map.of());
52+
}
53+
54+
@POST
55+
@Blocking
56+
@Consumes(MediaType.MULTIPART_FORM_DATA)
57+
@Transactional
58+
public TemplateInstance createProduct(CreateProductForm form) throws IOException {
59+
var violations = validator.validate(form);
60+
if (!violations.isEmpty()) {
61+
var errors = violations.stream()
62+
.collect(Collectors.toMap(v -> v.getPropertyPath().toString(),
63+
ConstraintViolation::getMessage));
64+
return EmployeeResource.Templates.create().data("errors", errors).data("form", form);
65+
}
66+
67+
//create product
68+
Product product = new Product();
69+
product.setName(form.name());
70+
product.setDescription(form.description());
71+
product.setPrice(form.price());
72+
product.setStock(form.inStock());
73+
repository.persist(product);
74+
75+
for (FileUpload file : form.photos()) {
76+
//persist photo data in database
77+
var photo = new Photo();
78+
var filename = generateUniqueFileName(file.fileName());
79+
photo.setName(filename);
80+
photo.setSize(file.size());
81+
photo.setUrl(photosDir.concat("/").concat(filename));
82+
photo.setProduct(product);
83+
repository.savePhoto(photo);
84+
85+
//copy file in filesystem
86+
var path = file.uploadedFile();
87+
Files.copy(path, Paths.get(photosDir).resolve(filename), REPLACE_EXISTING);
88+
}
89+
90+
return Templates.list(Employee.listAll());
91+
}
92+
93+
private String generateUniqueFileName(String originalFileName) {
94+
String extension = "";
95+
int dotIndex = originalFileName.lastIndexOf('.');
96+
if (dotIndex > 0 && dotIndex < originalFileName.length() - 1) {
97+
extension = originalFileName.substring(dotIndex);
98+
}
99+
extension = extension.replaceAll("[^a-zA-Z0-9.]", "");
100+
return UUID.randomUUID() + extension;
101+
}
102+
103+
@CheckedTemplate(requireTypeSafeExpressions = false)
104+
public static class Templates {
105+
public static native TemplateInstance list(List<Product> products);
106+
107+
public static native TemplateInstance create();
108+
}
109+
110+
}

src/main/resources/application.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ quarkus.hibernate-orm.database.generation=none
1111
%dev.quarkus.hibernate-orm.log.sql=true
1212
%dev.quarkus.flyway.migrate-at-start=true
1313
%dev.quarkus.flyway.locations=db/migration,db/testdata
14+
photos.dir=/home/victoralcantara/code/photos

src/main/resources/db/migration/V7.1__insert_users_and_authorites_table.sql

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)