Skip to content

Commit

Permalink
Enhance Quarkus sample project
Browse files Browse the repository at this point in the history
- Fix blocking and transactional annotations
- Add form url encoded UI elements to add booking and supply
  • Loading branch information
christophd committed Nov 25, 2023
1 parent c2ffa65 commit e1f3edb
Show file tree
Hide file tree
Showing 13 changed files with 276 additions and 22 deletions.
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,10 @@ bin
.gradle
build
test-output
sun-jaxb.episode
sun-jaxb.episode

.camel-jbang
.yaks-jbang
.citrus-jbang

_output
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.smallrye.reactive.messaging.annotations.Blocking;
import io.smallrye.reactive.messaging.annotations.Merge;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import org.apache.camel.demo.model.Booking;
import org.apache.camel.demo.model.Product;
import org.apache.camel.demo.model.Supply;
Expand Down Expand Up @@ -54,7 +54,7 @@ public class BookingEvents {

@Incoming("booking-events")
@Outgoing("booking-added")
@Transactional
@Blocking
public Booking processEvent(Booking booking) throws JsonProcessingException {
LOG.info(String.format("Processing booking for product: %s", booking.getProduct().getName()));
if (booking.getProduct().getId() == null) {
Expand All @@ -69,7 +69,7 @@ public Booking processEvent(Booking booking) throws JsonProcessingException {

@Incoming("booking-added")
@Merge
@Transactional
@Blocking
public void onAdded(Booking booking) throws JsonProcessingException {
Optional<Supply> matchingSupply = supplyService.findAvailable(booking);
if (matchingSupply.isPresent()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@ public class BookingService {
@Channel("completed-events")
MutinyEmitter<BookingCompletedEvent> completedEmitter;

@Transactional
public Booking findById(Long id) {
return em.createNamedQuery("Bookings.findById", Booking.class)
.setParameter("id", id)
.getSingleResult();
}

@Transactional
public Optional<Booking> findMatching(Supply supply) {
List<Booking> matching = em.createNamedQuery("Bookings.findMatching", Booking.class)
.setParameter("product", supply.getProduct().getId())
Expand All @@ -72,6 +74,10 @@ public Optional<Booking> findMatching(Supply supply) {

@Transactional
public void add(Booking booking) {
if (booking.getId() != null) {
booking.setId(null);
}

em.persist(booking);
}

Expand All @@ -80,6 +86,7 @@ public void update(Booking booking) {
em.merge(booking);
}

@Transactional
public List<Booking> findAll() {
return em.createNamedQuery("Bookings.findAll", Booking.class).getResultList();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,26 @@

package org.apache.camel.demo;

import java.util.Optional;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.quarkus.qute.Template;
import io.quarkus.qute.TemplateInstance;
import io.smallrye.reactive.messaging.MutinyEmitter;
import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import org.apache.camel.demo.model.Booking;
import org.apache.camel.demo.model.Product;
import org.apache.camel.demo.model.Supply;
import org.eclipse.microprofile.reactive.messaging.Channel;
import org.jboss.logging.Logger;
import org.reactivestreams.Publisher;

/**
Expand All @@ -33,15 +45,17 @@
@Path("/")
public class FoodMarketResource {

private static final Logger LOG = Logger.getLogger(FoodMarketResource.class);

@Inject
Template index;

@Inject
@Channel("booking-events-stream")
@Channel("booking-added-events-stream")
Publisher<String> bookingEvents;

@Inject
@Channel("supply-events-stream")
@Channel("supply-added-events-stream")
Publisher<String> supplyEvents;

@Inject
Expand All @@ -50,25 +64,79 @@ public class FoodMarketResource {
@Inject
SupplyService supplyService;

@Inject
ProductService productService;

@Inject
ObjectMapper mapper;

@Inject
@Channel("booking-added")
MutinyEmitter<Booking> bookingAddedEmitter;

@Inject
@Channel("supply-added")
MutinyEmitter<Supply> supplyAddedEmitter;

@GET
@Produces(MediaType.TEXT_HTML)
public TemplateInstance index() {
return index.data("bookings", bookingService.findAll())
.data("supplies", supplyService.findAll());
.data("supplies", supplyService.findAll())
.data("products", productService.findAll());
}

@GET
@Path("/bookings")
@Path("bookings")
@Produces(MediaType.SERVER_SENT_EVENTS)
public Publisher<String> bookingProcessor() {
return bookingEvents;
}

@GET
@Path("/supplies")
@Path("supplies")
@Produces(MediaType.SERVER_SENT_EVENTS)
public Publisher<String> supplyProcessor() {
return supplyEvents;
}

@POST
@Consumes({MediaType.APPLICATION_FORM_URLENCODED})
public TemplateInstance formSubmit(MultivaluedMap<String, String> form) throws JsonProcessingException {
String type = form.getFirst("type");
String productName = form.getFirst("product");
LOG.info(String.format("Processing booking for product: %s", productName));
Optional<Product> product = productService.findByName(productName);
if (product.isEmpty()) {
LOG.info(String.format("Failed to find product: %s", productName));
return index();
}

if ("booking".equals(type)) {
Booking booking = new Booking(form.getFirst("name"), product.get(),
Integer.parseInt(form.getFirst("amount")), Double.parseDouble(form.getFirst("price")));

bookingService.add(booking);
LOG.info("New booking: " + mapper.writeValueAsString(booking));

bookingAddedEmitter.send(booking).subscribe()
.with(
success -> LOG.info("Booking added event successfully sent"),
failure -> LOG.info("Booking added event failed: " + failure.getMessage())
);
} else if ("supply".equals(type)) {
Supply supply = new Supply(form.getFirst("name"), product.get(),
Integer.parseInt(form.getFirst("amount")), Double.parseDouble(form.getFirst("price")));

supplyService.add(supply);
LOG.info("New supply: " + mapper.writeValueAsString(supply));

supplyAddedEmitter.send(supply).subscribe()
.with(
success -> LOG.info("Supply added event successfully sent"),
failure -> LOG.info("Supply added event failed: " + failure.getMessage())
);
}
return index();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.smallrye.reactive.messaging.annotations.Blocking;
import io.smallrye.common.annotation.Blocking;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.apache.camel.demo.model.Product;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@ public class ProductService {
@Inject
EntityManager em;

@Transactional
public Product findById(Long id) {
return em.createNamedQuery("Products.findById", Product.class)
.setParameter("id", id)
.getSingleResult();
}

@Transactional
public Optional<Product> findByName(String name) {
try {
return Optional.of(em.createNamedQuery("Products.findByName", Product.class)
Expand All @@ -64,6 +66,7 @@ public void update(Product product) {
em.merge(product);
}

@Transactional
public List<Product> findAll() {
return em.createNamedQuery("Products.findAll", Product.class).getResultList();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.smallrye.reactive.messaging.annotations.Blocking;
import io.smallrye.reactive.messaging.annotations.Merge;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import org.apache.camel.demo.model.Booking;
import org.apache.camel.demo.model.Product;
import org.apache.camel.demo.model.Supply;
Expand Down Expand Up @@ -54,7 +54,7 @@ public class SupplyEvents {

@Incoming("supply-events")
@Outgoing("supply-added")
@Transactional
@Blocking
public Supply processEvent(Supply supply) throws JsonProcessingException {
LOG.info(String.format("Processing supply for product: %s", supply.getProduct().getName()));
if (supply.getProduct().getId() == null) {
Expand All @@ -69,7 +69,7 @@ public Supply processEvent(Supply supply) throws JsonProcessingException {

@Incoming("supply-added")
@Merge
@Transactional
@Blocking
public void onAdded(Supply supply) throws JsonProcessingException {
Optional<Booking> matchingBooking;
while ((matchingBooking = bookingService.findMatching(supply)).isPresent()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@ public class SupplyService {
@Inject
ObjectMapper objectMapper;

@Transactional
public Supply findById(Long id) {
return em.createNamedQuery("Supplies.findById", Supply.class)
.setParameter("id", id)
.getSingleResult();
}

@Transactional
public Optional<Supply> findAvailable(Booking booking) {
List<Supply> matching = em.createNamedQuery("Supplies.findMatching", Supply.class)
.setParameter("product", booking.getProduct().getId())
Expand All @@ -72,6 +74,10 @@ public Optional<Supply> findAvailable(Booking booking) {

@Transactional
public void add(Supply supply) {
if (supply.getId() != null) {
supply.setId(null);
}

em.persist(supply);
}

Expand All @@ -80,6 +86,7 @@ public void update(Supply supply) {
em.merge(supply);
}

@Transactional
public List<Supply> findAll() {
return em.createNamedQuery("Supplies.findAll", Supply.class).getResultList();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ quarkus.log.level=INFO
quarkus.container-image.registry=quay.io
quarkus.container-image.group=citrusframework

quarkus.hibernate-orm.database.generation=update
quarkus.hibernate-orm.database.generation=drop-and-create

quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=quarkus-test
Expand Down
Loading

0 comments on commit e1f3edb

Please sign in to comment.