JFXComboBox does not show default set value - javafx

I am using a JFXComboBox to show user group a user can be allocated to. The roles are fetched from the DB. Fetching of the rolelist is done by getRoleNameList(). I populate the JFXComboBox as below:
Populate userGroup JFXComboBox
// Populate userGroup JFXComboBox
ObservableList<Role> roles = rdc.getRoleNameList();
roles.sort(Comparator.comparing(Role::getCode)); // Sort the list
uGroupComboBox.getItems().setAll(roles);
uGroupComboBox.setVisibleRowCount(5);
JFXCombobox FXML:
<JFXComboBox id="userGroup" fx:id="uGroupComboBox" focusColor="#07595a"
layoutX="245.0" layoutY="256.0" prefHeight="30.0" prefWidth="148.0"
promptText="Select User Group" styleClass="jfx-combo-box"
unFocusColor="#48aaad">
The model below is for Roles:
package records.models;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import org.apache.commons.lang3.StringUtils;
public class Role {
private final StringProperty code;
private final StringProperty name;
public Role() {
this.name = new SimpleStringProperty();
this.code = new SimpleStringProperty();
}
public Role(String name) {
String codename = StringUtils.capitalize(name.toLowerCase().trim());
this.code = new SimpleStringProperty(codename);
name = name.toLowerCase().trim();
this.name = new SimpleStringProperty(name);
}
// name
public String getName() {
return name.get();
}
public void setName(String name) {
if (name != null) {
name = name.toLowerCase().trim();
}
this.name.set(name);
}
public StringProperty nameProperty() {
return name;
}
// #return code
public String getCode() {
return code.get();
}
public void setCode(String code) {
if (code != null) {
code = StringUtils.capitalize(code.toLowerCase().trim());
}
this.code.set(code);
}
public StringProperty codeProperty() {
return code;
}
public Role getRole(){
return this;
}
#Override
public String toString(){
return this.code.get();
}
}
When I fetch from the DB the user group the user is assigned to, the data is not displayed:
String uRole = role.get("role") == null ? null :
role.get("role").toString();
user.setRole(uRole);
// Create the role that is fetched from DB
Role uGroup = new Role(uRole);
// uGroupComboBox.setValue(uGroup);
uGroupComboBox.getSelectionModel().select(uGroup);
This does not work. As you can see, the field is not null. If it were, I would show the prompt text
However, the JFXComboBox list is successfully populated:
If I do System.out.println(uGroupComboBox.getValue()); it shows the correct value eg. if the user group is Nurse, the statement returns Nurse
Why does the JFXComboBox not display the value?

The problem is in your Role object with its StringProperty properties. Let me explain myself.
if you just take :
static void main(String[] args){
StringProperty codeName = new SimpleStringProperty("codename");
StringProperty codeNameSameValue = new SimpleStringProperty("codename");
boolean isthesame = codeName.equals(codeNameSameValue);
System.out.println("isthesame:"+isthesame);
boolean isReallyTheSame = codeName.get().equals(codeNameSameValue.get());
System.out.println("isReallyTheSame:"+isReallyTheSame);
}
You will see on you console output
isthesame:false
isReallyTheSame:true
Ok it is still not the answer to your question but for you Role class default equals method that will be comparing object properties like my first comparison:
comparingStringProperty.equals(comparedStringProperty);
...
To solve the problem you need to override the equals method in the Role object. For example with something like that:
i
mport java.util.Objects;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import org.apache.commons.lang3.StringUtils;
public class Role {
private final StringProperty code;
private final StringProperty name;
/*Constructors, setters and getter are deleted for clarity */
....
#Override
public String toString() {
return this.code.get();
}
#Override
public boolean equals(Object o) {
// If the object is compared with itself then return true
if (o == this) {
return true;
}
/* Check if o is an instance of Role or not
"null instanceof [type]" also returns false */
if (!(o instanceof Role)) {
return false;
}
// typecast o to Role so that we can compare data members
Role r = (Role) o;
return (r.name.get() == this.name.get() || r.name.get() != null && r.name.get().equals(this.name.get()));
}
#Override
public int hashCode() {
return Objects.hash(name.get(), code.get());
}
}
This equals method will be use during the call :
uGroupComboBox.getSelectionModel().select(uGroup);
And voila!

Related

Unable select Javafx combobox items programmatically which uses objects

In the JavaFx ComboBox which uses a class object list .I want to select items in the ComboBox programmatically using getSelectionModel().select(object or index). i am not getting the desired result Although the value is set but it is something like this main.dao.Company.Company.CompanyTableData#74541e7b.
The code is somewhat like this.
ComboBox<CompanyTableData> company = new ComboBox<>();
company.setItems(GetCompany.getCompanyTableData());//where Observable list is set..
GetCompany.getCompanyTableData() returns observablelist of CompanyTableData class.
The ComboBox Looks as follows.
The CompanyTableData Class is as.
public class CompanyTableData {
private SimpleStringProperty itemCompanyId;
private SimpleStringProperty itemCompanyName;
private SimpleStringProperty createBy;
private SimpleStringProperty createdOn;
public CompanyTableData(CompanyData companyData){
this.itemCompanyId = new SimpleStringProperty(companyData.getItemCompanyId());
this.itemCompanyName = new SimpleStringProperty(companyData.getItemCompanyName());
this.createBy = new SimpleStringProperty(companyData.getCreatedBy());
this.createdOn = new SimpleStringProperty(companyData.getCreatedOn());
}
public String getItemCompanyId() {
return itemCompanyId.get();
}
public SimpleStringProperty itemCompanyIdProperty() {
return itemCompanyId;
}
public void setItemCompanyId(String itemCompanyId) {
this.itemCompanyId.set(itemCompanyId);
}
public String getItemCompanyName() {
return itemCompanyName.get();
}
public SimpleStringProperty itemCompanyNameProperty() {
return itemCompanyName;
}
public void setItemCompanyName(String itemCompanyName) {
this.itemCompanyName.set(itemCompanyName);
}
public String getCreateBy() {
return createBy.get();
}
public SimpleStringProperty createByProperty() {
return createBy;
}
public void setCreateBy(String createBy) {
this.createBy.set(createBy);
}
public String getCreatedOn() {
return createdOn.get();
}
public SimpleStringProperty createdOnProperty() {
return createdOn;
}
public void setCreatedOn(String createdOn) {
this.createdOn.set(createdOn);
}
}
The Cell Factory is set
company.setCellFactory(param -> new CompanyCell());
And the CompanyCell
public class CompanyCell extends ListCell<CompanyTableData> {
#Override
protected void updateItem(CompanyTableData item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null || item.getItemCompanyName() == null) {
setText(null);
} else {
setText(item.getItemCompanyName());
}
}
}
After all this when i try to set the items programmetically as
company.getSelectionModel().select(getSelectedCompanyIndex());
The getSelectedCompanyIndex() function is as follows.
public static CompanyTableData getSelectedCompanyIndex(){
CompanyTableData c = null,i;
Iterator<CompanyTableData> itr = GetCompany.getCompanyTableData().iterator();
while (itr.hasNext()){
i = itr.next();
if (i.getItemCompanyName().equals(Element.getItemTableData().getCompany())){
c = i;
}
}
return c;
}
And the result i am getting is
And
At the end it should select a name or item in the list but it has set some type of object i think.
Now what should i do. Is there any type of string conversion required.
The buttonCell used to display the item when the combobox popup is not shown is not automatically created using the cellFactory. You need to set this property too to use the same cell implementation:
company.setCellFactory(param -> new CompanyCell());
company.setButtonCell(new CompanyCell());

Unable to get insert, update and delete to work with spring-data-jpa

I am trying to create a web service that performs basic CRUD operations written using spring boot 2. The select operation works fine, however the insert, delete and update operations have no effect as their query is not getting generated and executed.
I have looked through different examples but I am unable to figure out any issues. The major concern for me is the fact that not even a query is being triggered for insert, delete or update operations.
Student Entity
#Entity
#Table(name = "student")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Student {
#Id
#NotNull
#Column(name = "id")
private int id;
#NotNull
#Column(name = "name")
private String name;
#Column(name = "course")
private String course;
public Student(int id, String name, String course) {
this.id = id;
this.name = name;
this.course = course;
}
public Student(){}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
#Override
public String toString() {
return "Student{ id=" + id + ", name='" + name + '\'' + ", course='" + course + '\'' + '}';
}
}
StudentDaoImpl
#Repository
#Transactional
public class StudentDaoImpl implements StudentDao {
#Autowired
private EntityManagerFactory entityManagerFactory;
#Override
public List<Student> fetchAllStudents() {
Session session = entityManagerFactory.unwrap(SessionFactory.class).openSession();
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<Student> cq = cb.createQuery(Student.class);
Root<Student> root = cq.from(Student.class);
CriteriaQuery<Student> all = cq.select(root);
List<Student> solution = session.createQuery(all).getResultList();
session.close();
return solution;
}
#Override
public Student deleteStudent(Integer id) {
Session session = entityManagerFactory.unwrap(SessionFactory.class).openSession();
Student student = session.load(Student.class, id);
if (student != null){
session.delete(student);
session.close();
}
return student;
}
#Override
public Student fetchForId(Integer id){
Session session = entityManagerFactory.unwrap(SessionFactory.class).openSession();
Student student = session.load(Student.class, id);
session.close();
return student;
}
#Override
public Student insertStudent(Student student) {
Session session = entityManagerFactory.unwrap(SessionFactory.class).openSession();
session.save(student);
session.close();
return student;
}
#Override
public Student updateStudent(Student student) {
Session session = entityManagerFactory.unwrap(SessionFactory.class).openSession();
Student studentCheck = session.load(Student.class, student.getId());
if (studentCheck != null) {
session.saveOrUpdate(student);
session.close();
}
return student;
}
}
application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=
spring.jpa.database = MYSQL
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = update
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
Edit
Replacing EntityManagerFactory with EntityManager( + Persistent Context Annotation) worked for me. However I still haven't figured why persistence worked for EntityManager.
If it's not strictly important, you can do it using NativeQuery and its executeUpdate API:
String query = "insert into student values(1,?)";
em.createNativeQuery(query)
.setParameter(1, "Tom")
.executeUpdate();
I would like to suggest this repository
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface StudentRepository extends JpaRepository<Student, Integer> {
}
Probably you have to change the id of Student from int to Integer.
And this repository has the methods for retrieving, updating, creating and deleting.
Let's say that you want to use this repository in a Service, you can do that like this:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
#Service
#Transactional(rollbackFor = Exception.class)
public class StudentService {
#Autowired
private StudentRepository studentRepository;
......
}

Is there a way we can put the decorator /interceptor on all the objects that are being declared as field of a class?

I have a class Teacher which have two variables one is a collection of Student class and another is a Student class Object. I intercept the Teacher class as per my understanding all the objects under the Teacher class should have the interceptor attached to it.
so for instance one we call a getter method on the Student variable retrieved from the Teacher class or from the list .It should call the intercept method is not called.This makes our axiom for design false.So my question is : Is there a way we can automatically intercept all the objects declared within the class and this could extend to the further down hierarchy within the tree?
Below is the code :
//Teacher class
package com.anz.interceptorproject;
import java.util.ArrayList;
import java.util.List;
/**
* Created by mehakanand on 4/24/16.
*/public class Teacher {
private String userName;
private String cource;
private List<Student> students=new ArrayList<Student>( );
public Student getComplexObjectStudent() {
return complexObjectStudent;
}
public void setComplexObjectStudent( Student complexObjectStudent ) {
this.complexObjectStudent = complexObjectStudent;
}
private Student complexObjectStudent=new Student();
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getCource() {
return cource;
}
public void setCource(String cource) {
this.cource = cource;
}
}
//Student Class
package com.anz.interceptorproject;
/**
* Created by mehakanand on 4/24/16.
*/public class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//Interceptor Class
package com.anz.interceptorproject.change;
import java.lang.reflect.*;
import net.sf.cglib.proxy.*;
/**
* Created by mehakanand on 4/24/16.
*/
public class ClassFacadeCglib implements MethodInterceptor{
private Object target;
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// callback method
enhancer.setCallback(this);
// create proxy object
return enhancer.create();
}
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
Object res=null;
if(method.getName().startsWith("set")){
System.out.println(method.getName()+" start");
res = method.invoke(target, args);
proxy.invokeSuper(obj, args);
System.out.println(method.getName()+" end..");
}
if(method.getName().startsWith("get")){
System.out.println(method.getName()+" start");
res = method.invoke(target, args);
proxy.invokeSuper(obj, args);
System.out.println(method.getName()+" end");
}
return res;
}
}
//Delegate class
package com.anz.interceptorproject;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import net.sf.cglib.proxy.MethodInterceptor;
import org.junit.Test;
public class SimpleUnitTest {
// this test is being used to test if when object is being intercepted will all its child object be intercepted automatically or not
#Test
public void TestifchildrenObjectIntercepted() {
String proxyStudentName="";
ClassFacadeCglib cglib=new ClassFacadeCglib();
Student studentMehak=new Student();
studentMehak.setAge( 30 );
studentMehak.setName( "Mehak Anand" );
Student studentComploexproxy=new Student();
studentComploexproxy.setAge( 23 );
studentComploexproxy.setName( "proxystudent Complex" );
//let us assume the Teacher object is an object return from JCR after the adapTo() function is called on a resource
Teacher teacher=new Teacher();
teacher.setComplexObjectStudent( studentComploexproxy );
teacher.getStudents().add( studentMehak );
teacher.setCource("Math");
teacher.setUserName("Mehak");
teacher.getUserName();
Teacher proxyTeacher=(Teacher)cglib.getInstance(teacher);
/ proxyTeacher.getClass().getDeclaredMethods();
for (Student proxyStudentList:proxyTeacher.getStudents())
{
//the intercept method is not called.
proxyStudentName= proxyStudentList.getName();
}
Student testComplexStudent=teacher.getComplexObjectStudent();
assertEquals("Math",proxyTeacher.getCource());
//the intercept method is not called
testComplexStudent.getAge();
System.out.println( teacher.getUserName());
assertTrue(true);
}
}
my understanding all the objects under the Teacher class should have the interceptor attached to it. so for instance one we call a getter method on the Student variable retrieved from the Teacher class or from the list .It should call the intercept method
This is not true. Method interceptors are attached only to the object created with enhancer.create(). Any object created with class constructor - such as your Student objects - are not enhanced and thus have no interceptors attached. The one possible solution is to use factory method instead of public constructor to produce enhanced objects:
public class Student {
protected Student() {
}
public static Student getInstance() {
Enhancer e = new Enhancer();
// set superclass, interceptors etc here....
return (Student) e.create();
}
}

How to make TableCell editable , so it automatically updates the data class?

I am making a system for a school project , and one part of it is a TableView that is populated with rows using my own data class InventoryData that has properties correspondent to the table columns. I would like to make cells in some columns editable using a TextField, so that when an edit is committed, it will update the InventoryData object's relevant property.
I tried setting TextFieldTableCell.forTableColumn() as the cell factory of the columns. Although, now after committing the edit, the text in the cell will change, I don't think it is changing the property in the InventoryData object. The reason why I think that, is because when I try to edit that cell again ( after already being edited once), the TextField shows the former value ( before the first edit).
Did I do something wrong , or is that normal behavior and I have to implement the commits myself?
Here's the code for InventoryData :
package UILayer.TableData;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import ModelLayer.Product;
public class InventoryData {
// From Product
private Product productObj;
private SimpleIntegerProperty id;
private SimpleStringProperty name;
// Constructor - converts Product obj into InventoryData
public InventoryData(Product product)
{
this.productObj = product;
this.id = new SimpleIntegerProperty(product.getId());
this.name = new SimpleStringProperty(product.getName())
}
// GET & SET
public Product getProduct()
{
return productObj;
}
public int getId() {
return id.get();
}
public void setId(int id) {
this.id.set(id);
}
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.set(name);
productObj.setName(name);
System.out.println(productObj.getName());
}
}
You need your InventoryData class to use the JavaFX Properties pattern. Specifically it needs property-type accessor methods in order to retrieve the property in the table cells. Without this, the cell value factory just calls the standard getName() or getId() method, and wraps the result in a ReadOnlyStringWrapper (or ReadOnlyIntegerWrapper): the table cell cannot change the values of those wrappers (since they are read only).
public class InventoryData {
// From Product
private Product productObj;
private IntegerProperty id;
private StringProperty name;
// Constructor - converts Product obj into InventoryData
public InventoryData(Product product)
{
this.productObj = product;
this.id = new SimpleIntegerProperty(product.getId());
this.name = new SimpleStringProperty(product.getName())
this.name.addListener((obs, oldName, newName) ->
productObj.setName(newName));
}
// GET & SET
public Product getProduct()
{
return productObj;
}
public IntegerProperty idProperty() {
return id ;
}
public final int getId() {
return idProperty().get();
}
public final void setId(int id) {
idProperty().set(id);
}
public StringProperty nameProperty() {
return name ;
}
public final String getName() {
return nameProperty().get();
}
public final void setName(String name) {
this.nameProperty().set(name);
// productObj.setName(name);
// System.out.println(productObj.getName());
}
}

How can I retrieve/store a result set to an ArrayList?

How do I use the JdbcTemplate.query()/queryForList() to run a query using namedParameter and store the result set into a List of 'User's?
User Class:
public class User {
String name = null;
String id = null;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return name;
}
public void setId(String id) {
this.id = id;
}
}
Query:
SELECT name, id FROM USERS where email=:email
I'm looking for something like:
ArrayList<User> userList = jdbcTemplate.query(sql_query,
...some_mapper..., etc);
Seems like the answer to the question is not available at one place, on the Internet. Here's what I found out:
For adding the resultset into a List<>, we can use the NamedParameterJdbcTemplate.query() function:
NamedParameterJdbcTemplate jdbcTemplate;
ArrayList<User> usersSearchResult = (ArrayList<User>) jdbcTemplate.query(
USER_LIST_TP_query,
namedParameters,
new RowMapperResultSetExtractor<User>(new UserRowMapper(), 20));
We also have to define a custom RowMapperResultSetExtractor so that JDBC can understand how to convert each row in the result set to the type User.
private class UserRowMapper implements RowMapper<User> {
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getString("ID"));
user.setName(rs.getString("NAME"));
return user;
}
}

Resources