Reputation: 29
In My Corda project, I need to retrieve a specific state based on the some specific field of the state class, which I have set Unique for each state. How to do that in Corda? The implementation of state is as follows:
@BelongsToContract(OfferContract.class)
public class OfferState implements LinearState {
private final UniqueIdentifier linearID;
private AnonymousParty sender;
private AnonymousParty receiver;
private final String policyID;
private final double faceValue;
private double offeredAmount;
private boolean isActive;
public OfferState(UniqueIdentifier linearID, AnonymousParty sender, AnonymousParty receiver, String policyID, double faceValue, double offeredAmount, boolean isActive) {
this.linearID = linearID;
this.sender = sender;
this.receiver = receiver;
this.policyID = policyID;
this.faceValue = faceValue;
this.offeredAmount = offeredAmount;
this.isActive = isActive;
}
public UniqueIdentifier getLinearID() {
return linearID;
}
public AnonymousParty getSender() {
return sender;
}
public AnonymousParty getReceiver() {
return receiver;
}
public String getPolicyID() {
return policyID;
}
public double getFaceValue() {
return faceValue;
}
public double getOfferedAmount() {
return offeredAmount;
}
public boolean isActive() {
return isActive;
}
@NotNull
@Override
public UniqueIdentifier getLinearId() {
return linearID;
}
@NotNull
@Override
public List<AbstractParty> getParticipants() {
return Arrays.asList(sender,receiver);
}
@Override
public String toString() {
return super.toString();
}
}
I am querying in the API with the following code But, that is showing empty brackets like [] in the postman output.
@GetMapping(value = "/getOfferWithID",headers = "Content-Type=application/x-www-form-urlencoded")
private List<StateAndRef<OfferState>> getOfferWithID(HttpServletRequest request) throws IllegalArgumentException {
String s = request.getParameter("PolicyID");
return proxy.vaultQuery(OfferState.class).getStates().stream().filter(it->it.getState().getData().getPolicyID().equalsIgnoreCase(s)).collect(Collectors.toList());
}
Can you please tell me, How can I filter states while querying, What is going wrong here? is there any direct query method so that I can filter it in rpc call itself or Do I really need to wirte a flow for it?
Upvotes: 1
Views: 144
Reputation: 2548
In order to be able to query your state by one of its attributes, you must:
VaultCustomQueryCriteria
to query against your attribute policyId
. Read about VaultCustomQueryCriteria
here (search for that term, and look for sample code).Your current approach (using .filter(it->it.getState().getData().getPolicyID().equalsIgnoreCase(s))
) is very bad, essentially you are bringing a list of all of your states then filtering that list.
What are you going to do when your query returns 1000,000 states?! You are creating a list of 1000,000 entries then looping through that list to find that one record that has your policyId
!!! This will simply drain your Java Heap, slow your application, and crash it.
Always delegate the search/query to the database by constructing the query in Corda then running it in the DB (using the approach that I already outlined), what you're currently doing is crafting a select * from some_table
then looping through all of the results, my approach crafts select * from some_table where policyId = xxx
, which will return one row.
Upvotes: 1
Reputation: 1821
The code looks fine at the 1st look, not sure what's going wrong. Perhaps there might be something wrong with the linearId
being passed to the query criteria.
As a reference you could look at the below code which works fine:
Upvotes: 0