Search in sources :

Example 1 with DefaultDaemonThreadFactory

use of jgnash.util.DefaultDaemonThreadFactory in project jgnash by ccavanaugh.

the class BudgetTableController method initialize.

@FXML
private void initialize() {
    runningTotalsButton.selectedProperty().setValue(preferences.getBoolean(RUNNING_TOTALS, false));
    rateLimitExecutor = new ScheduledThreadPoolExecutor(1, new DefaultDaemonThreadFactory("Budget View Rate Limit Executor"), new ThreadPoolExecutor.DiscardPolicy());
    tableWidthChangeListener = (observable, oldValue, newValue) -> {
        if (newValue != null && !oldValue.equals(newValue)) {
            optimizeColumnWidths();
        }
    };
    handleFontHeightChange();
    yearSpinner.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(LocalDate.now().getYear() - YEAR_MARGIN, LocalDate.now().getYear() + YEAR_MARGIN, LocalDate.now().getYear(), 1));
    accountTreeView.getStylesheets().addAll(StyleClass.HIDE_HORIZONTAL_CSS, StyleClass.HIDE_VERTICAL_CSS);
    accountTreeView.setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY);
    accountTreeView.setShowRoot(false);
    accountTreeView.setEditable(true);
    accountTreeView.fixedCellSizeProperty().bind(rowHeight);
    accountSummaryTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
    accountSummaryTable.getStyleClass().addAll(StyleClass.HIDDEN_ROW_FOCUS);
    accountSummaryTable.getStylesheets().addAll(StyleClass.HIDE_HORIZONTAL_CSS, StyleClass.HIDE_VERTICAL_CSS);
    accountSummaryTable.setItems(expandedAccountList);
    accountSummaryTable.fixedCellSizeProperty().bind(rowHeight);
    accountSummaryTable.setSelectionModel(new NullTableViewSelectionModel<>(accountSummaryTable));
    accountTypeTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
    accountTypeTable.getStyleClass().addAll(StyleClass.HIDDEN_COLUMN_HEADER, StyleClass.HIDDEN_ROW_FOCUS);
    accountTypeTable.getStylesheets().addAll(StyleClass.HIDE_HORIZONTAL_CSS, StyleClass.HIDE_VERTICAL_CSS);
    accountTypeTable.setItems(accountGroupList);
    accountTypeTable.fixedCellSizeProperty().bind(rowHeight);
    accountTypeTable.prefHeightProperty().bind(rowHeight.multiply(Bindings.size(accountGroupList)).add(BORDER_MARGIN));
    accountTypeTable.setSelectionModel(new NullTableViewSelectionModel<>(accountTypeTable));
    // widths need to be bound to the tree view widths for drag/resizing to work
    accountTypeTable.minWidthProperty().bind(accountTreeView.minWidthProperty());
    accountTypeTable.prefWidthProperty().bind(accountTreeView.prefWidthProperty());
    accountGroupPeriodSummaryTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
    accountGroupPeriodSummaryTable.getStyleClass().addAll(StyleClass.HIDDEN_COLUMN_HEADER, StyleClass.HIDDEN_ROW_FOCUS);
    accountGroupPeriodSummaryTable.getStylesheets().addAll(StyleClass.HIDE_HORIZONTAL_CSS, StyleClass.HIDE_VERTICAL_CSS);
    accountGroupPeriodSummaryTable.setItems(accountGroupList);
    accountGroupPeriodSummaryTable.fixedCellSizeProperty().bind(rowHeight);
    accountGroupPeriodSummaryTable.prefHeightProperty().bind(rowHeight.multiply(Bindings.size(accountGroupList)).add(BORDER_MARGIN));
    accountGroupPeriodSummaryTable.setSelectionModel(new NullTableViewSelectionModel<>(accountGroupPeriodSummaryTable));
    buildAccountTreeTable();
    buildAccountTypeTable();
    buildAccountSummaryTable();
    buildAccountGroupSummaryTable();
    accountSummaryTable.maxWidthProperty().bind(minSummaryColumnWidth.multiply(3.0).add(BORDER_MARGIN));
    accountGroupPeriodSummaryTable.maxWidthProperty().bind(minSummaryColumnWidth.multiply(3.0).add(BORDER_MARGIN));
    accountSummaryTable.minWidthProperty().bind(minSummaryColumnWidth.multiply(3.0).add(BORDER_MARGIN));
    accountGroupPeriodSummaryTable.minWidthProperty().bind(minSummaryColumnWidth.multiply(3.0).add(BORDER_MARGIN));
    accountTreeView.expandedItemCountProperty().addListener((observable, oldValue, newValue) -> JavaFXUtils.runLater(this::updateExpandedAccountList));
    // Calling handleBudgetChange which works for most changes, but can trigger an exception.
    // handleBudgetUpdate rate limits and prevents an exception.
    final ChangeListener<Object> budgetChangeListener = (observable, oldValue, newValue) -> handleBudgetUpdate();
    budget.addListener(budgetChangeListener);
    yearSpinner.valueProperty().addListener(budgetChangeListener);
    runningTotalsButton.selectedProperty().addListener(budgetChangeListener);
    visibleColumnCount.addListener(budgetChangeListener);
    runningTotalsButton.selectedProperty().addListener((observable, oldValue, newValue) -> preferences.putBoolean(RUNNING_TOTALS, newValue));
    /* Setting the tables as un-managed effectively removes these tables from the GridPane.  The tables are
           redundant if showing the amounts as running balances. */
    accountSummaryTable.managedProperty().bind(runningTotalsButton.selectedProperty().not());
    accountGroupPeriodSummaryTable.managedProperty().bind(runningTotalsButton.selectedProperty().not());
    horizontalScrollBar.setMin(0);
    horizontalScrollBar.maxProperty().bind(periodCount.subtract(visibleColumnCount));
    horizontalScrollBar.setUnitIncrement(1);
    horizontalScrollBar.disableProperty().bind(periodCount.lessThanOrEqualTo(1));
    // shift the table right and left with the ScrollBar value
    horizontalScrollBar.valueProperty().addListener((observable, oldValue, newValue) -> {
        /* must be synchronized to prevent a race condition from multiple events and an out of
                     * bounds exception */
        synchronized (this) {
            /* don't try unless columns exist.  This can occur if the UI is not large enough to display
                         * a minimum of one period of information.
                         */
            if (periodTable.getColumns().size() > 0) {
                final int newIndex = (int) Math.round(newValue.doubleValue());
                if (newIndex > index) {
                    while (newIndex > index) {
                        handleShiftRight();
                    }
                } else if (newIndex < index) {
                    while (newIndex < index) {
                        handleShiftLeft();
                    }
                }
            }
        }
    });
    // listen for changes in the font scale and update.  Listener needs to be weak to prevent memory leaks
    fontScaleListener = (observable, oldValue, newValue) -> handleFontHeightChange();
    ThemeManager.fontScaleProperty().addListener(new WeakChangeListener<>(fontScaleListener));
    // cursor handler
    accountTreeView.setOnMouseMoved(this::handleMouseMove);
    // drag handler
    accountTreeView.setOnMouseDragged(this::handleDividerDrag);
    // drag handler
    accountTreeView.setOnMousePressed(this::handleMouseClicked);
    // cursor handler
    accountTypeTable.setOnMouseMoved(this::handleMouseMove);
    // drag handler
    accountTypeTable.setOnMouseDragged(this::handleDividerDrag);
    // drag handler
    accountTypeTable.setOnMousePressed(this::handleMouseClicked);
    JavaFXUtils.runLater(() -> accountTreeView.setPrefWidth(preferences.getDouble(ACCOUNT_COLUMN_WIDTH, INITIAL_WIDTH * 2)));
}
Also used : Period(jgnash.time.Period) Pos(javafx.geometry.Pos) Engine(jgnash.engine.Engine) TODAY_BOLD_NEGATIVE_LABEL_ID(jgnash.uifx.skin.StyleClass.TODAY_BOLD_NEGATIVE_LABEL_ID) BigDecimal(java.math.BigDecimal) Budget(jgnash.engine.budget.Budget) MessageProperty(jgnash.engine.message.MessageProperty) DefaultDaemonThreadFactory(jgnash.util.DefaultDaemonThreadFactory) SimpleIntegerProperty(javafx.beans.property.SimpleIntegerProperty) TreeTableCell(javafx.scene.control.TreeTableCell) Point2D(javafx.geometry.Point2D) BudgetPeriodDescriptor(jgnash.engine.budget.BudgetPeriodDescriptor) TableView(javafx.scene.control.TableView) NullTableViewSelectionModel(jgnash.uifx.control.NullTableViewSelectionModel) ReadWriteLock(java.util.concurrent.locks.ReadWriteLock) MessageListener(jgnash.engine.message.MessageListener) HBox(javafx.scene.layout.HBox) NotNull(jgnash.util.NotNull) NORMAL_CELL_ID(jgnash.uifx.skin.StyleClass.NORMAL_CELL_ID) ScheduledThreadPoolExecutor(java.util.concurrent.ScheduledThreadPoolExecutor) Spinner(javafx.scene.control.Spinner) TODAY_BOLD_LABEL_ID(jgnash.uifx.skin.StyleClass.TODAY_BOLD_LABEL_ID) Logger(java.util.logging.Logger) Collectors(java.util.stream.Collectors) JavaFXUtils(jgnash.uifx.util.JavaFXUtils) AccountGroup(jgnash.engine.AccountGroup) Objects(java.util.Objects) Platform(javafx.application.Platform) FXML(javafx.fxml.FXML) BudgetGoal(jgnash.engine.budget.BudgetGoal) TODAY_NORMAL_CELL_ID(jgnash.uifx.skin.StyleClass.TODAY_NORMAL_CELL_ID) List(java.util.List) LocalDate(java.time.LocalDate) Optional(java.util.Optional) SimpleDoubleProperty(javafx.beans.property.SimpleDoubleProperty) BOLD_LABEL_ID(jgnash.uifx.skin.StyleClass.BOLD_LABEL_ID) ObservableList(javafx.collections.ObservableList) NumericFormats(jgnash.text.NumericFormats) Message(jgnash.engine.message.Message) WeakChangeListener(javafx.beans.value.WeakChangeListener) ThreadPoolExecutor(java.util.concurrent.ThreadPoolExecutor) BudgetPeriodResults(jgnash.engine.budget.BudgetPeriodResults) SimpleStringProperty(javafx.beans.property.SimpleStringProperty) TreeItem(javafx.scene.control.TreeItem) MouseEvent(javafx.scene.input.MouseEvent) EngineFactory(jgnash.engine.EngineFactory) FXCollections(javafx.collections.FXCollections) DoubleProperty(javafx.beans.property.DoubleProperty) ReentrantReadWriteLock(java.util.concurrent.locks.ReentrantReadWriteLock) Bindings(javafx.beans.binding.Bindings) IntegerProperty(javafx.beans.property.IntegerProperty) NumberFormat(java.text.NumberFormat) ArrayList(java.util.ArrayList) Level(java.util.logging.Level) TableColumn(javafx.scene.control.TableColumn) TableCell(javafx.scene.control.TableCell) TreeTableView(javafx.scene.control.TreeTableView) ResourceBundle(java.util.ResourceBundle) ThemeManager(jgnash.uifx.skin.ThemeManager) GridPane(javafx.scene.layout.GridPane) BOLD_NEGATIVE_LABEL_ID(jgnash.uifx.skin.StyleClass.BOLD_NEGATIVE_LABEL_ID) Label(javafx.scene.control.Label) Comparators(jgnash.engine.Comparators) FXMLUtils(jgnash.uifx.util.FXMLUtils) BudgetResultsModel(jgnash.engine.budget.BudgetResultsModel) CheckBox(javafx.scene.control.CheckBox) Preferences(java.util.prefs.Preferences) TimeUnit(java.util.concurrent.TimeUnit) Cursor(javafx.scene.Cursor) TreeTableColumn(javafx.scene.control.TreeTableColumn) StageUtils(jgnash.uifx.util.StageUtils) Stage(javafx.stage.Stage) SimpleObjectProperty(javafx.beans.property.SimpleObjectProperty) StyleClass(jgnash.uifx.skin.StyleClass) SpinnerValueFactory(javafx.scene.control.SpinnerValueFactory) Account(jgnash.engine.Account) TODAY_NORMAL_NEGATIVE_CELL_ID(jgnash.uifx.skin.StyleClass.TODAY_NORMAL_NEGATIVE_CELL_ID) ChangeListener(javafx.beans.value.ChangeListener) NORMAL_NEGATIVE_CELL_ID(jgnash.uifx.skin.StyleClass.NORMAL_NEGATIVE_CELL_ID) ScrollBar(javafx.scene.control.ScrollBar) ScheduledThreadPoolExecutor(java.util.concurrent.ScheduledThreadPoolExecutor) DefaultDaemonThreadFactory(jgnash.util.DefaultDaemonThreadFactory) SpinnerValueFactory(javafx.scene.control.SpinnerValueFactory) FXML(javafx.fxml.FXML)

Example 2 with DefaultDaemonThreadFactory

use of jgnash.util.DefaultDaemonThreadFactory in project jgnash by ccavanaugh.

the class JpaNetworkServer method run.

/**
 * Starts the server and blocks until it is stopped
 *
 * @param dataStoreType datastore type
 * @param fileName      database file name
 * @param port          port
 * @param password      password*
 * @throws EngineException thrown if engine or buss cannot be created
 */
private synchronized void run(final DataStoreType dataStoreType, final String fileName, final int port, final char[] password) throws EngineException {
    final DistributedLockServer distributedLockServer = new DistributedLockServer(port + LOCK_SERVER_INCREMENT);
    final boolean lockServerStarted = distributedLockServer.startServer(password);
    final AttachmentTransferServer attachmentTransferServer = new AttachmentTransferServer(port + TRANSFER_SERVER_INCREMENT, AttachmentUtils.getAttachmentDirectory(Paths.get(fileName)));
    final boolean attachmentServerStarted = attachmentTransferServer.startServer(password);
    if (attachmentServerStarted && lockServerStarted) {
        final Engine engine = createEngine(dataStoreType, fileName, port, password);
        if (engine != null) {
            // Start the message bus and pass the file name so it can be reported to the client
            final MessageBusServer messageBusServer = new MessageBusServer(port + MESSAGE_SERVER_INCREMENT);
            // don't continue if the server is not started successfully
            if (messageBusServer.startServer(dataStoreType, fileName, password)) {
                // Start the backup thread that ensures an XML backup is created at set intervals
                final ScheduledExecutorService backupExecutor = Executors.newSingleThreadScheduledExecutor(new DefaultDaemonThreadFactory("JPA Network Server Executor"));
                // run commit every backup period after startup
                backupExecutor.scheduleWithFixedDelay(() -> {
                    if (dirty) {
                        exportXML(engine, fileName);
                        EngineFactory.removeOldCompressedXML(fileName, engine.getRetainedBackupLimit());
                        dirty = false;
                    }
                }, BACKUP_PERIOD, BACKUP_PERIOD, TimeUnit.HOURS);
                final LocalServerListener listener = event -> {
                    // look for a remote request to stop the server
                    if (event.startsWith(STOP_SERVER_MESSAGE)) {
                        logger.info("Remote shutdown request was received");
                        stopServer();
                    }
                    dirty = true;
                };
                messageBusServer.addLocalListener(listener);
                // if a callback has been registered, call it
                if (runningCallback != null) {
                    runningCallback.run();
                }
                // wait here forever
                try {
                    while (stopLatch.getCount() != 0) {
                        // check for condition, handle a spurious wake up
                        // wait forever from stopServer()
                        stopLatch.await();
                    }
                } catch (final InterruptedException ex) {
                    logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
                    Thread.currentThread().interrupt();
                }
                messageBusServer.removeLocalListener(listener);
                backupExecutor.shutdown();
                exportXML(engine, fileName);
                messageBusServer.stopServer();
                EngineFactory.closeEngine(SERVER_ENGINE);
                EngineFactory.removeOldCompressedXML(fileName, engine.getRetainedBackupLimit());
                distributedLockManager.disconnectFromServer();
                distributedAttachmentManager.disconnectFromServer();
                distributedLockServer.stopServer();
                attachmentTransferServer.stopServer();
                em.close();
                factory.close();
            } else {
                throw new EngineException("Failed to start the Message Bus");
            }
        } else {
            throw new EngineException("Failed to create the engine");
        }
    } else {
        if (lockServerStarted) {
            distributedLockServer.stopServer();
        }
        if (attachmentServerStarted) {
            attachmentTransferServer.stopServer();
        }
    }
}
Also used : Engine(jgnash.engine.Engine) Persistence(javax.persistence.Persistence) EngineFactory(jgnash.engine.EngineFactory) AttachmentTransferServer(jgnash.engine.attachment.AttachmentTransferServer) LocalServerListener(jgnash.engine.message.LocalServerListener) ArrayList(java.util.ArrayList) Level(java.util.logging.Level) SQLException(java.sql.SQLException) DefaultDaemonThreadFactory(jgnash.util.DefaultDaemonThreadFactory) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) MessageBusServer(jgnash.engine.message.MessageBusServer) Path(java.nio.file.Path) Properties(java.util.Properties) AttachmentUtils(jgnash.engine.AttachmentUtils) DistributedAttachmentManager(jgnash.engine.attachment.DistributedAttachmentManager) Files(java.nio.file.Files) FileMagic(jgnash.util.FileMagic) IOException(java.io.IOException) EntityManager(javax.persistence.EntityManager) DistributedLockManager(jgnash.engine.concurrent.DistributedLockManager) Logger(java.util.logging.Logger) Executors(java.util.concurrent.Executors) EngineException(jgnash.engine.EngineException) StoredObject(jgnash.engine.StoredObject) TimeUnit(java.util.concurrent.TimeUnit) LogUtil(jgnash.util.LogUtil) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) Paths(java.nio.file.Paths) EntityManagerFactory(javax.persistence.EntityManagerFactory) FileUtils(jgnash.util.FileUtils) DistributedLockServer(jgnash.engine.concurrent.DistributedLockServer) DataStoreType(jgnash.engine.DataStoreType) MessageBusServer(jgnash.engine.message.MessageBusServer) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) LocalServerListener(jgnash.engine.message.LocalServerListener) DistributedLockServer(jgnash.engine.concurrent.DistributedLockServer) EngineException(jgnash.engine.EngineException) DefaultDaemonThreadFactory(jgnash.util.DefaultDaemonThreadFactory) AttachmentTransferServer(jgnash.engine.attachment.AttachmentTransferServer) Engine(jgnash.engine.Engine)

Aggregations

ArrayList (java.util.ArrayList)2 List (java.util.List)2 TimeUnit (java.util.concurrent.TimeUnit)2 Level (java.util.logging.Level)2 Logger (java.util.logging.Logger)2 IOException (java.io.IOException)1 BigDecimal (java.math.BigDecimal)1 Files (java.nio.file.Files)1 Path (java.nio.file.Path)1 Paths (java.nio.file.Paths)1 SQLException (java.sql.SQLException)1 NumberFormat (java.text.NumberFormat)1 LocalDate (java.time.LocalDate)1 Objects (java.util.Objects)1 Optional (java.util.Optional)1 Properties (java.util.Properties)1 ResourceBundle (java.util.ResourceBundle)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 Executors (java.util.concurrent.Executors)1 ScheduledExecutorService (java.util.concurrent.ScheduledExecutorService)1