Running 2 java classes simultaneously from command prompt and eclipse - java

I'm currently working on a small project that requires a server and a small user interface, which I built with JavaFX. I have to start the user interface via the command prompt using mvn javafx:run (as you can see, I use maven to manage my dependencies). I start the server normally via Eclipse. This also works so far and both programs start up as desired. It just seems like they can't communicate with each other. The commands from the user interface do not arrive in the "actual" program. It seems like there are two separate versions running and not a unified one.
Here is my GUI main-class i start using mvn javafx:run:
public class FX extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
try {
Parent root = FXMLLoader.load(getClass().getResource("../main/Scene.fxml"));
Scene scene = new Scene(root);
//scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
And heres the corresponding controller:
public class Controller {
#FXML
private TextField senderField;
#FXML
private TextField receiverField;
#FXML
private TextField amountField;
#FXML
private TextField tfbpField;
#FXML
private TextField tflField;
#FXML
private TextField nonceField;
#FXML
private Button submitButton;
#FXML
void submitPressed(ActionEvent event) {
System.out.println("Submit Pressed");
byte[] sender = SHA3Helper.hexToDigest(senderField.getText());
byte[] receiver = SHA3Helper.hexToDigest(receiverField.getText());
double amount = Double.parseDouble(amountField.getText());
double tfbp = Double.parseDouble(tfbpField.getText());
double tfl = Double.parseDouble(tflField.getText());
Transaction transaction = new Transaction(sender, receiver, amount, 0, tfbp, tfl);
System.out.println(transaction.getAmount());
DependencyManager.getPendingTransactions().addPendingTransaction(transaction);
for(int i = 0; i<100 ; i++) {
System.out.println("Receiving test");
}
}
}
As you can see i implemented a simple for-loop to check whether "Receiving test" will also be displayed on eclipse or not - with the rusult that i can see it only in my cmd, not in Eclipse.
And here is the Tomcat that starts the actual program. Of course I start this one first.
public class Start
{
public static void main( String args[] )
{
try
{
Tomcat tomcat = new Tomcat( );
String webappDirectory = new File( "src/main/webapp" ).getAbsolutePath( );
tomcat.setPort( 8080 );
Context context = tomcat.addWebapp( "", webappDirectory );
Tomcat.addServlet( context, "blockchain", new ServletContainer( new Application( ) ) );
context.addServletMappingDecoded( "/blockchain/api/*", "blockchain" );
tomcat.start( );
tomcat.getServer( ).await( );
}
catch ( Exception e )
{
e.printStackTrace( );
}
}
}
Through dubugging I quickly found out that the problem lies in the communication between the two programs. Commands from the UserInterface do not reach the actual program.

Related

java.awt.Desktop.isDesktopSupported return false in javafx application

I have this javafx controller method trying to open up a local html file that's generated by the application. The function is running in another thread.
My main class that starts the application, using fxmlloader:
#SpringBootApplication
public class DemoAppiumProjectApplication extends Application
{
public static ConfigurableApplicationContext applicationContext;
public static void main(String[] args)
{
applicationContext = SpringApplication.run(DemoAppiumProjectApplication.class, args);
Application.launch(DemoAppiumProjectApplication.class, args);
}
#Override
public void start(Stage stage)
throws Exception
{
stage.setTitle("JS SDK Demo Test Suite");
stage.setScene(new Scene(createRoot()));
stage.show();
}
private Parent createRoot()
throws IOException
{
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(DemoAppiumProjectApplication.class.getResource("/setup.fxml"));
fxmlLoader.setControllerFactory(applicationContext::getBean);
return fxmlLoader.load();
}
}
My controller class:
#Override
public void initialize(URL url, ResourceBundle resourceBundle)
{
Task<String> task = new Task<String>()
{
#Override
protected String call()
throws Exception
{
showFinalDialog();
return null;
}
};
new Thread(task).start();
}
public void showFinalDialog()
{
Platform.runLater(() -> {
String text = "Test is complete! Click to view test report.";
Alert alert = new Alert(Alert.AlertType.INFORMATION, text, ButtonType.OK);
alert.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
Optional<ButtonType> buttonType = alert.showAndWait();
if (!buttonType.isPresent())
{
Platform.exit();
}
else if (buttonType.get() == ButtonType.OK)
{
if (Desktop.isDesktopSupported())
{
try
{
Desktop.getDesktop()
.open(new File(System.getProperty("user.dir") + "/test-output/ExtentReport.html"));
}
catch (IOException e)
{
createAlertWindow(e.getMessage());
}
}
Platform.exit();
}
});
}
Now the only question is the condition Desktop.isDesktopSupported return false here. I wrote another main function in another project to test again, it returns true.
I guess that means Desktop is supported on my OS (windows 10), but not supported in my javafx application?
So what am I missing here?
And perhaps there's another recommanded way to open up this html file as well? Any ideas would help! Thanks!
Why use the Desktop to open a local html file when you are using javafx already.
Here is an example.
public class HelpWindow extends Application{
#Override
public void start(Stage primaryStage) throws Exception{
FlowPane root = new FlowPane();
primaryStage.setTitle("Help Window");
WebView view = new WebView();
WebEngine engine = view.getEngine();
engine.load( HelpWindow.class.getResource("help.html").toString());
root.getChildren().add(view);
Scene scene = new Scene(root, 790, 675);
primaryStage.setScene(scene);
primaryStage.show();
System.out.println(Desktop.isDesktopSupported());
}
}
That will show the help.html file, that I have included as a resource. From the looks of it, you might be generating your .html file so you would have to get the file a different way.
<html>
<body>
<p> Here is some text</p>
original question
</body>
</html>
I've also included printing out the Desktop.isDesktopSupported() since that returns true for me.
I suspect one issue you are having is that Desktop.getDesktop().open() is non-blocking, so your application just quits before your desktop can actually open the webpage.

NullPointerException while modyfing elements on second Pane JavaFX

I have a problem with nullPointer while i'm trying to modify any element from second Panel in my application.
How my application look like: I have 2 Panel, first to loggin and second one with Main Application.
Steps in my application:
Create and show 1 panel
Provide passwords and loggin to database
a/ Success - open new panel and hide this one
b/ show error message
Now i'm trying to modify any element from panel 2 but i cant
Caused by: java.lang.NullPointerException
at sample.ControllerLoginMenu.openScene(ControllerLoginMenu.java:114)
at sample.ControllerLoginMenu.login(ControllerLoginMenu.java:41)
... 58 more
Here is my code
public class ControllerLoginMenu {
#FXML private Label statusMessage; // second Panel
#FXML private Circle statusCircle; // second Panel
#FXML private Label errorMessageConnection; // First Panel
#FXML private Label errorMessagePassword; // First Panel
#FXML private TextField loginField; //First Panel
#FXML private PasswordField passwordField; //First panel
private String username ;
private String password ;
private final String url = "jdbc:oracle:thin:#google.com:6666:NotExist";
private Stage primaryStage = new Stage();
private Connection con;
private Statement statement;
#FXML private void login(ActionEvent event) throws IOException {
checkConnection();
openScene(event);
// From there is the problem'
errorMessageConnection.setVisible(true); -- no Error
statusCircle.setFill(Color.RED); -- Error
}
private void openScene(ActionEvent event) throws IOException {
Parent root = FXMLLoader.load(getClass().getResource("MainMenu.fxml"));
((Node) event.getSource()).getScene().getWindow().hide();
primaryStage.setTitle("Masterdata loading application");
primaryStage.setScene(new Scene(root, 640, 480));
primaryStage.show();
}
private boolean checkConnection() {
boolean result = false;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
return result;
}
try {
con = DriverManager.getConnection(url, username, password);
statement = con.createStatement();
String sql = "SELECT SYSDATE FROM DUAL";
result = statement.execute(sql);
}
catch (SQLException e)
{
passwordField.setText("");
e.printStackTrace();
return result;
}
return result;
}
private boolean getPasswords()
{
username = loginField.getText();
password = passwordField.getText();
if(username.isEmpty() || password.isEmpty())
return false;
else
return true;
}
#Override // Main Class
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("LoginMenu.fxml"));
primaryStage.setTitle("Masterdata loading application");
primaryStage.setScene(new Scene(root, 540, 380));
primaryStage.show();
}
I other posts i have found that this should solve problem, but it didnt.
Platform.runLater(() ->{
statusCircle.setFill(Color.GREEN);});
You load two fxml files, so you have (at least) two controllers. The fields with matching fx:ids in the first fxml file will be initialized in the first controller, and the fields with matching fx:ids in the second fxml file will be initialized in the second controller. Since errorMessageConnection and statusCircle are defined in different FXML files, it is impossible for them both to be non-null in the same controller. Consequently, your login method is guaranteed to throw a null pointer exception.
(You actually appear to be getting a null pointer exception in openScene, but there isn't enough information in your question to diagnose that. It is likely related.)
If you use the same controller class for all your different fxml files, it becomes extremely difficult to keep track of what is initialized, and what remains null, in each controller. You should use a different controller class for each FXML file. If you need to pass data to a controller, use the techniques outlined in this answer.

JavaFX application Window freezes when trying to show the backgroud process status

I'm working on an application feature to show the progress status in TextArea. And I'm using observer pattern to implement that. But when I try to append the status information to the TextArea, the Window freezes. How to solve that problem?
The freeze window like this :
When doSomething() is done. The freezes window back to normal. Like this:
Here are my codes
start(Stage stage)
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("view/progressStatus.fxml"));
Parent root = loader.load();
statusStage = new Stage();
statusScene = new Scene(root);
statusStage.setScene(statusScene);
progressStatusController = loader.getController();
statusStage.show();
MyFiles myFiles = new MyFiles();
myFiles.addObserver(progressStatusController);
newMyFiles.doSomething();
public class ProgressStatusController implements Initializable, Observer {
#FXML private ProgressBar progressBar;
#FXML private TextArea textArea;
private String[] message;
#Override
public void initialize(URL location, ResourceBundle resources) {
}
#Override
public void update(Observable o, Object arg) {
System.out.println(arg);
textArea.textProperty().set(textArea.getText().concat("\n").concat((String)arg));
textArea.positionCaret(textArea.getText().length());
}
}
doSomething is a long-running task and therefore should not be run on the JavaFX application thread. However the start method is run on this thread.
You need to run doSomething on a different thread to avoid blocking the application thread. Updates to the UI should be done on the application thread; therefore you should use Platform.runLater to execute the updates:
...
MyFiles myFiles = new MyFiles();
myFiles.addObserver(progressStatusController);
new Thread(newMyFiles::doSomething).start();
#Override
public void update(Observable o, Object arg) {
System.out.println(arg);
Platform.runLater(() -> {
textArea.setText(textArea.getText() + "\n" + arg);
textArea.positionCaret(textArea.getText().length());
});
}
🔗In addition to Fabian's answer i recommend you to use JavaFX Service.Service is running into a different than JavaFX Thread and you can do what you want there but be careful modifying JavaFX Nodes that are into the SceneGraph is not allowed so you have to use:
Platform.runLater(() -> {
//your code...
});
Typical example of Service for reading the files into a folder using
Files.walk(..) method + Streams:
/**
* With this Service you can count the files of a folder
* it is a minimalistic example of the power of Services
*
*/
public class ServiceExample extends Service<Void> {
/**
* Constructor
*/
public InputService() {
setOnSucceeded(s ->{
//code
});
setOnCancelled(c ->{
//code
});
setOnFailed(c ->{
//code
});
}
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
#Override
protected Void call() throws Exception {
countFiles(new File("the path of the folder");
return null;
}
/**
* Count files in a directory (including files in all sub
* directories)
*
* #param directory
* the directory to start in
* #return the total number of files
*/
private int countFiles(File dir) {
if (dir.exists())
try (Stream<Path> paths = Files.walk(Paths.get(dir.getPath()))) {
return (int) paths.filter(s -> { //where s is a File or Folder
// System.out.println("Counting..." +
// s.toString())
// cancelled?
if (isCancelled())
paths.close();
else
System.out.println(s);
return false;
}).count();
} catch (IOException ex) {
Main.logger.log(Level.WARNING, "", ex);
}
return 0;
}
};
}
}

Can't get second JavaFX stage to show?

I am writing a RDP client and I want to show a new stage while keeping the old one running. Unfortunately the second stage isn't coming up at all.
This is my stage:
public final class Remote extends Stage {
private static final URL FXML = Remote.class
.getResource("/conspire/remote.fxml");
private static final Image ICON = new Image(Remote.class.getResource(
"icon.png").toExternalForm());
public static Remote create(String title) throws IOException {
return new Remote(title);
}
private Remote(String title) throws IOException {
Parent parent = FXMLLoader.load(FXML);
Scene scene = new Scene(parent);
setScene(scene);
getIcons().add(ICON);
setTitle(title);
setResizable(true);
centerOnScreen();
show();
}
}
And this is how I run it:
Remote.create(host + " (" + partner.getValue() + ") - Conspire");
The create method won't even invoke. If I add a sysout in there it won't print.
In order to create a new stage you must run it from within the JavaFX thread. You can do this easily with JavaFX's Platform tool. In your case:
Platform.runLater(() -> {
Remote.create(host + " (" + partner.getValue() + ") - Conspire");
});

How to create background service in JavaFX

I've been away from Java for some years and have started to pick it up again a couple of days ago. I'll need to create a GUI using FXML and to get some practice I'm implementing a little chat application as an exercise.
I want to create a background thread which listens on a port and sends received messages to a textArea. By what I've read, this is best done by using the 'javafx.concurrent' package.
So I came up with the following:
import javafx.concurrent.Service;
import javafx.concurrent.Task;
public class ListenOnPort extends Service<Void> {
#Override protected Task<Void> createTask() {
return new Task<Void>() {
#Override protected Void call() throws Exception {
updateMessage("Bla!");
/*
int max = 50;
for (int i = 1; i <= max; i++) {
updateProgress(i, max);
updateMessage(String.valueOf(i));
Thread.sleep(50);
}
*/
return null;
} //call()
};
} //createTask()
}// ListenOnPort
The [shortened] controller is:
public class FXMLDocumentController {
#FXML private Label status;
#FXML private ProgressBar progressBar;
ListenOnPort listenService;
#FXML void startListening(ActionEvent event) {
localPort = Integer.parseInt(listenPort.getText());
status.setText("Attempting to open local port " +localPort +" for listening.");
listenService.start();
}
#FXML void initialize() {
// assertions
listenService = new ListenOnPort();
/*>>>*/ progressBar.progressProperty().bind(listenService.progressProperty());
status.textProperty().bind(listenService.messageProperty());
}
}
Which results in:
java.lang.NullPointerException
at p2pchat.FXMLDocumentController.initialize(FXMLDocumentController.java:130)
Line 130 is the second to last line of code, marked with '/>>>/'.
Why do I get a nullPointerException? What am i doing wrong?
First, make sure you created a ProgressBar element in the .fxml file with an fx:id of progressBar.
Then in your IDE click in your project folder and press F5, it will refresh the .fxml and it will see the most updated version. Otherwise the IDE will not see the recent modifications you've made to your .fxml file and will cause the NullPointerException.

Categories

Resources