Loading...
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.

Product icon
TUTORIAL

Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.

Problem with JPAContainer and adding entity

Martin Hjalmarsson
10 years ago Mar 21, 2012 1:16pm

Hello everyone,

I'm having some issues with JPAContainer and adding a new entity. The new entity does not contain the generated @Id.

This code:

@SuppressWarnings("serial")
public class VaadinFormTestApplication extends Application {

    private static final Logger LOG = LoggerFactory.getLogger(VaadinFormTestApplication.class);
    
    private static final String PERSISTENCE_UNIT = "FormTest";
    
	@Override
	public void init() {
		Window mainWindow = new Window("VaadinFormTest Application");
		setMainWindow(mainWindow);

        Label label = new Label("<h1>FormTest</h1>", Label.CONTENT_XHTML);
        mainWindow.addComponent(label);
        
        final JPAContainer<Person> container = JPAContainerFactory.make(Person.class, PERSISTENCE_UNIT);
        //container.setAutoCommit(false);
        
        final Form form = new BeanValidationForm<Person>(Person.class);
        form.setWriteThrough(false);
        form.setImmediate(true);
        form.setFormFieldFactory(new com.vaadin.addon.jpacontainer.fieldfactory.FieldFactory());
        form.setItemDataSource(container.getItem(container.addItem()));
        form.setVisibleItemProperties(new String[] {"name","phone","email","address"});
        form.getFooter().addComponent(new Button("Save", new Button.ClickListener() {
            
            public void buttonClick(ClickEvent event) {
                LOG.debug("     Entity before form commit: {}", ((JPAContainerItem<?>)form.getItemDataSource()).getEntity());
                form.commit();
                LOG.debug("Entity before container commit: {}", ((JPAContainerItem<?>)form.getItemDataSource()).getEntity());
                container.commit();
                LOG.debug(" Entity after container commit: {}", ((JPAContainerItem<?>)form.getItemDataSource()).getEntity());
            }
            
        }));
        
        mainWindow.addComponent(form);
        
	}

}

@Entity
public class Person {
    
    @Id
    @GeneratedValue
    private long id;
    
    @Size(min=2,max=32)
    private String name;
    
    @Size(min=2,max=32)
    private String phone;

    @Size(min=2,max=32)
    private String email;
    
    @NotNull
    @OneToOne
    private Address address;

    .... GETTERS AND SETTERS ....
    
    public String toString() {
        return id + ": " + name;
    }
    
}

Outputs the following exception to the browser:

javax.validation.ConstraintViolationException: Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'prePersist'. Please refer to embedded ConstraintViolations for details.
	org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener.validateOnCallbackEvent(BeanValidationListener.java:90)
	org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener.prePersist(BeanValidationListener.java:62)
	org.eclipse.persistence.descriptors.DescriptorEventManager.notifyListener(DescriptorEventManager.java:698)
        .......
        com.example.vaadinformtest.VaadinFormTestApplication.init(VaadinFormTestApplication.java:40)
        .......

So it says it cannot save the item, when adding it to the form on line 40:

form.setItemDataSource(container.getItem(container.addItem()));

So, to remedy that, one could possibly use a Batchable JPAContainer... Testing this:

final JPAContainer<Person> container = JPAContainerFactory.makeBatchable(Person.class, PERSISTENCE_UNIT);
        container.setAutoCommit(false);

Results in the following output when saving:

11847 [http-8080-3] DEBUG c.e.v.VaadinFormTestApplication -      Entity before form commit: 0: null
11851 [http-8080-3] DEBUG c.e.v.VaadinFormTestApplication - Entity before container commit: 0: My name
11927 [http-8080-3] DEBUG c.e.v.VaadinFormTestApplication -  Entity after container commit: 0: My name

As you can see, the ID of the Person is still 0. And I have verified that an entity has been saved to the database with a new ID.
The extra side-effect of this is that when clicking Save twice, 2 entities are created in the database.

Only way around this I've found is to not make JPAContainer batchable and to have validation-safe default values in the Person entity (i.e. Person.name = "123").
But that creates a new Entity in the database even if the user does not click the save button.

So, why even use JPAContainer as a backend for Form? Because JPAContainers FieldFactory only works with a JPAContainer. And there's no good alternative as far as I know.

Last updated on Mar, 21st 2012
Marko Grönroos
10 years ago Mar 22, 2012 9:28pm