I'm trying to create a Hello World application with quarkus. I have many troubles making it work.
Here are my classes :
import java.time.Duration;
import io.quarkus.hibernate.reactive.panache.Panache;
import io.quarkus.hibernate.reactive.panache.PanacheEntityBase;
import io.quarkus.hibernate.reactive.panache.common.WithSession;
import io.quarkus.hibernate.reactive.panache.common.WithSessionOnDemand;
import io.smallrye.mutiny.Uni;
import jakarta.persistence.Cacheable;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Cacheable
@Entity
@Table(name = "category", schema = "administration")
@WithSessionOnDemand
public class Category extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long id;
public String name;
public static Uni<Category > add(Category cat) {
return Panache
.withTransaction(cat::persist)
.replaceWith(cat)
.ifNoItem()
.after(Duration.ofMillis(10000))
.fail()
.onFailure()
.transform(t -> new IllegalStateException(t));
}
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public Uni<List<Category>> list2() {
// Create and persist a new category
Category category = new Category();
category.name = "test quarkus 3";
Category.add(category)
.onItem().transform(id -> id.id)
.subscribe().with(e -> System.out.println(e));
// Return the list of categories
return Category.listAll();
}
When I hit the GET endpoint, the category is created.
But If I hit it 3 times in a row, I get the following error :
ERROR [io.qua.mut.run.MutinyInfrastructure] (vert.x-eventloop-thread-1) Mutiny had to drop the following exception: java.lang.IllegalStateException: java.lang.IllegalStateException: No current Mutiny.Session found - no reactive session was found in the context and the context was not marked to open a new session lazily - you might need to annotate the business method with @WithSession at org.test.category.Category.lambda$1(Category.java:39)
So I tried to annotate my Category
class with @WithSession
and then with @WithSessionOnDemand
but nothing worked.
What am I doing wrong ?
you need to chain your create
and query
operations in a stream style thus they can access the session from thin air.
Entity class:
import jakarta.persistence.Cacheable;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import io.quarkus.hibernate.reactive.panache.PanacheEntity;
@Entity
@Cacheable
public class Fruit extends PanacheEntity {
@Column(length = 40, unique = false)
public String name;
}
Service Class:
import io.quarkus.hibernate.reactive.panache.Panache;
import io.quarkus.panache.common.Sort;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import java.time.Duration;
import java.util.List;
// first method
@Path("/fruits")
@ApplicationScoped
public class FruitResource {
@GET
public Uni<List<Fruit>> get() {
return Fruit.listAll(Sort.by("name"));
}
@POST
public Uni<List<Fruit>> create(Fruit fruit) {
Uni<Long> createStage = Panache
.withTransaction(fruit::persist)
.replaceWith(fruit)
.ifNoItem()
.after(Duration.ofMillis(10000))
.fail()
.onFailure()
.transform(t -> {
System.out.println("exception happen lalal");
t.printStackTrace();
return new IllegalStateException(t);
})
.onItem().transform(item -> {
System.out.println("fruit is created: " + item.id);
return item.id;
});
Uni<List<Fruit>> queryAllFruitsStage = Fruit.listAll();
return createStage.chain(() -> queryAllFruitsStage);
}
}
// second method
@Path("/fruits")
@ApplicationScoped
public class FruitResource {
@GET
public Uni<List<Fruit>> get() {
return Fruit.listAll(Sort.by("name"));
}
@POST
public Uni<List<Fruit>> create(Fruit fruit) {
return Panache
.withTransaction(fruit::persist)
.replaceWith(fruit)
.ifNoItem()
.after(Duration.ofMillis(10000))
.fail()
.onFailure()
.transform(t -> {
System.out.println("exception happen lalal");
t.printStackTrace();
return new IllegalStateException(t);
})
.onItem()
.transformToUni(item -> Fruit.listAll());
}
}
The curl test:
curl --location 'localhost:8080/fruits' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{
"name": "fruit1"
}'
you may have a look at the Mutiny Patterns part at the docs Quarkus - Mutiny Primer and have a better understanding of reactive programming.