FXML: Bind to nested field - javafx

I have a TableColumn coded as:
<TableColumn text="Nom" prefWidth="${purchasesTable.width*0.65}">
<cellValueFactory>
<PropertyValueFactory property="item.name" />
</cellValueFactory>
</TableColumn>
it's TableView's items property is bound to a list of Purchase class:
Purchase class:
public class Purchase {
private Item item;
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
}
My Item class is as follows:
public class Item {
private long id;
private StringProperty name = new SimpleStringProperty();
private DoubleProperty price = new SimpleDoubleProperty();
//Getters and Setters
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
}
when I add Purchases to my table the name cell do not appear. What am I doing wrong? and is it necessary to my Item fields as properties, because I want to use them somewhere else where JavaFX is not used?

PropertyValueFactory does not support "properties of properties". You need to implement the Callback yourself here, which has to be done in the controller class:
public class MyController {
#FXML
private TableColumn<Purchase, String> nameColumn ;
public void initialize() {
nameColumn.setCellValueFactory(cellData -> {
String name ;
Purchase purchase = cellData.getValue();
if (purchase == null) {
name = null ;
} else {
name = purchase.getName();
}
return new SimpleStringProperty(name);
});
// ...
}
// ...
}
and then in the fxml, of course, you need to map the table column to the field in the controller
<TableColumn fx:id="nameColumn" text="Nom" prefWidth="${purchasesTable.width*0.65}" />

Related

java.lang.NoSuchMethodException Gluon Connect

please i get this errror on logcat when i use restclient to get a list. it works on desktop just after deploymnet to android
java.lang.NoSuchMethodException: ...dto.Meeting.()
its pops up more than the number of record i have in my list
WARNING: Failed to create object of type class .Meeting from the following json object {"id":1,"topic":"leksyde","description":"123e4","location":"7623","longitude":"45","latitude":"10","category":null,"datetime":"9839823"}
primary.setShowTransitionFactory(BounceInRightTransition::new);
RestClient restClient = RestClient.create()
.method("GET")
.host(LISTOFMEETINGS);
// create a custom Converter that is able to parse the response into a list of objects
InputStreamIterableInputConverter<Meeting> converter = new ItemsIterableInputConverter<>(Meeting.class);
// retrieve a list from the DataProvider
GluonObservableList<Meeting> data = DataProvider.retrieveList(restClient.createListDataReader(converter));
data.initializedProperty().addListener((obs, ov, nv) -> {
if (nv) {
for (Meeting meet: data) {
meetingslv.setItems(meet);
}
}
});
meeting.java
public class Meeting {
private IntegerProperty id = new SimpleIntegerProperty();
private StringProperty topic = new SimpleStringProperty();
private StringProperty description = new SimpleStringProperty();
private StringProperty location = new SimpleStringProperty();
private StringProperty longitude = new SimpleStringProperty();
private StringProperty latitude = new SimpleStringProperty();
private StringProperty datetime = new SimpleStringProperty();
private StringProperty category = new SimpleStringProperty();
public Meeting() {
}
public Meeting(int id, String topic, String description, String location, String longitude, String latitude, String datetime, String category) {
this.id = new SimpleIntegerProperty(id);;
this.topic = new SimpleStringProperty(topic);
this.description = new SimpleStringProperty(description);
this.location = new SimpleStringProperty(location) ;
this.longitude = new SimpleStringProperty(longitude);
this.latitude = new SimpleStringProperty(latitude);
this.datetime = new SimpleStringProperty(datetime);
this.category = new SimpleStringProperty(category);
}
public int getId() {
return id.get();
}
public IntegerProperty IdProperty() {
return id;
}
public void setId(int id) {
this.id.set(id);
}
public String getTopic() {
return topic.get();
}
public StringProperty TopicProperty() {
return topic;
}
public void setTopic(String id) {
this.topic.set(id);
}
public String getDescription() {
return description.get();
}
public StringProperty DescriptionProperty() {
return description;
}
public void setDescription(String id) {
this.description.set(id);
}
public String getLocation() {
return location.get();
}
public StringProperty LocationProperty() {
return location;
}
public void setLocation(String id) {
this.location.set(id);
}
public String getLongitude() {
return longitude.get();
}
public StringProperty LongitudeProperty() {
return longitude;
}
public void setLongitude(String id) {
this.longitude.set(id);
}
public String getLatitude() {
return latitude.get();
}
public StringProperty LatitudeProperty() {
return latitude;
}
public void setLatitude(String id) {
this.latitude.set(id);
}
public String getDatetime() {
return datetime.get();
}
public StringProperty DatetimeProperty() {
return datetime;
}
public void setDatetime(String id) {
this.datetime.set(id);
}
public String getCategory() {
return category.get();
}
public StringProperty CategoryProperty() {
return category;
}
public void setCategory(String id) {
this.category.set(id);
}
}
this is the list i am trying to parse to the listview [enter link description here]1

main page doesn't get updated after initialisation is finished

I am having issues with binding context, after initialisation it doesn't update. so the button is not clickable and the name label doesn't update as its stated in ctor. This is the first and only page.
Page
<Label x:Name="NamesLabels" Text="{Binding Name}"/>
<Button HorizontalOptions="FillAndExpand" Text="Show scanner" Command="{Binding ShowScannerCommand}"/>
public MainPage()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
BindingContext = new MainPageViewModel();
}
//also tried
protected override void OnAppearing()
{
base.OnAppearing();
var context = new MainPageViewModel();
BindingContext = context;
name.Source = context.Name;
btn.Command = context.ShowScannerCommand;
}
ViewModel
public string Name
{
get => _name;
private set
{
_name = value;
NotifyPropertyChanged("Name");
}
}
public ICommand ShowScannerCommand { get; private set; }
public MainPageViewModel()
{
Name = "rwatag";
//have tried _name = "rwatag";
ShowScannerCommand = new Command(() => ShowScanner());
}
void ShowScanner()
{
System.Diagnostics.Debug.WriteLine("result");
}
this is what I get after clicking on button and when debugging the code doesn't get fired
[InputEventReceiver] Slow Input: took 118ms in dispatching, now at finishInputEvent (MotionEvent: event_seq=0, seq=78288, action=ACTION_DOWN)
Resolved pending breakpoint at '/Users/de/Projects/Demo/Demo/View/MainPage.xaml.cs:26,1' to void Demo.MainPage.OnAppearing () [0x00014].
[zygote] Do partial code cache collection, code=61KB, data=59KB
[zygote] After code cache collection, code=61KB, data=59KB
[zygote] Increasing code cache capacity to 256KB
I use your code and it works well on my side. I just add a string _name { get; set; } property and implement the INotifyPropertyChanged interface in MainPageViewModel.
Here is the code example:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new MainPageViewModel();
}
}
public class MainPageViewModel : INotifyPropertyChanged
{
string _name { get; set; }
public string Name
{
get => _name;
private set
{
_name = value;
OnPropertyChanged("Name");
}
}
public ICommand ShowScannerCommand { get; private set; }
public MainPageViewModel()
{
Name = "rwatag";
ShowScannerCommand = new Command(() => ShowScanner());
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
void ShowScanner()
{
System.Diagnostics.Debug.WriteLine("result");
}
}

Dynamically update row style javaFX

Suppose you have an ObservableList of Product
ObservableList<Product> = FXCollections.observableArrayList();
Where Product is defined as:
public class Product{
SimpleStringProperty name;
SimpleStringProperty status;
public void setName(String name){
this.name.set(name);
}
public String getName(){
return this.name.get();
}
public SimpleStringProperty nameProperty(){
return name;
}
public void setStatus(String status){
this.status.set(status);
}
public String getStatus(){
return this.status.get();
}
public SimpleStringProperty statusProperty(){
return status;
}}
In order to have the rows of my TableView bold if status is "Available" i've written this rowFactory:
mytable.setRowFactory(new Callback<TableView<Product>, TableRow<Product>>() {
#Override
public TableRow<Product> call(TableView<Product> param) {
return new TableRow<Product>() {
#Override
protected void updateItem(Product item, boolean empty) {
super.updateItem(item, empty);
if (item == null) {
setStyle("");
} else {
String status= item.getStatus();
if (!status.equals("Available")) {
setStyle("");
} else {
setStyle("-fx-font-weight: bold");
}
}
}
};
}
});
The problem is that if i update the model( observablelist) by changing some product' status to available when the table is already displayed, the row doesn't change its style! Can you help me?

Spring And Hibernate MVC

Hey guys i have stuck in the hibernate Relation with spring MVC , I have class like Student and this class is having the OneToOne relation with the Parent class ,My Error is When i tried to delete Student Object the parent Object Doesn't allow to delete the Student Object
It is giving an error like
Hibernate: delete from Student where id=?
WARN : org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 1451, SQLState: 23000
ERROR: org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Cannot delete or update a parent row: a foreign key constraint fails (`digischool`.`parent`, CONSTRAINT `FK_l65r4icaxmteeq1tg96t6n3ol` FOREIGN KEY (`student_id`) REFERENCES `student` (`id`))
"
i have Student Model Class like
#Entity
public class Student implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private long id;
private String name;
private Parent parent;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToOne(mappedBy="student",fetch=FetchType.EAGER)
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
}
Parent model class like
#Entity
public class Parent {
private long id;
private String name;
private String phoneNumber;
private String email;
private String relation;
private Student student;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
#OneToOne(fetch=FetchType.EAGER)
#JoinColumn(name="student_id")
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public String getRelation() {
return relation;
}
public void setRelation(String relation) {
this.relation = relation;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
In order to delete Student Object i have written DAO like
public boolean deleteStudent(long studentId) {
if(studentId > 0){
Session session = getSessionFactory().getCurrentSession();
Query query = session.createQuery("DELETE FROM Student S WHERE S.id = :studentId");
query.setParameter("studentId", studentId);
int rowChanged = query.executeUpdate();
if(rowChanged > 0){
return true;
}
}
return false;
}
My db is looks like
Please help me out i am new bee to this Spring World
This is because you are forgeting to remove the relationship from the parent entity prior to deleting the student.
the way to do this:
public boolean deleteStudent(long studentId) {
if(studentId > 0){
// get parent object
parent.setStudent(null); // THIS REMOVES THE RELATIONSHIP FROM PARENT CLASS SINCE ITS STORED THERE
// save parent object with emptied student field
Session session = getSessionFactory().getCurrentSession();
Query query = session.createQuery("DELETE FROM Student S WHERE S.id = :studentId");
query.setParameter("studentId", studentId);
int rowChanged = query.executeUpdate();
if(rowChanged > 0){
return true;
}
}
return false;
}
FYI
use the hibernates own functions when you can.
check out this link for some ways to delete a object http://www.codejava.net/frameworks/hibernate/hibernate-basics-3-ways-to-delete-an-entity-from-the-datastore
You can use attribute orphanRemoval = true with annotation #OneToOne with your Parent entity
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
public Student getStudent() {
return student;
}
....
hope it help.

SpringMVC 3 - Error in displaying the nested object's property in a <c:forEach> list object

i am new for Spring MVC. In my small crm project, i want to display a objectList with nested object. But it show only a object inside objectname like de.fischerlandmaschinen.crm.model.Employee#6018ebcc statt the converted name string.
the below are the codes:
Domain:
#Entity
#Table(name = "CUSTOMER")
public class Customer implements Serializable {
private static final long serialVersionUID = 5015685214532097319L;
private Long id;
private String foreignId;
private String title;
private String firstName;
private String middleName;
#NotEmpty
private String lastName;
#Enumerated(EnumType.STRING)
private Gender gender;
#Past
#Temporal(TemporalType.DATE)
private Date dateOfBirth;
#Valid
private Address address = new Address();
#Valid
private Contact contact = new Contact();
private Company company = null; // new Company();
private String notice;
#Past
#Temporal(TemporalType.DATE)
private Date createdDate;
#Past
#Version
#Temporal(TemporalType.DATE)
private Date lastUpdatedDate;
private String status;
private Employee primaryConsultant = null; //new Employee();
private Employee secondaryConsultant = null; //new Employee();
public Customer(){
createdDate = new Date();
lastUpdatedDate = new Date();
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "customer_id")
public Long getId() {
return id;
}
public void setId(Long customerId) {
this.id = customerId;
}
#Column(name = "foreign_id")
public String getForeignId() {
return foreignId;
}
public void setForeignId(String foreignId) {
this.foreignId = foreignId;
}
#OneToOne(cascade = CascadeType.ALL)
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
#OneToOne(cascade = CascadeType.ALL)
public Contact getContact() {
return contact;
}
public void setContact(Contact contact) {
this.contact = contact;
}
#Column(name = "created_date")
public Date getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
#Column(name = "date_of_birth")
public Date getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
#ManyToOne(fetch=FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
#JoinColumn(name="company", nullable=true)
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
public String getNotice() {
return notice;
}
public void setNotice(String notice) {
this.notice = notice;
}
#Column(name = "last_updated_date")
public Date getLastUpdatedDate() {
return lastUpdatedDate;
}
public void setLastUpdatedDate(Date lastUpdatedDate) {
this.lastUpdatedDate = lastUpdatedDate;
}
// #ManyToOne(fetch=FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name="primary_consultant", nullable=true)
public Employee getPrimaryConsultant() {
return primaryConsultant;
}
public void setPrimaryConsultant(Employee primaryConsultant) {
this.primaryConsultant = primaryConsultant;
}
// #ManyToOne(fetch=FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name="secondary_consultant", nullable=true)
public Employee getSecondaryConsultant() {
return secondaryConsultant;
}
public void setSecondaryConsultant(Employee secondaryConsultant) {
this.secondaryConsultant = secondaryConsultant;
}
}
and the Employee Domain:
#Entity
#Table(name = "EMPLOYEE")
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String alias;
private String title;
private String firstName;
private String middleName;
private String lastName;
// getter and setter
}
In my Controller:
#RequestMapping(value = "customer/list")
public ModelAndView list() {
ModelAndView mav = new ModelAndView("customer/list");
List<Customer> customers = customerService.getAllCustomers();
mav.addObject("customerList", customers);
return mav;
}
#InitBinder
protected void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
dateFormat.setLenient(false);
binder.setAutoGrowNestedPaths(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(
dateFormat, true));
binder.registerCustomEditor(Gender.class, new GenderEditor());
binder.registerCustomEditor(Employee.class,
new CustomEmployeePropertyEditor(employeeService));
}
And i have a CustomEmployeePropertyEditor extends PropertyEditorSupport for initBinder:
#Override
public void setAsText(String text) {
logger.info("convert string to employee object");
if (text == null || text.length() == 0) {
setValue(null);
return;
}
Long id = (Long) typeConverter.convertIfNecessary(text, Long.class);
if (id == null) {
setValue(null);
return;
}
setValue(employeeService.getEmployee(id));
}
#Override
public String getAsText() {
logger.info("convert employee object to string");
Object obj = getValue();
if (obj == null) {
return null;
}
return (String) typeConverter.convertIfNecessary(
((Employee) obj).getLastName(), String.class);
}
#Override
public void setAsText(String text) {
logger.info("convert string to employee object");
if (text == null || text.length() == 0) {
setValue(null);
return;
}
Long id = (Long) typeConverter.convertIfNecessary(text, Long.class);
if (id == null) {
setValue(null);
return;
}
setValue(employeeService.getEmployee(id));
}
#Override
public String getAsText() {
logger.info("convert employee object to string");
Object obj = getValue();
if (obj == null) {
return null;
}
return (String) typeConverter.convertIfNecessary(
((Employee) obj).getLastName(), String.class);
}
And die JSP Code:
<c:forEach items="${customerList}" var="customer">
<tr>
<td>${customer.id}</td>
...
<td>${customer.primaryConsultant}</td>
<td>${customer.secondaryConsultant}</td>
...
</tr>
</c:forEach>
But i get the unwanted result in Browser:
de.fischerlandmaschinen.crm.model.Employee#6018ebcc
in the field primaryConsultant and secondaryConsultant fields
What is the wrong. And i look for the document of registerCustomEditor. it saids, that it can for the nested path property too. What means the path property? The path in .jsp page or the property in domain object?
thanks
Ludwig
Override toString() method in Employee class and write what field values you want to display in the browser. That is the easy way and the only way I can think of right now. :)

Resources