Important Notice - Forums is archived
To simplify things and help our users to be more productive, we have archived the current forum and focus our efforts on helping developers on Stack Overflow. You can post new questions on Stack Overflow or join our Discord channel.

Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.
JPAContainer - FieldFactory does not work for new Items
Hi Everyone out there,
I am having a problem with the JPAContainer's FieldFacotry. It creates “simple” TextFields for all fields even for @ManyToOne, @OneToMany, etc. - as you can see in the screenshot. Should it not create a Native Select for the UserGroup field?
I followed the JPAContainer tutorial and the instructions given in the Book of Vaadin. I guess there is something very simple which I have overseen or which I do not understand. Would be nice if someone can point me in the right direction.
Thanks for your help.
Regards
Kurt
My Entities:
@Entity
public class UserGroup implements Serializable {
@Id
private String userGroupUUID;
private String name;
private String description;
@OneToMany(mappedBy = "userGroup")
private Set<AppUser> appUsers;
public UserGroup() {
userGroupUUID = UUID.randomUUID().toString();
}
........
@Entity
public class AppUser implements Serializable {
@Id
private String appUserUUID;
private String name;
private String description;
@NotNull
@ManyToOne
private UserGroup userGroup;
public AppUser() {
appUserUUID = UUID.randomUUID().toString();
}
.......
The Editor:
public class AppUserEditor extends Window implements Button.ClickListener {
private final Item appUserItem;
private Form editorForm;
private Button saveButton;
private Button cancelButton;
public AppUserEditor(Item appUserItem) {
this.appUserItem = appUserItem;
editorForm = new Form();
// Use a JPAContainer field factory
// - no configuration is needed here according to the Book of Vaadin
final FieldFactory fieldFactory = new FieldFactory();
editorForm.setFormFieldFactory(fieldFactory);
editorForm.setItemDataSource(appUserItem);
editorForm.setWriteThrough(false);
editorForm.setImmediate(true);
saveButton = new Button("Save", this);
cancelButton = new Button("Cancel", this);
editorForm.getFooter().addComponent(saveButton);
editorForm.getFooter().addComponent(cancelButton);
getContent().setSizeUndefined();
addComponent(editorForm);
setCaption("AppUser Editor");
}
@Override
public void buttonClick(ClickEvent event) {
if (event.getButton() == saveButton) {
editorForm.commit();
fireEvent(new EditorSavedEvent(this, appUserItem));
} else if (event.getButton() == cancelButton) {
editorForm.discard();
}
close();
}
public void addListener(EditorSavedListener listener) {
try {
Method method = EditorSavedListener.class.getDeclaredMethod(
"editorSaved", new Class[]{EditorSavedEvent.class});
addListener(EditorSavedEvent.class, listener, method);
} catch (final java.lang.NoSuchMethodException e) {
// This should never happen
throw new java.lang.RuntimeException("Internal error, editor saved method not found");
}
}
public void removeListener(EditorSavedListener listener) {
removeListener(EditorSavedEvent.class, listener);
}
public static class EditorSavedEvent extends Component.Event {
private Item savedItem;
public EditorSavedEvent(Component source, Item savedItem) {
super(source);
this.savedItem = savedItem;
}
public Item getSavedItem() {
return savedItem;
}
}
public interface EditorSavedListener extends Serializable {
public void editorSaved(EditorSavedEvent event);
}
}
And finally the Main Window:
public class MainWindow extends Window {
private JPAContainer<UserGroup> userGroups = JPAContainerFactory.makeJndi(UserGroup.class);
private JPAContainer<AppUser> appUsers = JPAContainerFactory.makeJndi(AppUser.class);
public MainWindow() {
super("MainWindow");
init();
}
private void init() {
VerticalLayout contentRoot = (VerticalLayout) getContent();
contentRoot.setSizeUndefined();
/*
* UserGroup.
*/
Table userGroupTable = new Table("User Groups", userGroups);
contentRoot.addComponent(userGroupTable);
Button buNewUserGroup = new Button("Create new UserGroup");
contentRoot.addComponent(buNewUserGroup);
buNewUserGroup.addListener(new Button.ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
final BeanItem<UserGroup> newUserGroupItem = new BeanItem<UserGroup>(new UserGroup());
UserGroupEditor userGroupEditor = new UserGroupEditor(newUserGroupItem);
userGroupEditor.addListener(new UserGroupEditor.EditorSavedListener() {
@Override
public void editorSaved(UserGroupEditor.EditorSavedEvent event) {
userGroups.addEntity(newUserGroupItem.getBean());
}
});
getApplication().getMainWindow().addWindow(userGroupEditor);
}
});
/*
* AppUser.
*/
Table appUserTable = new Table("App Users", appUsers);
contentRoot.addComponent(appUserTable);
Button buNewAppUser = new Button("Create new AppUser");
contentRoot.addComponent(buNewAppUser);
buNewAppUser.addListener(new Button.ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
final BeanItem<AppUser> newAppUserItem = new BeanItem<AppUser>(new AppUser());
AppUserEditor appUserEditor = new AppUserEditor(newAppUserItem);
appUserEditor.addListener(new AppUserEditor.EditorSavedListener() {
@Override
public void editorSaved(AppUserEditor.EditorSavedEvent event) {
appUsers.addEntity(newAppUserItem.getBean());
}
});
getApplication().getMainWindow().addWindow(appUserEditor);
}
});
}
}
I found out, that when I try to edit an (existing) item the JPAContainer FieldFactory works.
But when creating a new item it still does not work. Why is that? Any ideas? I followed section 6.2 Creating an Item in the JPAContainer tutorial.
P.S.: I changed the subject from JPAContainer - FieldFactory does not create the "right" Fields to JPAContainer - FieldFactory does not work for new items.
final Table userGroupTable = new Table("User Groups", userGroups);
contentRoot.addComponent(userGroupTable);
userGroupTable.setSelectable(true);
userGroupTable.setImmediate(true);
userGroupTable.addListener(new Table.ValueChangeListener() {
@Override
public void valueChange(ValueChangeEvent event) {
Item item = userGroups.getItem(event.getProperty().getValue());
[b]getApplication().getMainWindow().addWindow(new UserGroupEditor(item)); // This works[/b]
}
});
Button buNewUserGroup = new Button("Create new UserGroup");
contentRoot.addComponent(buNewUserGroup);
buNewUserGroup.addListener(new Button.ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
final BeanItem<UserGroup> newUserGroupItem = new BeanItem<UserGroup>(new UserGroup());
UserGroupEditor userGroupEditor = new UserGroupEditor(newUserGroupItem);
userGroupEditor.addListener(new UserGroupEditor.EditorSavedListener() {
@Override
public void editorSaved(UserGroupEditor.EditorSavedEvent event) {
[b]userGroups.addEntity(newUserGroupItem.getBean()); // This does not work! TextFields only.[/b]
}
});
getApplication().getMainWindow().addWindow(userGroupEditor);
}
});
Two things: First the tutorial leads in a "wrong" direction and second one should RTFM. :D
First:
The tutorial says you should create a BeanItem and pass it to your editor. Well, in general this is not wrong. BUT the FieldFactory checks if the passed item is of type JPAContainerItem. If it is it does the trick. If not, well no trick. Thus BeanItem --> no trick.
Second:
JPAContainer has a method called createEntityItem. It creates a new EntityItem without adding it to the container. So exactly what I need. But I was that focused on the tutorial I oversaw this method completely.
So here is how to add new Entities:
Button buNewAppUser = new Button("Create new AppUser");
contentRoot.addComponent(buNewAppUser);
buNewAppUser.addListener(new Button.ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
EntityItem newAppUserItem = appUsers.createEntityItem(new AppUser());
AppUserEditor appUserEditor = new AppUserEditor(newAppUserItem);
appUserEditor.addListener(new AppUserEditor.EditorSavedListener() {
@Override
public void editorSaved(AppUserEditor.EditorSavedEvent event) {
appUsers.addItem(event.getSavedItem());
}
});
getApplication().getMainWindow().addWindow(appUserEditor);
}
});
Happy Easter