I'm trying to refresh grid after adding an row into it, but it's not working. Here is my Event Listener on my UI Code : Edited Full code.
Grid<TransactionModel> transactionData = new Grid<>(TransactionModel.class);
try {
// transactionData.setItems(transactionServices.getTransactionTable());
List<TransactionModel> transactionList = transactionServices.getTransactionTable();
ListDataProvider<TransactionModel> transactionDataProvider = new ListDataProvider<>(transactionList);
transactionData.setDataProvider(transactionDataProvider);
transactionData.setColumns("id", "transactionTimestamp", "srcAccountId", "dstAccountId", "amount");
Grid.Column<TransactionModel> idColumn = transactionData.getColumnByKey("id");
Grid.Column<TransactionModel> srcAccountIdColumn = transactionData.getColumnByKey("srcAccountId");
Grid.Column<TransactionModel> dstAccountIdColumn = transactionData.getColumnByKey("dstAccountId");
HeaderRow filterRow2 = transactionData.appendHeaderRow();
TransactionFilterModel transactionFilterModel = new TransactionFilterModel();
transactionDataProvider.setFilter(transaction -> transactionFilterModel.find(transaction));
// Filter srcAccountId
TextField idField = new TextField();
idField.addValueChangeListener(event -> {
transactionFilterModel.setId(event.getValue());
transactionDataProvider.refreshAll();
});
idField.setValueChangeMode(ValueChangeMode.EAGER);
filterRow2.getCell(idColumn).setComponent(idField);
idField.setSizeFull();
idField.getElement().setAttribute("focus-terget", "");
// Filter srcAccountId
TextField srcAccountIdField = new TextField();
srcAccountIdField.addValueChangeListener(event -> {
transactionFilterModel.setSrcAccountId(event.getValue());
transactionDataProvider.refreshAll();
});
srcAccountIdField.setValueChangeMode(ValueChangeMode.EAGER);
filterRow2.getCell(srcAccountIdColumn).setComponent(srcAccountIdField);
srcAccountIdField.setSizeFull();
srcAccountIdField.getElement().setAttribute("focus-terget", "");
// Filter dstAccountId
TextField dstAccountIdField = new TextField();
dstAccountIdField.addValueChangeListener(event -> {
transactionFilterModel.setDstAccountId(event.getValue());
transactionDataProvider.refreshAll();
});
dstAccountIdField.setValueChangeMode(ValueChangeMode.EAGER);
filterRow2.getCell(dstAccountIdColumn).setComponent(dstAccountIdField);
dstAccountIdField.setSizeFull();
dstAccountIdField.getElement().setAttribute("focus-terget", "");
transactionData.setWidth("50%");
} catch (JsonProcessingException | EndpointException ex) {
Logger.getLogger(MainView.class.getName()).log(Level.SEVERE, null, ex);
}
// Event Listener
submitButton.addClickListener(e -> {
System.out.println("Submitted !");
AccountModel submittedModel = new AccountModel();
if (accountModelBinder.writeBeanIfValid(submittedModel)) {
try {
accountServices.registerAccount(submittedModel);
accountIdTextField.clear();
nameTextField.clear();
addressTextField.clear();
birthDateDatePicker.clear();
allowNegativeBalanceButtonGroup.clear();
} catch (EndpointException | JsonProcessingException ez) {
Logger.getLogger(MainView.class.getName()).log(Level.SEVERE, null, ez);
}
}
accountData.getDataProvider().refreshAll(); // <- REFRESH
});
And for service I'm using rest, here is the accountservice code:
public List<AccountModel> getAccountTable() throws JsonProcessingException, EndpointException {
List<AccountModel> datalog = new JsonResponseReader(restMockvaEndpoint.send(new EndpointRequestBuilder()
.method("GET")
.resource("/account")
.build()
)).getContentTable(AccountModel.class).getData();
return datalog;
}
public AccountModel registerAccount(AccountModel accountModel) throws JsonProcessingException, EndpointException{
AccountModel account = new JsonResponseReader(restMockvaEndpoint.send(new EndpointRequestBuilder()
.method("POST")
.content(Json.getWriter().writeValueAsBytes(accountModel), MediaType.APPLICATION_JSON)
.resource("/account")
.build())).getContentObject(AccountModel.class);
return account;
}
Edited : Add registerAccount.
The problem is when I click submitButton for adding new data, the grid doesn't refresh. Any ideas?
For this to work with a ListDataProvider, you would have to modify the underlying list (add/remove items).
Now that you call refreshAll(), it just reads the list you passed again, and as it still contains the same items, nothing changes. It does not know to fetch the items from your service again.
There are a few solutions that I can think of:
1. Manually add the new item to the list (it will then appear at the end of the grid):
accountList.add(submittedModel);
...
// This instructs the grid to read the list again
accountData.getDataProvider().refreshAll();
If your accountServices.registerAccount method returns the newly saved item, you might want to add that one instead.
2. Set the items again
You could fetch the items again and set a new data provider. You can just use setItems(...) then, which uses a ListDataProvider under the hood.
// Run this both when first creating the grid, and again after the new item is saved.
// This time you don't need to call refreshAll()
List<AccountModel> accountList = accountServices.getAccountTable();
accountData.setItems(accountList);
3. Use a lazy data provider
When you use a lazy data provider, for example from callbacks, then calling refreshAll() executes those callbacks again to fetch new items.
In this case you need to implement the needed service methods, and it requires a bit more work if you need sorting or filtering.
this.setDataProvider(DataProvider.fromCallbacks(
query -> myAccountService.getAccounts(query.getOffset(), query.getLimit()).stream(),
query -> myAccountService.countAccounts()
));
Related
I am new to DynamoDB and working on a dynamo project. I am trying to update the item amount in a transaction with condition if_not_exists() with TransactionWriteRequest in DynamoDB Mapper.
As per the Doc, transactionWriteRequest.updateItem() takes DynamoDBTransactionWriteExpression which doesn't have any UpdateExpression. Class definition is attached bellow.,
Wanted to know How can i provide the if_not_exists() in DynamoDBTransactionWriteExpression to update the item in a transaction. Or there is no way to do this in a transactionWrite.
Please help here.
Thanks in advance
Judging from the snippet you shared it seems you are using Java SDK v1. Below is a code snippet which has 1 PutItem and 1 UpdateItem combined in a single TransactWrite request.
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
final String ORDER_TABLE_NAME = "test1";
/*
Update Item with condition
*/
HashMap<String,AttributeValue> myPk =
new HashMap<String,AttributeValue>();
myPk.put("pk", new AttributeValue("pkValue1"));
Map<String, AttributeValue> expressionAttributeValues = new HashMap<>();
expressionAttributeValues.put(":new_status", new AttributeValue("SOLD"));
Update markItemSold = new Update()
.withTableName(ORDER_TABLE_NAME)
.withKey(myPk)
.withUpdateExpression("SET ProductStatus = if_not_exists(createdAt, :new_status)")
.withExpressionAttributeValues(expressionAttributeValues)
.withReturnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure.ALL_OLD);
/*
Put Item
*/
HashMap<String, AttributeValue> orderItem = new HashMap<>();
orderItem.put("pk", new AttributeValue("pkValue2"));
orderItem.put("OrderTotal", new AttributeValue("100"));
Put createOrder = new Put()
.withTableName(ORDER_TABLE_NAME)
.withItem(orderItem)
.withReturnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure.ALL_OLD);
/*
Transaction
*/
Collection<TransactWriteItem> actions = Arrays.asList(
new TransactWriteItem().withUpdate(markItemSold),
new TransactWriteItem().withPut(createOrder));
TransactWriteItemsRequest placeOrderTransaction = new TransactWriteItemsRequest()
.withTransactItems(actions)
.withReturnConsumedCapacity(ReturnConsumedCapacity.TOTAL);
try {
client.transactWriteItems(placeOrderTransaction);
System.out.println("Transaction Successful");
} catch (ResourceNotFoundException rnf) {
System.err.println("One of the table involved in the transaction is not found" + rnf.getMessage());
} catch (InternalServerErrorException ise) {
System.err.println("Internal Server Error" + ise.getMessage());
} catch (TransactionCanceledException tce) {
System.out.println("Transaction Canceled " + tce.getMessage());
} catch (AmazonServiceException e){
System.out.println(e.getMessage());
}
With the v2 version of the SDK you can do it like this
var table =
enhancedClient.table(<table name>, TableSchema.fromClass(DynamoEntity.class));
var transactWriteItemsEnhancedRequest = TransactWriteItemsEnhancedRequest
.builder()
.addUpdateItem(table,
TransactUpdateItemEnhancedRequest.builder(LoadTestEntity.class)
.item(<entity>)
.conditionExpression(Expression.builder().expression("attribute_not_exists(ID)").build())
.build())
.build();
enhancedClient.transactWriteItems(transactWriteItemsEnhancedRequest);
You might need to play around with the expression builder, I haven't tested it.
I am creating a new state in the flow and then I am trying to consume the state by using reference input. But every time I see in the result as unconsumed state, though I was providing the reference state in the transaction's input.
public SignedTransaction call() throws FlowException {
//------------------------------------------------------------------------------------------------------------
// STEP-1:
// FIRST FLOW MUST CREATE THE NEW STATE WHICH HAS NO INPUT ( THIS WILL CREATE NEW RECORD-ANCHOR WITH LINEARID )
//
//------------------------------------------------------------------------------------------------------------
// We retrieve the notary identity from the network map.
Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
// We create the transaction components.
AnchorState outputState = new
AnchorState(ownerId,contentHash,description,classid,timestamp,expiry, getOurIdentity(), otherParty,new UniqueIdentifier());
//required signers
List<PublicKey> requiredSigners = Arrays.asList(getOurIdentity().getOwningKey(),otherParty.getOwningKey());
//send create command with required signer signatures as below
Command command = new Command<>(new AnchorStateContract.Commands.CreateRecAnchorCmd(), requiredSigners);
// We create a transaction builder and add the components.
TransactionBuilder txBuilder = new TransactionBuilder(notary)
.addOutputState(outputState, AnchorStateContract.ID)
.addCommand(command);
// Verifying the transaction.
txBuilder.verify(getServiceHub());
// Signing the transaction.
SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder);
// Creating a session with the other party.
FlowSession otherPartySession = initiateFlow(otherParty);
// Obtaining the counterparty's signature.
SignedTransaction fullySignedTx = subFlow(new CollectSignaturesFlow(
signedTx, Arrays.asList(otherPartySession), CollectSignaturesFlow.Companion.tracker()));
//notarized transaction
SignedTransaction notraizedtransaction = subFlow(new FinalityFlow(fullySignedTx, otherPartySession));
//------------------------------------------------------------------------------------------------------------
// STEP-2:
// SINCE NOW WE HAVE A NEW UNCONSUMED RECORD-ANCHOR SO WE MUST MAKE IT CONSUMED ( BY USING THE PREVIOUS OUTPUT AS AN INPUT)
//
//------------------------------------------------------------------------------------------------------------
StateAndRef oldStateref = getServiceHub().toStateAndRef(new StateRef(notraizedtransaction.getId(),0));
Command storeCommand = new Command<>(new AnchorStateContract.Commands.ApproveRecAnchorCmd(), requiredSigners);
TransactionBuilder txBuilder2 = new TransactionBuilder(notary)
.addInputState(oldStateref)
.addOutputState(outputState, AnchorStateContract.ID)
.addCommand(storeCommand);
txBuilder2.verify(getServiceHub());
// signing
SignedTransaction signedTx2 = getServiceHub().signInitialTransaction(txBuilder2);
// Creating a session with the other party.
FlowSession otherPartySession2 = initiateFlow(otherParty);
// Finalising the transaction.
SignedTransaction fullySignedTx2 = subFlow(new CollectSignaturesFlow(
signedTx2, Arrays.asList(otherPartySession2), CollectSignaturesFlow.Companion.tracker()));
//notarized transaction
return subFlow(new FinalityFlow(fullySignedTx2, otherPartySession2));
}
In my flow initiator class I am first creating new state of a hash which I am calling as AnchorState. This state is coming from one of the participants and then it requests to the other participant to sign. afterward the signed record is stored in the ledger but its reference used as an input for a new state change, I simply want to make this state as consumed rather than unconsumed.
The responding flow class of participant B is as below
public SignedTransaction call() throws FlowException
{
//this class is used inside call function for the verification purposes before signed by this party
class SignTxFlow extends SignTransactionFlow
{
private SignTxFlow(FlowSession otherPartySession) {
super(otherPartySession);
}
#Override
protected void checkTransaction(SignedTransaction stx) {
requireThat(require -> {
ContractState output = stx.getTx().getOutputs().get(0).getData();
require.using("This must be an AnchorState transaction.", output instanceof AnchorState);
AnchorState state = (AnchorState) output;
require.using("The AnchorState's value should be more than 6 characters", state.getContentHash().length() > 6);
return null;
});
}
}
SecureHash expectedTxId = subFlow(new SignTxFlow(otherPartySession)).getId();
return subFlow(new ReceiveFinalityFlow(otherPartySession, expectedTxId));
}
This flow successfully runs and returns me unique id for the transaction but I tried everything and could not found how to change the state from unconsumed to consumed?
AFTER FIX
I realized that the vaultQuery on the CordaOS by default returns unconsumed state. Which is now clear why I was not able to get the consumed state in the first place. One more issue which I found, was lack of resources in CORDA for java though I found many kotlin based answers for a transaction with "creation and consumption" in single workflow however converting them into JAVA required some efforts.
Kotlin Based answer
Some differences I observed between Java and Kotlin approach
1) When I have tried to use the same session in my second transaction which was used in the first transaction then I get this error
java.util.concurrent.ExecutionException: net.corda.core.flows.UnexpectedFlowEndException: Tried to access ended session SessionId(toLong=1984916257986245538) with empty buffer
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at net.corda.core.internal.concurrent.CordaFutureImpl.get(CordaFutureImpl.kt)
Which means we have to create new session every time for the new transaction regardless if they are in the single workflow.
2) As I understood by looking at the Kotlin solution that we don't need to add output in the transaction if we just want to make it consumed. However when I do not add an output state in the second transaction then I get the following error which means even for the consumed state I must add the same output inside the transaction. Otherwise, the following error will get erupted again.
ava.util.concurrent.ExecutionException: net.corda.core.flows.UnexpectedFlowEndException: Counter-flow errored
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at net.corda.core.internal.concurrent.CordaFutureImpl.get(CordaFutureImpl.kt)
at com.etasjil.Client.testFlow(Client.java:92)
So it is clear that unlike kotlin, in java we need to explicitly add the output state and new session if we want to create and consume a state within same workflow.
Note: Since this is a new learning curve for me therefore, if I made any mistake in the above realization then kindly correct me. This answer could be good for the new comers in Corda who wants to code in Java rather than Kotlin.
State
#BelongsToContract(AnchorStateContract.class)
public class AnchorState implements LinearState {
public String ownerId,contentHash,description,classid,timestamp,expiry;
public Party initiatorParty, otherParty;
public UniqueIdentifier linearId;
#Override
public List<AbstractParty> getParticipants() {
return Arrays.asList(initiatorParty, otherParty);
}
public AnchorState() {
}
#ConstructorForDeserialization
public AnchorState(String ownerId, String contentHash, String description, String classid, String timestamp, String expiry, Party initiatorParty, Party otherParty, UniqueIdentifier linearId) {
this.ownerId = ownerId;
this.contentHash = contentHash;
this.description = description;
this.classid = classid;
this.timestamp = timestamp;
this.expiry = expiry;
this.initiatorParty = initiatorParty;
this.otherParty = otherParty;
this.linearId = linearId;
}
...
FlowTest case
...
...
#Test
public void test1() {
Future data = a.startFlow(new Initiator("Owner1", "1234567", "Description", "c1", Instant.now().toString(), Instant.MAX.toString(), b.getInfo().getLegalIdentities().get(0).getName().toString()));
network.runNetwork();
try {
System.out.println(data.get());
}catch (Exception e){
System.out.println(e.getMessage());
}
QueryCriteria.VaultQueryCriteria criteria1 = new QueryCriteria.VaultQueryCriteria(Vault.StateStatus.CONSUMED);
Vault.Page<AnchorState> results1 = a.getServices().getVaultService().queryBy(AnchorState.class, criteria1);
System.out.println("--------------------- "+ results1.getStates().size());
QueryCriteria.VaultQueryCriteria criteria2 = new QueryCriteria.VaultQueryCriteria(Vault.StateStatus.ALL);
Vault.Page<AnchorState> results2 = a.getServices().getVaultService().queryBy(AnchorState.class, criteria2);
System.out.println("--------------------- "+ results2.getStates().size());
QueryCriteria.VaultQueryCriteria criteria3 = new QueryCriteria.VaultQueryCriteria(Vault.StateStatus.CONSUMED);
Vault.Page<AnchorState> results3 = b.getServices().getVaultService().queryBy(AnchorState.class, criteria3);
System.out.println("--------------------- "+ results3.getStates().size());
QueryCriteria.VaultQueryCriteria criteria4 = new QueryCriteria.VaultQueryCriteria(Vault.StateStatus.ALL);
Vault.Page<AnchorState> results4 = b.getServices().getVaultService().queryBy(AnchorState.class, criteria4);
System.out.println("--------------------- "+ results4.getStates().size());
}
I got 1,2,1,2 as the outputs which tells 1 consumed state in node a & b, totally 2 states in node a and b(1 consumed and 1 unconsumed).
The 1st time program is loaded the arrow key selection in autocomplete combobox works. But after I clear and reload the values in it using a method below the arrow key navigation and selection of combobox items does not work.
I use TextFields.bindAutoCompletion method from ControlsFx 8 to bind combobox.
// load Auto Compleat nic,fname,lname,id values for search Combo Box
private void loadValuesToComboSearchBox() {
try {
// clear elements of Search Combo Box
comboSearch.getItems().clear();
// Disable Search Combo Box
comboSearch.setEditable(false);
// load Auto Compleat nic,fname,lname,id values for search Text Field
ResultSet getsearchElements = employeDao.getSearchemployeeByNicFnameLnmeId();
LinkedHashSet<String> addElements = new LinkedHashSet<>();
while (getsearchElements.next()) {
addElements.add(getsearchElements.getString("id"));
addElements.add(getsearchElements.getString("firstname"));
addElements.add(getsearchElements.getString("lastname"));
addElements.add(getsearchElements.getString("nic"));
}
// Add elements to Auto Compleat Text Field
TextFields.bindAutoCompletion(comboSearch.getEditor(), addElements);
// Enable Search Combo Box
comboSearch.setEditable(true);
} catch (Exception e) {
new Alert(Alert.AlertType.INFORMATION, e + "", ButtonType.OK).showAndWait();
e.printStackTrace();
}
}
I believe this issue occurs due to the several overlapping AutoCompletionBindings.
In order to fix that you should keep reference to the previous binding and dispose it upon reload. Also, note that to clear the selection in JavaFX combobox more steps should be performed.
private AutoCompletionBinding<String> completion;
....
private void loadValuesToComboSearchBox() {
try {
// clear selection
comboSearch.getItems().clear();
comboSearch.valueProperty().set(null);
comboSearch.getEditor().clear();
comboSearch.setEditable(false);
ResultSet getSearchElements = employeDao.getSearchemployeeByNicFnameLnmeId();
Set<String> addElements = new LinkedHashSet<>();
while (getSearchElements.next()) {
addElements.add(getSearchElements.getString("id"));
addElements.add(getSearchElements.getString("firstname"));
addElements.add(getSearchElements.getString("lastname"));
addElements.add(getSearchElements.getString("nic"));
}
if (completion != null) {
completion.dispose();
}
completion = TextFields.bindAutoCompletion(comboSearch.getEditor(), addElements);
comboSearch.setEditable(true);
} catch (Exception e) {
new Alert(Alert.AlertType.INFORMATION, e + "", ButtonType.OK).showAndWait();
e.printStackTrace();
}
}
i don't have any idea on how to get the selected items in a DualListField. Can somebody help me. so here's my code on DualListField. And I want txtCat to be the container of the selected items aside from the TextCell. And also I want the selected item to be converted on its IDCategory
final DualListField<Category, String> field = new DualListField<Category, String>(category, toCategory, catProp.strName(), txCell);
field.addValidator(new EmptyValidator<List<Category>>());
field.setEnableDnd(true);
field.setMode(Mode.INSERT);
vlc.add(new FieldLabel(field, "Categories"), new VerticalLayoutData(1, -1, new Margins(10)));
txtCat = new TextField();
txtCat.setEmptyText("Value");
txtCat.addFocusHandler(new FocusEvent.FocusHandler() {
#Override
public void onFocus(FocusEvent event) {
field.getFromStore();
}
});
vlc.add(new FieldLabel(txtCat, "Chosen Categories"), new VerticalLayoutData(-18, -1, new Margins(10)));
In latest GXT3 version DualListField, You could get the selected items in ToView part through field.getValue() method. You get all the data in ToView as follows. field.getToView().getStore().getAll() . hth
I'm trying to build grid with build in column filtering (using sencha gxt), here is my code:
public Grid<Stock> createGrid() {
// Columns definition
ColumnConfig<Stock, String> nameCol = new ColumnConfig<Stock, String>(props.name(), 100, "Company");
// Column model definition and creation
List<ColumnConfig<Stock, ?>> cl = new ArrayList<ColumnConfig<Stock, ?>>();
cl.add(nameCol);
ColumnModel<Stock> cm = new ColumnModel<Stock>(cl);
// Data populating
ListStore<Stock> store = new ListStore<Stock>(props.key());
store.addAll(TestData.getStocks());
// Grid creation with data
final Grid<Stock> grid = new Grid<Stock>(store, cm);
grid.getView().setAutoExpandColumn(nameCol);
grid.setBorders(false);
grid.getView().setStripeRows(true);
grid.getView().setColumnLines(true);
// Filters definition
StoreFilterField<Stock> filter = new StoreFilterField<Stock>() {
#Override
protected boolean doSelect(Store<Stock> store, Stock parent, Stock item, String filter) {
// Window.alert(String.valueOf("a"));
String name = item.getName();
name = name.toLowerCase();
if (name.startsWith(filter.toLowerCase())) {
return true;
}
return false;
}
};
filter.bind(store);
cm.addHeaderGroup(0, 0, new HeaderGroupConfig(filter, 1, 1));
filter.focus();
return grid;
}
My problem is: after I run this code, I cannot write anything to filter input, I'm using test data and classes (Stock.java and StockProperties.java) from this example: http://sencha.com/examples-dev/#ExamplePlace:filtergrid
I try to put allert in doSelect method to check if this function was called, but it wasn't.
Any idea will be welcome. Thanks.
I was able to make your code work. I observed that there were compiler errors in the code for StoreFilterField class. Here is the code that filters the grid based on the values in the first column, that is, name field in the Stock model.
StoreFilterField<Stock> filter1 = new StoreFilterField<Stock>() {
#Override
protected boolean doSelect(Store<Stock> store, Stock parent, Stock record, String property, String filter) {
String name = record.get("name");
name = name.toLowerCase();
if (name.startsWith(filter.toLowerCase())) {
return true;
}
return false;
}
};
filter1.bind(store);
Btw, I tested this with GXT 2.2.5 and GWT 2.4.
Thanks,
Ganesh
I solve this problem according to this paper http://www.sencha.com/forum/archive/index.php/ … but I replace disableTextSelection(false) with setAllowTextSelection(true);