Best practice for ComboBox and BeanField

HI,

i have a little probleme with Many To many and combox with Form.

I have 2 entitys class : User.class and UserRole.class
User.class have :

@ManyToMany
    private Set<UserRole> userRoles;

My process for edit user, i open page with Grid with all users. When i click into a cell , a windows pop up with formlayaut (All textfiels represente my entity class and one combox box for userRoles)

public class UserForm extends FormLayout {

    private MainUi mainUi;
    Button save = new Button("Save", this::save);
    Button cancel = new Button("Close", this::cancel);
    TextField userLogin = new TextField("Login");
    TextField userPassword = new TextField("Password");
    Label userLoginVersion = new Label("Login Version");
    TextField userSecureKey = new TextField("Secure Key");
    ComboBox userProvider = new ComboBox("User Provider");
    OptionGroup userRoles = new OptionGroup("Roles");
    Label userProviderId = new Label("Provider ID");
    TextField userGameName = new TextField("Game name");
    TextField userFastId = new TextField("Fast id");
    DateField userLastConnection = new DateField("Last Connection");
    Label userLastIp = new Label("Last Ip");
    ComboBox userLanguage = new ComboBox("Language");
    ComboBox userCountry = new ComboBox("Country");
    DateField created = new DateField("Created Date");
    DateField updated = new DateField("Created Date");

    BeanItemContainer<UserRole> containerBean = new BeanItemContainer<UserRole>(UserRole.class);
    BeanFieldGroup<User> formFieldBindings;
    User user;

    public UserForm(MainUi mainUi) {
        this.mainUi = mainUi;
        configureComponents();
        buildLayout();
    }

    private void configureComponents() {
        save.setClickShortcut(ShortcutAction.KeyCode.ENTER);
        setVisible(true);
        updated.setReadOnly(true);
        created.setReadOnly(true);
        save.setIcon(new ThemeResource("icons/synchronize2.png"));
        cancel.setIcon(new ThemeResource("icons/loading2.png"));
        userLanguage.addItems(CountryCode.values());
        userCountry.addItems(CountryCode.values());
        userProvider.addItems(UserProvider.values());
        containerBean.addAll(mainUi.userRoleService.getListUserRole());
        // userRoles.addItems(mainUi.userRoleService.getListUserRole());
        userRoles.setContainerDataSource(containerBean);
        userRoles.setMultiSelect(true);
        userRoles.setRequired(true);

    }

    private void buildLayout() {
        setSizeUndefined();
        setMargin(true);
        HorizontalLayout actions = new HorizontalLayout(save, cancel);
        HorizontalLayout groupField = new HorizontalLayout(userLogin, userPassword);
        HorizontalLayout groupField2 = new HorizontalLayout(userFastId, userGameName);
        HorizontalLayout groupField3 = new HorizontalLayout(userSecureKey, userProvider);
        HorizontalLayout groupField4 = new HorizontalLayout(userLanguage, userCountry);
        HorizontalLayout groupField5 = new HorizontalLayout(created, updated);
        actions.setSpacing(true);
        addComponents(groupField, groupField2, groupField3, groupField4, userRoles, userProviderId,
                userLastConnection, userLastIp, userProviderId, userLoginVersion,
                groupField5, actions);
    }

    private void save(Button.ClickEvent event) {
        try {
            formFieldBindings.commit();
            mainUi.userService.saveUserRole(user);
            fireEvent(new DataUpdate(event.getComponent(), DataUpdate.editAction.UPDATE_DATA));
        } catch (FieldGroup.CommitException ex) {
            fireEvent(new DataUpdate(event.getComponent(), DataUpdate.editAction.CLOSE_EDIT));
        }
    }

    private void cancel(Button.ClickEvent event) {
        fireEvent(new DataUpdate(event.getComponent(), DataUpdate.editAction.CLOSE_EDIT));
    }

    public void edit(User user) {
        this.user = user;
        if (user == null) {
            this.user = new User();
        }

        formFieldBindings = BeanFieldGroup.bindFieldsBuffered(this.user, this);
        
        //DEBUG
        if (user.getId() != null) {
            for (UserRole role : containerBean.getItemIds()) {
                System.err.println("1  " + role.hashCode());
            }
        }
        for (UserRole role : user.getUserRoles()) {
            System.err.println("2  " + role.hashCode());
        }

    }
}

Bind working good for all field and i can save object user with new parameters but ComboBox represente all userRoles by not set active actif user role for edit User.

I Understand where is my probleme , i try to print hascode object to my fonction edit and of exemple :

Systeme out :
: 1
86797355
// USER_ROLE_ADMIN object of my combobox
: 1 1388651512 // USER_ROLE_WEB object of my combobox
: 1 1731178725 // USER_ROLE_TEST object of my combobox
: 2
435341188
// USER_ROLE_ADMIN object of my UserRoles list , hashcode is not same but is same object.

Environement : Glassfish 4.1 - Spring 4.2.2 - Spring security 4.0.3 - Hibernate 4.3.5 - Vaadin 7.5.9
Could you help me ?

Question 2 :

I have other little probleme with TextField Component , i have class with longitude and latitude (GPS pos) double format.

When i click to map add call eventlistener for exemple i print Lat: 51.344338660599234 Lon: -1.4666748046875

[code]
TextField containerLatitude = new TextField(“Latitude”);

containerLatitude.setValue(position.getLat()); // Lat is 51.344338660599234
[/code]Textfield cut number and write 51.344 and remove others number.

Coudl you help me ?

Hi Sebastian,

I’d look into your equals/hashCode implementations. I usually implement them like this:


https://github.com/mstahv/jpa-addressbook/blob/master/src/main/java/org/example/backend/AbstractEntity.java#L33-L54

Not a perfect solution for each and every use case, but works well most of the time.

The missing desimals can be brought back by introducing a bit smarter Converter for your field. See
this thread
for more information.

cheers,
matti