0

I would be pleased if I could get my models sub collection into a combobox containing the values of said sub collection. The application I'm making is a hybrid of JavaFX and Spring. I used JavaFX for GUI and Spring Data JPA to interact with my database, which, elsewhere is being worked by a Spring Boot REST API. The models I'm using in my GUI app are copies of the models used in the REST API elsewhere.

Here's the models.

@Entity
@NoArgsConstructor
@Getter
@Setter
@Table(name = "users")
public class User  implements Serializable {
    private static final long serialVersionUID = 65981149772133526L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "USER_ID")
    private Long id;
    
    @Column(name = "PROVIDER_USER_ID")
    private String providerUserId;
    
    @Column(name = "enabled", columnDefinition = "BIT", length = 1)
    private boolean enabled;

    @Column(name = "DISPLAY_NAME")
    private String displayName;

    @Column(name = "created_date", nullable = false, updatable = false)
    @Temporal(TemporalType.TIMESTAMP)
    protected Date createdDate;

    @Temporal(TemporalType.TIMESTAMP)
    protected Date modifiedDate;
    
    private String fullName;
    
    private String phone;
    
    private String company;
    
    private String provider;

    private String username;
    
    private String formEmail;

    @NotBlank
    @Size(max = 50)
    @Email
    private String email;

    @NotBlank
    @Size(max = 120)
    private String password;

    @JsonIgnore
    @ManyToMany
    @JoinTable(name = "user_role", joinColumns = { @JoinColumn(name = "USER_ID") }, inverseJoinColumns = { @JoinColumn(name = "ROLE_ID") })
    private Set<Role> roles;
    
    public User(String username, String email, String pass) {
        this.username = username;
        this.email = email;
        this.password = pass;
    }

}

Here's the Role model.

package com.example.javafx;

import java.io.Serializable;
import java.util.Set;

import javax.persistence.*;

import com.example.javafx.Role;
import com.example.javafx.User;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Entity
@Getter
@Setter
@NoArgsConstructor
public class Role implements Serializable {
    private static final long serialVersionUID = 1L;
    public static final String USER = "USER";
    public static final String ROLE_USER = "ROLE_USER";
    public static final String ROLE_ADMIN = "ROLE_ADMIN";
    public static final String ROLE_MODERATOR = "ROLE_MODERATOR";

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ROLE_ID")
    private Long roleId;

    @Column(name = "USER_ID")
    private String name;

    // bi-directional many-to-many association to User
    @ManyToMany(mappedBy = "roles")
    private Set<User> users;

    public Role(String name) {
        this.name = name;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Role role = (Role) obj;
        if (!role.equals(role.name)) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        final StringBuilder builder = new StringBuilder();
        builder.append("Role [name=").append(name).append("]").append("[id=").append(roleId).append("]");
        return builder.toString();
    }
}

ERole enum

public enum ERole {
    ROLE_USER,
    ROLE_MODERATOR,
    ROLE_ADMIN
}

The repo.

public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUsername(String username);

    Boolean existsByUsername(String username);

    Boolean existsByEmail(String email);
    
    User findByEmail(String email);
}
@Component
public class SimpleUiController {

@Autowired
private UserRepository userRepo;
@FXML
private TableView<User> users_table;
    
@FXML
private TableColumn user_id_col;

@FXML   
private TableColumn<User, Set<Role>> user_roles_col;

public void syncUsersTableWithDB() {
        List<User> userFromServer = userRepo.findAll();
        users = FXCollections.observableArrayList(userFromServer);
        user_id_col.setCellValueFactory(new PropertyValueFactory("id"));
        user_email_col.setCellValueFactory(new PropertyValueFactory("email"));
        password_hash_col.setCellValueFactory(new PropertyValueFactory("password"));
        user_fullname_col.setCellValueFactory(new PropertyValueFactory("fullName"));
        user_formEmail_col.setCellValueFactory(new PropertyValueFactory("formEmail"));
        user_phone_col.setCellValueFactory(new PropertyValueFactory("phone"));
        user_company_col.setCellValueFactory(new PropertyValueFactory("company"));
        //user_roles_col.
        user_enabled_col.setCellValueFactory(new PropertyValueFactory("enabled"));
        user_created_col.setCellValueFactory(new PropertyValueFactory("createdDate"));
        user_modified_col.setCellValueFactory(new PropertyValueFactory("modifiedDate"));
        
        
        users_table.setItems(users);
    }
}

You'll see there is a user_roles_col access in the syncUsersTableWithDB function. I had other attempts but I'm not confident in my approach.

I tried setting a PropertyValueFactory like the others, then trying to modify the Set into strings of roles but was unable. So what I want to do is turn the Set into strings of the role string in a Combobox in a TableView. I hope I have explained it well, let me know if I need to explain further.

Adam Howard
  • 181
  • 5
  • 16
  • 1
    [mcve] please (mind the __M__!) and stick to java naming conventions – kleopatra Apr 12 '21 at 06:49
  • 2
    Why a combo box? A combo box is used to select something from a list; as far as I can tell here there's no notion of selecting one of the roles from the user's set of roles. Surely just a `ListView` would be more appropriate? But anyway, just set the `cellValueFactory` the same way as you do with the other columns, and set a `cellFactory` to return a cell displaying the roles the way you want. – James_D Apr 12 '21 at 13:23
  • @James_D yes I see what you're saying. I thought combobox would be a good fit. It's only for me anyway it's not an enterprise app. I must get better at these callbacks. Thanks for the reply. Ya I must look into the listview instead. – Adam Howard Apr 12 '21 at 15:04
  • For anyone looking for a solution to this problem, https://stackoverflow.com/questions/31126123/how-to-show-a-list-on-table-column-with-few-fields-of-list-items was helpful. Also set fetch type lazy to your many to many relationship. All the best. – Adam Howard Apr 12 '21 at 15:14

0 Answers0