Аз съм сравнително нов в Java и JavaFX и разработвам приложение JavaFX и използвам REST api в задача javafx.concurrent.ScheduledService, за да актуализирам TableView. Мога да получа отговора от моята услуга SpringBoot REST и мога да видя, че данните се задават в моделния обект, ObservableList, както и самия TableView, но таблицата все още остава празна.
Крайна точка на API на SpringBoot:
@RequestMapping(value = "/getAllActive", method = RequestMethod.GET)
public List<IssuedTicket> getAllActive () {
List<IssuedTicket> issuedTicketList = issuedTicketService.findAll();
return issuedTicketList;
}
JSON отговор от горната крайна точка:
[{"id":2,"ticketId":1230717013545,"dateArrived":"23-07-17","timeArrived":"01:35:45","deviceId":1},{"id":3,"ticketId":1230717013552,"dateArrived":"23-07-17","timeArrived":"01:35:52","deviceId":1},{"id":4,"ticketId":1230717013556,"dateArrived":"23-07-17","timeArrived":"01:35:56","deviceId":1}]
В моето JavaFX приложение:
HomeSceneController.java
package com.ronintech.bayTrans.ui.main;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXTextField;
import com.ronintech.bayTrans.model.ActiveTickets;
import com.ronintech.bayTrans.utils.RestErrorHandler;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.AnchorPane;
import javafx.util.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
public class HomeSceneController implements Initializable{
@FXML
private AnchorPane homeAnchorPane;
@FXML
private JFXTextField ticketTxt;
@FXML
private JFXButton scanTicketBtn;
@FXML
private TableView<ActiveTickets> activeTicketsTable;
@FXML
private TableColumn<ActiveTickets, Long > ticketIdCol;
@FXML
private TableColumn<ActiveTickets, String > dateArrivedCol;
@FXML
private TableColumn<ActiveTickets, String> timeArrivedCol;
private ObservableList<ActiveTickets> activeTicketsList;
private static final Logger LOGGER = LoggerFactory.getLogger(HomeSceneController.class);
private static final String ACTIVE_TICKETS_URL = "http://localhost:9090/api/ticket/getAllActive";
@Override
public void initialize(URL location, ResourceBundle resources) {
getActiveTickets.reset();
getActiveTickets.setPeriod(Duration.seconds(20));
getActiveTickets.start();
getActiveTickets.setOnSucceeded(event -> {
LOGGER.info("onSuccess");
List<ActiveTickets> activeList = getActiveTickets.getValue();
activeTicketsList = FXCollections.observableArrayList(activeList);
ticketIdCol.setCellValueFactory(new PropertyValueFactory<ActiveTickets, Long>("ticketId"));
dateArrivedCol.setCellValueFactory(new PropertyValueFactory<ActiveTickets, String>("dateArrived"));
timeArrivedCol.setCellValueFactory(new PropertyValueFactory<ActiveTickets, String>("timeArrived"));
activeTicketsTable.setItems(activeTicketsList);
LOGGER.info("Items in Table");
LOGGER.info(activeTicketsTable.getItems().toString());
});
getActiveTickets.setOnFailed(event -> {
LOGGER.error("service task FAILED");
});
}
@FXML
void openTicketModal(ActionEvent event) {
}
private ScheduledService<List<ActiveTickets>> getActiveTickets = new ScheduledService<List<ActiveTickets>>() {
@Override
protected Task<List<ActiveTickets>> createTask() {
return new Task<List<ActiveTickets>>() {
@Override
protected List<ActiveTickets> call() throws Exception {
LOGGER.info("Scheduled Service getActiveTickets STARTED");
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new RestErrorHandler());
List<ActiveTickets> response = restTemplate.getForObject(ACTIVE_TICKETS_URL, List.class);
LOGGER.info(response.toString);
return response;
}
};
}
};
}
Моят моделен обект: ActiveTickets.java
package com.ronintech.bayTrans.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.beans.property.SimpleStringProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class ActiveTickets {
private SimpleLongProperty id;
private SimpleLongProperty ticketId;
private SimpleStringProperty dateArrived;
private SimpleStringProperty timeArrived;
private SimpleIntegerProperty deviceId;
public ActiveTickets(long id,
long ticketId,
String dateArrived,
String timeArrived,
int deviceId) {
this.id = new SimpleLongProperty(id);
this.ticketId = new SimpleLongProperty(ticketId);
this.dateArrived = new SimpleStringProperty(dateArrived);
this.timeArrived = new SimpleStringProperty(timeArrived);
this.deviceId = new SimpleIntegerProperty(deviceId);
}
public long getId() {
return id.get();
}
public SimpleLongProperty idProperty() {
return id;
}
public long getTicketId() {
return ticketId.get();
}
public SimpleLongProperty ticketIdProperty() {
return ticketId;
}
public String getDateArrived() {
return dateArrived.get();
}
public SimpleStringProperty dateArrivedProperty() {
return dateArrived;
}
public String getTimeArrived() {
return timeArrived.get();
}
public SimpleStringProperty timeArrivedProperty() {
return timeArrived;
}
public int getDeviceId() {
return deviceId.get();
}
public SimpleIntegerProperty deviceIdProperty() {
return deviceId;
}
public void setId(long id) {
this.id.set(id);
}
public void setTicketId(long ticketId) {
this.ticketId.set(ticketId);
}
public void setDateArrived(String dateArrived) {
this.dateArrived.set(dateArrived);
}
public void setTimeArrived(String timeArrived) {
this.timeArrived.set(timeArrived);
}
public void setDeviceId(int deviceId) {
this.deviceId.set(deviceId);
}
@Override
public String toString() {
return "ActiveTickets{" +
"ticketId=" + ticketId +
", dateArrived=" + dateArrived +
", timeArrived=" + timeArrived +
'}';
}
}
Отговорът от извикването на RestTemplate е:
00:43:06.901 [Thread-9] INFO com.ronintech.bayTrans.ui.main.HomeSceneController - [{id=2, ticketId=1230717013545, dateArrived=23-07-17, timeArrived=01:35:45, deviceId=1}, {id=3, ticketId=1230717013552, dateArrived=23-07-17, timeArrived=01:35:52, deviceId=1}, {id=4, ticketId=1230717013556, dateArrived=23-07-17, timeArrived=01:35:56, deviceId=1}]
Дневникът след задаване на ObservableList на TableView:
activeTicketsTable.setItems(activeTicketsList);
00:43:07.159 [JavaFX Application Thread] INFO com.ronintech.bayTrans.ui.main.HomeSceneController - [{id=2, ticketId=1230717013545, dateArrived=23-07-17, timeArrived=01:35:45, deviceId=1}, {id=3, ticketId=1230717013552, dateArrived=23-07-17, timeArrived=01:35:52, deviceId=1}, {id=4, ticketId=1230717013556, dateArrived=23-07-17, timeArrived=01:35:56, deviceId=1}]
Регистрационният файл показва, че данните за TableView се задават в основната нишка на потребителския интерфейс, но таблицата все още е празна
Не съм сигурен дали и какво правя погрешно. Моля, помогнете, ако някой знае как да реши това.
Благодаря предварително.
РЕДАКТИРАНЕ
Моята структура на TableView в FXML:
<TableView fx:id="activeTicketsTable" prefHeight="800.0" prefWidth="800.0" tableMenuButtonVisible="true">
<columns>
<TableColumn fx:id="ticketIdCol" prefWidth="75.0" text="Ticket ID"/>
<TableColumn fx:id="dateArrivedCol" prefWidth="75.0" text="Date Arrived"/>
<TableColumn fx:id="timeArrivedCol" prefWidth="75.0" text="Time Arrived"/>
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/>
</columnResizePolicy>
</TableView>
АКТУАЛИЗАЦИЯ
Изглежда маршалингът не се извършва правилно.
Това е трасирането за отстраняване на грешки на ObservableList activeTicketsList:
Списъкът е зададен като ArrayList на LinkedHashMaps'
Докато когато правя ръчно ObservableList:
private final ObservableList<ActiveTickets> data = FXCollections.observableArrayList(
new ActiveTickets(1,1234,"date1","time1",1),
new ActiveTickets(2,5678,"date2","time2",2)
);
"данни" е правилно зададен като ArrayList от обекти от клас ActiveTickets
Как мога да се уверя, че JSON -> Маршалирането на обекти се извършва правилно в RestTemplate?
setCellValueFactory(...)
, не са правилните екземпляри на колоната на таблицата. - person James_D   schedule 24.07.2017ActiveTickets
клас почти сигурно също се нуждае от конструктор без аргументи. - person James_D   schedule 24.07.2017ParameterizedTypeReference
, или просто marshal за масив вместо списък. Трябва да направите и двете стъпки, за да работи това. - person Jai   schedule 25.07.2017