dapr / java-sdk

Dapr SDK for Java
Apache License 2.0
259 stars 207 forks source link

Unable to query from state store when sate was submitted using Java SDK. #748

Open solidity-software opened 2 years ago

solidity-software commented 2 years ago

I am using Java SDK v1.5 with dapr runtime 1.7 trying to use query state.

Expected Behavior

When using java sdk and storing state it would be expected to be able to query the data using the state api like when storing data to state directly via the dapr state api.

Actual Behavior

I am able to post to postgres state store and it will store as non binary enabling access through query but when I store using the java sdk it stores as binary and unable to use query. Is this a bug or is there a way to force state to be stored as non binary so it can be queried. I have also verified this behavior with Mongo. I think the issue is that the OBJECT_MAPPER encodes as binary json before posting to DAPR state store. I have included a snapshot of 4 records in the database. The two that were posted to the dapr state api were stored as non binary while the one stored using the java sdk are in binary. I am able to query the non binary data through the dapr state query api but not the non binary.

Steps to Reproduce the Problem

save state as using java sdk by passing java object to save method and try to use dapr state query api to get state, nothing returns. Submit same json to state store using dapr state api and then try same query and data will return that matches.

Screenshot 2022-06-03 072144

pravinpushkar commented 2 years ago

@solidity-software If you trying to use state query API could you please try to run this example and check the result - https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/querystate

If you are trying to use CRUD operations using SDK APIs then ideally there should not be any issue. Could you please try to run this example and check once at your end - https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/state

Let us know if the issue persists.

solidity-software commented 2 years ago

@pravinpushkar I tried with the save bulk state including the application/json metadata and it stored in database as json as expected. There doesn't seem to be a way to set metadata for a single save state operation which it looks like the application/json metadata is required for state to be saved in json format required for query to work.

I suggest the save single state operations should include the ability to set metadata so there isn't the need to create a savestaterequest. Documentation should also be updated to clarify this limitation.

Thanks

pravinpushkar commented 2 years ago

@solidity-software Could you please paste here your sample code snippet and data that your are trying to save.

For Saving a single sate - Below code seems to work jsut fine -

public class OrderProcessingServiceApplication {
    private static final String DAPR_STATE_STORE = "statestore";

    public static void main(String[] args) throws Exception {
        try (DaprClient client = new DaprClientBuilder().build()) {

            Order order = new Order();
            order.setOrderId(1);
            order.setOrderName("one order");

            // Save state into the state store
            client.saveState(DAPR_STATE_STORE, String.valueOf(1), order).block();
            System.out.println("Saving Order: " + order.getOrderId());

            // Get state from the state store
            State<Order> response = client.getState(DAPR_STATE_STORE, String.valueOf(1), Order.class).block();
            System.out.println("Getting Order: " + response.getValue());
        }
    }
}

@Getter
@Setter
class Order {
    private int orderId;
    private String orderName;
}
salaboy commented 3 months ago

I think we can close this one, this works if you store state using JSON payloads. I am working on a new Spring integration to do this automatically behind the covers of well-known spring interfaces.

I am using SaveBulk to be able to specify the content type as metadata:

https://github.com/diagridio/dapr-spring-boot-starter/blob/new-spring-boot/dapr-spring-core/src/main/java/io/diagrid/spring/core/keyvalue/DaprKeyValueAdapter.java#L50

Map<String, String> meta = Map.of("contentType", "application/json");
        SaveStateRequest request = new SaveStateRequest(statestoreName)
                    .setStates(new State<>(keyspace + "-" +id.toString(), item, null, meta, null));

        daprClient.saveBulkState(request).block();

That works because to use the Query API that is deprecated you need to store JSON keys on Redis, without that they are stored as HASHs.

salaboy commented 3 months ago

@artursouza I think we can close this one.