Search code examples
javaquarkusresteasymutiny

How to use a variable from Uni, Mutiny


I created a reactive resteasy service with Quarkus and Mutiny. In POST method I insert object in my PostgreSQL table and get an Uni< id > in return. I need to set this id as part of my Response class which contains f.ex. "id", "errorCode", "errorString" and other variables, but I struggle as id comes as Uni object and I don't know how to extract id from it.

Create method:

  public static Uni<Long> create(PgPool client, RetailPlace retailPlace) {
        return client.withTransaction(conn -> conn
                .preparedQuery("INSERT INTO retail_place (title) VALUES ($1) RETURNING id")
                .execute(Tuple.of(retailPlace.getRetailPlaceTitle()))
                .onItem().transformToUni(id -> conn.
                        preparedQuery("INSERT INTO retail_place_address (retail_place_id,region_code,city,locality_id,apartment,house,region,street) " +
                                "VALUES ($1,$2,$3,$4,$5,$6,$7,$8) returning retail_place_id")
                        .execute(Tuple.tuple(Arrays.asList(id.iterator().next().getLong("id"), retailPlace.getRetailPlaceAddress().getRegionCode(),
                                retailPlace.getRetailPlaceAddress().getCity(), retailPlace.getRetailPlaceAddress().getLocalityId(),
                                retailPlace.getRetailPlaceAddress().getApartment(), retailPlace.getRetailPlaceAddress().getHouse(),
                                retailPlace.getRetailPlaceAddress().getRegion(), retailPlace.getRetailPlaceAddress().getStreet())))))
                .onItem().transform(pgRowSet -> pgRowSet.iterator().next().getLong("retail_place_id"));
    }

I get long value of id in return. Now I need to return a RetailPlaceResponse with id value in it:

public RetailPlaceResponse(String errorCode, long id, boolean isSuccessful) {
    this.errorCode = errorCode;
    this.id = id;
    this.isSuccessful = isSuccessful;
}

Solution

  • If you need both successful and non-successful responses to map to the same class, you could write separate transforms. One for success and one for failure.

    public static Uni<RetailPlaceResponse> create(PgPool client, RetailPlace retailPlace) {
        return client.withTransaction(conn -> conn
                .preparedQuery("INSERT INTO retail_place (title) VALUES ($1) RETURNING id")
                .execute(Tuple.of(retailPlace.getRetailPlaceTitle()))
                .onItem().transformToUni(id -> conn.
                        preparedQuery("INSERT INTO retail_place_address (retail_place_id,region_code,city,locality_id,apartment,house,region,street) " +
                                "VALUES ($1,$2,$3,$4,$5,$6,$7,$8) returning retail_place_id")
                        .execute(Tuple.tuple(Arrays.asList(id.iterator().next().getLong("id"), retailPlace.getRetailPlaceAddress().getRegionCode(),
                                retailPlace.getRetailPlaceAddress().getCity(), retailPlace.getRetailPlaceAddress().getLocalityId(),
                                retailPlace.getRetailPlaceAddress().getApartment(), retailPlace.getRetailPlaceAddress().getHouse(),
                                retailPlace.getRetailPlaceAddress().getRegion(), retailPlace.getRetailPlaceAddress().getStreet())))))
                .onItem().transform(pgRowSet -> new RetailPlaceResponse(null, pgRowSet.iterator().next().getLong("retail_place_id"), true))
                .onFailure().transform(error -> new RetailPlaceResponse(error.toString(), 0, false));
    }