FieldGroup con clases (entity) anidadas

Hola a todos, estoy empezando a utilizar Vaadin, el problema que les comparto es que al tratar de usar el objeto FieldGroup con una entidad anidadas obtengo:

com.vaadin.data.fieldgroup.FieldGroup$CommitException: Commit failed at com.vaadin.data.fieldgroup.FieldGroup.commit(FieldGroup.java:492) at com.rfrg.vaadin.example.vaadinappexample.sample.viewusuarios.UsuarioEditor.buttonClick(UsuarioEditor.java:169) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:508) at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:198) at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:161) at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:1003) at com.vaadin.ui.Button.fireClick(Button.java:377) at com.vaadin.ui.Button$1.click(Button.java:54) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:158) at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:118) at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:408) at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:273) at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:79) at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41) at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1409) at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:364) at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:769) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1667) at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:172) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1650) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:583) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1125) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1059) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215) at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:110) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) at org.eclipse.jetty.server.Server.handle(Server.java:497) at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311) at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:248) at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:610) at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:539) at java.lang.Thread.run(Thread.java:745) Caused by: com.vaadin.data.Buffered$SourceException at com.vaadin.ui.AbstractField.commit(AbstractField.java:257) at com.vaadin.data.fieldgroup.FieldGroup.commitFields(FieldGroup.java:509) at com.vaadin.data.fieldgroup.FieldGroup.commit(FieldGroup.java:481) ... 47 more Caused by: com.vaadin.data.util.MethodProperty$MethodException at com.vaadin.data.util.NestedMethodProperty.invokeSetMethod(NestedMethodProperty.java:251) at com.vaadin.data.util.NestedMethodProperty.setValue(NestedMethodProperty.java:231) at com.vaadin.data.util.TransactionalPropertyWrapper.setValue(TransactionalPropertyWrapper.java:94) at com.vaadin.ui.AbstractField.commit(AbstractField.java:253) ... 49 more Caused by: java.lang.NullPointerException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.vaadin.data.util.NestedMethodProperty.invokeSetMethod(NestedMethodProperty.java:247) ... 52 more les muestro el codigo de mi vista y formulario, asi como las entidades a las que quiero realizar el “bind” desde el formulario:

Entity User

[code]
@Entity
@Table(name=“USERS”)
@XmlRootElement
@NamedQueries({
@NamedQuery(name=“User.findAll”, query=“SELECT u FROM User u”),
@NamedQuery(name = “User.findByUsuarioAndPassword”, query = “SELECT l FROM User l WHERE l.id.username = :username and l.id.pass = :pass”)
})
public class User implements Serializable {
private static final long serialVersionUID = 1L;

@EmbeddedId
private UserPK id;

@Temporal(TemporalType.DATE)
@Column(name="CREATION_DATE")
private Date creationDate;

private String email;

private String loggin;

@Temporal(TemporalType.DATE)
@Column(name="MODIFICATION_DATE")
private Date modificationDate;

private String perfil;

public User() {
}

//setters and getters.....

}
[/code]Entity UserPK

@Embeddable
public class UserPK implements Serializable {
    //default serial version id, required for serializable classes.
    private static final long serialVersionUID = 1L;

    private String firtsname;

    private String lastname;

    private String username;

    private String pass;

    public UserPK() {
    }
//setters and getters.....

}

Vista desde mando a llamar un modal o Window

public class UsuarioView extends VerticalLayout implements View{

    private static final long serialVersionUID = -8235808140209855392L;
    
    public static final String VIEW_NAME = "REGISTRO DE USUARIOS";
    
    private Table usuariosTable;
    private TextField searchField;
    private Button newButton;
    private Button deleteButton;
    private Button editButton;
    private JPAContainer<User> usuarios;
    private String textFilter;
    
    public UsuarioView() {
        usuarios = JPAContainerFactory.make(User.class,
                JpaUtil.PERSISTENCE_UNIT);
        usuarios.addNestedContainerProperty("id.username");
        usuarios.addNestedContainerProperty("id.lastname");
        usuarios.addNestedContainerProperty("id.firtsname");
        usuarios.addNestedContainerProperty("id.pass");
        
        buildMainArea();
    }
    
    private void buildMainArea(){
        
        //CONSTRUCCION TABLA
        usuariosTable = new Table(null, usuarios);
        usuariosTable.setSizeFull();
        usuariosTable.setSelectable(true);
        usuariosTable.setImmediate(true);
        usuariosTable.setImmediate(true);
        
        usuariosTable.setVisibleColumns(new Object[] { "id.username", "id.lastname", "id.firtsname", "loggin",
                "perfil", "email", "creationDate", "modificationDate"});
        usuariosTable.setColumnHeaders(new String[] { "USERNAME", "NOMBRES", "APELLIDOS", "ESTATUS", 
                "PERFIL", "CORREO", "FECHA ALTA", "FECHA MODIFICACION"});

//        AGREGAMOS CONVERTIDORES A LAS COLUMNAS
        usuariosTable.setConverter("loggin", new IntegerToStringPerfilConverter());
        usuariosTable.setConverter("perfil", new IntegerToStringPerfilConverter());
        
//        AGREGAMOS EVENTO PARA QUE SE HABILITEN LOS BOTONES DE BORRADO Y EDICION
        usuariosTable.addValueChangeListener(new Property.ValueChangeListener() {
            @Override
            public void valueChange(ValueChangeEvent event) {
                setModificationsEnabled(event.getProperty().getValue() != null);
            }

            private void setModificationsEnabled(boolean b) {
                deleteButton.setEnabled(b);
                editButton.setEnabled(b);
            }
            
        });
        
        //CONSTRUCCION TOOLBAR
        HorizontalLayout toolbar = new HorizontalLayout();
        newButton = new Button("Nuevo");
//        CREAMOS LISTENER PARA EL BOTON NUEVO USUARIO
        newButton.addClickListener(new Button.ClickListener() {

            @Override
            public void buttonClick(ClickEvent event) {
                final BeanItem<User> newUsuarioItem = new BeanItem<User>(new User());
                newUsuarioItem.addNestedProperty("id.username");
                newUsuarioItem.addNestedProperty("id.firtsname");
                newUsuarioItem.addNestedProperty("id.lastname");
                newUsuarioItem.addNestedProperty("id.pass");
                UsuarioEditor usuarioEditor = new UsuarioEditor(newUsuarioItem);

                final String hola = usuarioEditor.getHola();
                usuarioEditor.addCloseListener(new Window.CloseListener(){

                    @Override
                    public void windowClose(CloseEvent e) {

                    
                        Notification.show("Value changed:",
                            String.valueOf(((ValueChangeEvent) e).getProperty().getValue()),
                                Type.TRAY_NOTIFICATION);
                    }
                });
                
        .......
    
}

y el modal donde construyo la forma y utilizo FieldGroup

[code]
public class UsuarioEditor extends Window implements Button.ClickListener {

private static final long serialVersionUID = 19967873878950719L;

private final Item usuarioItem;
private FormLayout editorForm;
private final BeanFieldGroup<User> binder;

private Button saveButton;
private Button cancelButton;
private TextField nombresTxt;
private TextField apellidosTxt;
private TextField usernameTxt;
private TextField passwordTxt;
private TextField emailTxt;
private OptionGroup activoOptionGrp;
private OptionGroup perfilOptionGrp;
private DateField creationDate;
private DateField modificationDate;    

public UsuarioEditor(Item usuarioItem) {

    super("Usuario Editor");
    center();
    setModal(true);

    this.usuarioItem = usuarioItem;
    editorForm = new FormLayout();
    
    nombresTxt = new TextField("NOMBRES:");
    apellidosTxt = new TextField("APELLIDOS:", "");
    usernameTxt = new TextField("USERNAME:", "");
    passwordTxt = new TextField("PASSWORD:", "");
    emailTxt = new TextField("EMAIL:", "");
    activoOptionGrp = new OptionGroup("ACTIVO:");
    perfilOptionGrp = new OptionGroup("PERFIL:");
    creationDate = new DateField("FECHA CREACION:", new Date());
    modificationDate = new DateField("FECHA MODIFICACION:", new Date());

    activoOptionGrp.addItem("0");
    activoOptionGrp.setItemCaption("0", "INACTIVO");
    activoOptionGrp.addItem("1");
    activoOptionGrp.setItemCaption("1", "ACTIVO");

    perfilOptionGrp.addItem("0");
    perfilOptionGrp.setItemCaption("0", "ADMINISTRADOR");
    perfilOptionGrp.addItem("1");
    perfilOptionGrp.setItemCaption("1", "USUARIO");
    
    editorForm.addComponent(nombresTxt);
    editorForm.addComponent(apellidosTxt);
    editorForm.addComponent(usernameTxt);
    editorForm.addComponent(passwordTxt);
    editorForm.addComponent(emailTxt);
    editorForm.addComponent(activoOptionGrp);
    editorForm.addComponent(perfilOptionGrp);
    editorForm.addComponent(creationDate);
    editorForm.addComponent(modificationDate);

    saveButton = new Button("Save", this);
    cancelButton = new Button("Cancel", this);

    HorizontalLayout horizontalLayout = new HorizontalLayout();
    horizontalLayout.addComponent(saveButton);
    horizontalLayout.addComponent(cancelButton);
    editorForm.addComponent(horizontalLayout);

    binder = new BeanFieldGroup<User>(User.class);
    binder.setItemDataSource(new User());
    
    
    binder.bind(nombresTxt, "id.firtsname");
    binder.bind(apellidosTxt, "id.lastname");
    binder.bind(usernameTxt, "id.username");
    binder.bind(passwordTxt, "id.pass");
    binder.bind(emailTxt, "email");
    binder.bind(activoOptionGrp, "loggin");
    binder.bind(perfilOptionGrp, "perfil");
    binder.bind(creationDate, "creationDate");
    binder.bind(modificationDate, "modificationDate");
    
    for (final Object propertyId : binder.getUnboundPropertyIds()) {
        System.out.println("propertyId.-"+propertyId);
    }
    
    setSizeUndefined();
    setContent(editorForm);

}

@Override
public void buttonClick(ClickEvent event) {
    if (event.getButton() == saveButton) {

        try {
            System.out.println("saveButton");
            binder.commit();   <---HERE NPE
            BeanItem ok = ((BeanItem)binder.getItemDataSource());
            System.out.println("bean.-"+ok.getBean().toString());

        } catch (CommitException e) {
            e.printStackTrace();
        }
    } else if (event.getButton() == cancelButton) {
        binder.discard();        
    }
    close();
}        

.......

}
[/code]Otra cosa, es que cuando creo el formulario me aparecen los campos TextField con la palabra “null”

por ultimo, si comento las lineas :

binder.bind(nombresTxt, “id.firtsname”);
binder.bind(apellidosTxt, “id.lastname”);
binder.bind(usernameTxt, “id.username”);
binder.bind(passwordTxt, “id.pass”);

en la clase UsuarioEditor funciona, pero de la siguiente manera:

bean.-User [

id=null,

creationDate=Thu Feb 11 00:00:00 CST 2016, email=correo, loggin=0, modificationDate=Thu Feb 11 00:00:00 CST 2016, perfil=1]

la versión que ocupo de vaadin es
<vaadin.version>7.6.1</vaadin.version>

Gracias de antemano.

Saludos

23104.png