I have a POST operation that should only occur if the result of another NamedQuery has a row count Greater Than ">" than a known value.
I am new to Mutiny and moreso hibernate-reactive. My current catastrophe looks like this:
package org.electricaltrainingalliance.attendees.selections.boundary;
import java.util.UUID;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.electricaltrainingalliance.attendees.selections.entity.AttendeeSelection;
import org.hibernate.reactive.mutiny.Mutiny.SessionFactory;
import org.jboss.logging.Logger;
import org.jboss.logging.Logger.Level;
import org.jboss.resteasy.reactive.RestPath;
import io.smallrye.mutiny.Uni;
@Path("selections")
@ApplicationScoped
@Produces("application/json")
@Consumes("application/json")
public class AttendeeSelectionsService {
private static final Logger LOGGER = Logger.getLogger(AttendeeSelectionsService.class.getName());
@Inject
SessionFactory sf;
@POST
public Uni<Response> create(AttendeeSelection selection) {
if (selection == null || !selection.isValid()) {
return Uni.createFrom()
.item(Response.status(400)
.entity("The Selection is not valid, please refer to the API Documentation.")::build);
}
Uni<Boolean> seatsAvailable = sf.withSession((s) -> s
.createNamedQuery(AttendeeSelection.findByOfferingId, AttendeeSelection.class)
.setParameter("offeringId", selection.getOffering().getOfferingId())
.getResultList()).onItem()
.transform(entity -> entity.size() >= selection.getOffering().getCapacity() ? Boolean.FALSE : Boolean.TRUE);
seatsAvailable.onItem().transformToUni(result -> {
if (!result) {
return Uni.createFrom()
.item(Response.status(409)
.entity("The Offering is no longer available.")::build);
} else {
sf.withTransaction((s, t) -> s.persist(selection))
.replaceWith(Response.ok(selection).status(Status.CREATED)::build)
.onFailure().transform(failure -> {
if (failure.getMessage().toLowerCase().contains("uk_unique_selection")) {
throw new WebApplicationException(
"A Selection with this information already exists.",
Status.CONFLICT);
} else {
LOGGER.log(Level.DEBUG, failure.getMessage(), failure);
throw new WebApplicationException(failure.getMessage(),
Status.INTERNAL_SERVER_ERROR);
}
});
}
});
}
...
}
Essentily, I have a query that returns a list of elements. The item being created, has a value that handles the maximum allowed.
I would like to:
I have tried an .await() on the NamedQuery to get a Boolean. I get the error This method should exclusively be invoked from a Vert.x EventLoop thread; currently running on thread 'executor-thread-0
I have tried in place of .transform as well as .transformToUni but it provides the context error This method must return a result of type Uni<Response>
of which all paths do, confusingly.
Much like promises in JS, passing the Uni is part of the issue, and I need to return from within the chain.
return seatsAvailable.onItem().transformToUni(result -> {
I could then handle the check on the result as a boolean and continue by returning the following:
return sf.withTransaction((s, t) -> s.persist(selection))