Adam75
(Adam Brusselback)
May 31, 2014, 4:51am
1
Hey all,
I’ve got a bit of an issue I wanted to ask you about, as I haven’t been able to figure out a good way to overcome it.
I have a multi user application which uses a Postgres database to store permanant data. I want to be able to cache some of that frequently used data inside the application.
I’ll give a quick example of my issue: I have a singleton which holds a hashmap, and provides all access to that map. It allows you to add, remove, overwrite, check if exists, return a value, etc… I load that singleton on startup of my application from the database.
Say the data in that singleton is account data, and I have an account management page which has an editable table. I want to be able to add the data from that singleton to some datasource, and have it not save changes back to the original items until a commit is called.
My issue is, I load the BeanContainer from my singleton, and any changes that are made to any field in the table are instantly reflected in that singleton without even calling a commit. I expected the table to buffer the changes to the datasource until a commit was called, but that is not the case (I have setBuffered(true) set on the table).
How can I get around this?
Adam75
(Adam Brusselback)
May 31, 2014, 5:25am
2
I don’t even… gah.
I have messed with this for days, gone through a bunch of things such as testing deep copy to mitigate (way too slow), and had no results.
I post this, then I think “what if I set each field to buffered in the field factory?!”…
It worked. I feel dumb for wasting as much time as I have.
Edit: Never mind, didn’t work, because now nothing will commit to the container datasource.
Adam75
(Adam Brusselback)
May 31, 2014, 6:20am
3
public class AccountAdminView extends Page {
/**
*
*/
private static final long serialVersionUID = -2215388422551586484L;
private final FormLayout form = new FormLayout();
private final HorizontalLayout buttons = new HorizontalLayout();
private CustomBeanContainer<Account, Account> container = new CustomBeanContainer(Account.class, AccountManager.INSTANCE, AccountContainer.INSTANCE);
private final FilterTable table = new FilterTable();
private final Label prompt = new Label();
private final Button add = new Button();
private final Button save = new Button();
private final Button resetPass = new Button();
private String textFieldWidth = "300px";
public AccountAdminView() {
setProperties();
layoutPage();
}
private boolean validate() {
try {
table.validate();
} catch (Exception e) {
return false;
}
return true;
}
@Override
public void setProperties() {
// TODO Auto-generated method stub
form.setSizeUndefined();
form.setDefaultComponentAlignment(Alignment.MIDDLE_CENTER);
// Prompt
prompt.setValue("Please enter your new account information");
container.setBeanIdResolver(bean -> bean);
CustomFieldFactory fieldFactory = new CustomFieldFactory() {
@Override
public Field createField(final Container container, final Object itemId, final Object propertyId, Component uiContext) {
Field<?> field = super.createField(container, itemId, propertyId, uiContext);
if (propertyId.equals("ID")) {
field.setReadOnly(true);
((TextField) field).setConverter(new StringToPlainIntegerConverter());
}
field.setBuffered(true);
field.addValidator(new BeanValidator(Account.class, (String) propertyId));
return field;
}
};
// table
table.setWidth("100%");
table.setContainerDataSource(container);
table.setImmediate(true);
table.setEditable(true);
table.setBuffered(true);
table.setSelectable(true);
table.setPageLength(10);
table.setFilterBarVisible(true);
table.setFilterGenerator(new MyFilterGenerator());
table.setFilterDecorator(new MyFilterDecorator());
table.setTableFieldFactory(fieldFactory);
table.setVisibleColumns("ID", "email", "firstName", "lastName", "active");
table.setColumnWidth("ID", 80);
table.setColumnWidth("email", 250);
// Layout for buttons
buttons.setWidth("200px");
buttons.setSpacing(false);
// add
add.setCaption("Add");
add.addClickListener(event -> {
if(!table.getItemIds().contains("Temporary row id")) {
Account newAccount = new Account();
newAccount.setClientID(AccountContainer.INSTANCE.get(getSession()).getClientID());
String newPass = RandomStringGenerator.generateRandomString(6, RandomStringGenerator.Mode.ALPHA);
newAccount.setPassword(newPass);
newAccount.setActive(true);
container.addBean(newAccount);
Notification.show("The password for the new account you created is: " + newPass, Type.ERROR_MESSAGE);
table.refreshRowCache();
}
else {
Notification.show("Only one account can be added at a time. Please save the existing account before adding another.", Type.WARNING_MESSAGE);
}
});
add.setImmediate(true);
add.setWidth("65px");
add.setHeight("25px");
// save
save.setCaption("Save");
save.addClickListener(event -> {
try {
validate();
table.commit();
container.commit();
Notification.show("Account saved.");
} catch (Exception e) {
// TODO Auto-generated catch block
Notification.show("Account could not be created / saved.", Type.ERROR_MESSAGE);
//remove uncommitted rows from the table
List<Object> remove = table.getItemIds().stream().filter(item -> ((Account) item).getID() == null).collect(Collectors.toList());
for(Object i : remove) {
table.removeItem(i);
}
}
});
save.setImmediate(true);
save.setWidth("65px");
save.setHeight("25px");
// resetPass
resetPass.setCaption("Reset Password");
resetPass.addClickListener(event -> {
if (table.getValue() == null) {
Notification.show("You must select an account first.", Type.WARNING_MESSAGE);
return;
}
Account account = (Account) AccountContainer.INSTANCE.get((Integer) table.getValue());
String newPass = RandomStringGenerator.generateRandomString(6, RandomStringGenerator.Mode.ALPHA);
if (AccountManager.INSTANCE.updatePassword(account, newPass)) {
Notification.show("Password successfully set to: " + newPass, Type.ERROR_MESSAGE);
} else
Notification.show("The password could not be reset for this account", Type.ERROR_MESSAGE);
});
resetPass.setImmediate(true);
resetPass.setWidth("120px");
resetPass.setHeight("25px");
}
@Override
public void layoutPage() {
// TODO Auto-generated method stub
components.addComponent(prompt);
components.addComponent(resetPass);
components.setComponentAlignment(resetPass, Alignment.MIDDLE_LEFT);
components.addComponent(table);
buttons.addComponent(add);
buttons.addComponent(save);
buttons.setComponentAlignment(add, Alignment.MIDDLE_LEFT);
buttons.setComponentAlignment(save, Alignment.MIDDLE_RIGHT);
components.addComponent(buttons);
}
@Override
public void enter(ViewChangeListener.ViewChangeEvent event) {
super.enter(event);
if (AccountContainer.INSTANCE.get(getSession()) == null)
return;
container.removeAllItems();
container.addAll(AccountContainer.INSTANCE.getAll(AccountContainer.INSTANCE.get(getSession()).getClientID()));
}
}
Here is the code for my page i’m trying to get working properly. Probably best to just show what is going on.