I need to wait for a Server program to send data to the Client program using a socket so I must wait for it using a while loop. However the Client program is a JavaFX Application and if used in a while loop it will freeze up and crash so I put the while loop in a new Thread. However the body of this while loop needs to update the JavaFX UI which cannot be done as it causes "Not on FX application thread;" Exception so I cannot create a new thread for it.
This is my code:
import static util.Constants.PORT;
import static util.Constants.SERVER_NAME;
public class Client extends Application {
private static View view;
public static Scanner in;
public static PrintWriter out;
private static boolean appRunning = true;
public static void main(String[] args) {
try {
Socket socket = new Socket(SERVER_NAME, PORT);
in = new Scanner(socket.getInputStream());
out = new PrintWriter(socket.getOutputStream(), true);
launch(args);
} catch (IOException e) {
System.out.println("Could not establish connection to server. Program terminating..");
System.exit(1);
}
}
#Override
public void start(Stage window) throws Exception {
// This is a JavaFX BorderPane that adds itself to window:
view = new View(window);
// ServerListener
new Thread(() -> {
try {
while (appRunning) {
// will through exception. needs to run on Application thread:
parseServerMessage(Client.in.nextLine());
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}).start();
}
private static String[] parseServerMessage(String message0 {
// update the JavaFX UI
}
}
and if I used this code below in the start method without the thread, the JavaFX app will freeze:
#Override
public void start(Stage window) throws Exception {
// This is a JavaFX BorderPane that adds itself to window:
view = new View(window);
// causes JavaFX to freeze:
while (appRunning) {
parseServerMessage(Client.in.nextLine());
}
}
Also putting the thread to sleep doesn't help.
How can I get around this problem? Thank you!
EDIT Solution:
Thanks to the solution, I edited my code and now it works perfectly. Here is the edited solution:
new Thread(() -> {
while (true) {
String serverMessage = Client.in.nextLine();
Platform.runLater(() -> {
parseServerMessage(serverMessage);
});
}
}).start();
You can take a look at Platform::runLater. From the JavaDoc:
Run the specified Runnable on the JavaFX Application Thread at some unspecified time in the future. This method, which may be called from any thread, will post the Runnable to an event queue and then return immediately to the caller.
Related
I made an email client which has two main threads: the first one is the one with the GUI and the second one is that which get executed in the background in a loop and that update the GUI if their new emails. I would like to synchronize these this thread and execute them one at a time. On the server I manage them on this way:
public void initModel() throws IOException {
contenutoTextArea.append("Waiting for connections\n");
textarea.setText(contenutoTextArea.toString());
s = new ServerSocket(5000);
new Thread() {
#Override
public void run() {
while (true) {
try {
new ThreadedEchoHandler(s);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}.start();
}
class ThreadedEchoHandler implements Runnable {
private Socket incoming;
private String nomeAccount = "";
ThreadedEchoHandler(ServerSocket serv) throws IOException {
incoming = serv.accept();
new Thread(this).start();
}
public void run() {
....
}
Does the JVM execute them on in time?
everybody.
Hope you can help me with this one:
I have two threads, which are tasked with handling connections from a client.
This is my code
ServerSocket loginSocket = new ServerSocket(8000);
ServerSocket fileSocket = new ServerSocket(7000);
while (running) {
new LoginThread(loginSocket.accept(),loginInormation).start();
new LoaderThread(fileSocket.accept()).start();
}
When I try to connect to the loginSocket two times, the server will block and stop working, blocking the client, but this doesn't happen if I delete this:
new LoginThread(loginSocket.accept(),loginInormation).start();
I'm not getting any error messages, so why is this happening and how can I fix this?
The accept() method is a blocking method, which means that your program won't continue until a connection is made with loginSocket().
When you're creating your LoginThread, the program waits a connection to set the first parameter of your object, and it will not continue the execution until a connection is made.
The line new LoginThread(loginSocket.accept(),loginInormation).start(); contains the method call loginSocket.accept(), which will be called before this thread is created. This method call will block until a client logs in. (In addition, the second thread will be blocked by fileSocket.accept()).
As for a solution, I would move the accept() calls to inside each of the Threads. You will need to pass the sockets to the threads for them to do this.
Start fileSocket and login socket in different threads
package com.ca.training.task.app;
import java.io.IOException;
import java.net.ServerSocket;
public class App {
public void execute() {
LoginRunnable loginRunnable = new LoginRunnable();
loginRunnable.setLoginInformation(new Object());//Login information
FileRunnable fileRunnable = new FileRunnable();//Data for loaded runnable.
fileRunnable.setParams(new Object());
startLoginThread(loginRunnable);
startFileThread(fileRunnable);
}
private static void startLoginThread(LoginRunnable loginRunnable) {
Thread loginThread = new Thread(loginRunnable);
loginThread.start();
}
private static void startFileThread(FileRunnable fileRunnable) {
Thread loadedThread = new Thread(fileRunnable);
loadedThread.start();
}
class LoginRunnable implements Runnable {
private Object loginInformation;
#Override
public void run() {
try {
ServerSocket loginSocket = new ServerSocket(8000);
loginSocket.accept();
} catch (IOException e) {
e.printStackTrace();
}
}
public Object getLoginInformation() {
return loginInformation;
}
public void setLoginInformation(Object loginInformation) {
this.loginInformation = loginInformation;
}
}
class FileRunnable implements Runnable {
private Object params;
#Override
public void run() {
try {
ServerSocket fileSocket = new ServerSocket(7000);
} catch (IOException e) {
e.printStackTrace();
}
}
public Object getParams() {
return params;
}
public void setParams(Object params) {
this.params = params;
}
}
}
am developing a java application in which I am using swings to develop GUI screens. i am supposed to run some application files. which I did by connecting to command prompt by using Runtime.exec() method. if my application failes to execute properly then a GUI frame will come up asking weather to run that file again or to skip.
here my problem is when I say run that file again the control should return to the point where the frame is called using ui.setvisible(true);
if not the swing frame what can i use to make my code work
public static boolean runFormat(String format,String buildNumber) throws Exception
{
try{
ProcessExecutor process = new ProcessExecutor();
process.executeCommand(format+"\\Scripts"+File.separator+"Step1.bat"+""+"02_00"+" "+format);
process.waitForCompletion();
File file = new File(format+File.separator+"Results1.log");
BufferedReader read = new BufferedReader (new FileReader(file));
String line;
while((line=read.readLine())!=null)
{
if(line.contains("Successful exit."))
{
return true;
}
}
return false;
}
catch(Exception e)
{
System.out.println("EXCEPTION OCCURED..................");
System.out.println("JTag has failed for "+format);
e.printStackTrace();
}
return true;
}
void run(Set<String> formats)
{
try
{
for(String ar : formats)
{
boolean b =runFormat(ar,"001");
if(b==false)
{
ExampleUi ui = new ExampleUi();
ui.setVisible(true);
}
}
}
catch(Exception e)
{
}
}
Thanks in advance
The short answer is no.
The long answer would involve using a SwingWorker and making the decisions about what to do within it's done method
Take a look at Worker Threads and SwingWorker for more details...
public class ProcessWorker extends SwingWorker<Boolean, Void> {
public Boolean doInBackground() throws Exception {
ProcessBuilder pb = new ProcessBuilder(...);
Process p = pb.start();
// Read the input stream in separate thread...
return p.waitFor() == 0;
}
public void done() {
try {
boolean okay = get();
if (!okay) {
// Re-run....?
}
} catch (Exception exp) {
// Show error message, maybe in a JOptionPane
}
}
}
sorry about the title I had trouble finding out what I should call it.
So here is the deal! I am currently creating a chat application where I use a Gui using I've created in JavaFx (a Gui that has some graphics on it but I think that is kinda irrelevant) what I have done so far is that I've setup a small server that each client connect to through the program! The main idea is that the clients sends a message to the server and the server will then send it to the other client (which is the whole idea in a chat program) one important note is that I am not using Threads and do not wish to yet!
So to get down to the real problem:
I've created a client class that contains methods to connect, receive and send. my Connect class works fine with my Gui and I am able to connect to the server without any problems!
The problem begins when I try to send to or receive from my server. No matter how many exceptions I throw or how many try Catch I do I get a nullpointer error! I've looked at the code for about 2 hours trying to figure out the problem but without luck! my code are as following:
Client class:
private PrintWriter pw;
/**
* #param args
* #throws IOException
*/
public void connect() throws IOException{
final int portNumber = 6040;
// du kan vælge at bruge inetadressen til at connecte i socketet.
InetAddress adr = InetAddress.getByName("localhost");
Socket socket = new Socket("localhost", portNumber);
pw = new PrintWriter(socket.getOutputStream());
// outPut - Programmet sender til serveren
pw.println("Connected waiting for input");
pw.flush();
//input - Serveren sender til programmet;
}
public void Send(String x) throws IOException{
if (x != null) {
pw.print(x);
pw.flush();
}else {
System.out.println("ingen meddelse");
}
}
public String getInformation(){
Scanner informationFromServer = new Scanner(System.in);
String x = informationFromServer.nextLine();
if (x== null) {
return "";
}
return x;
}
my simpleController code (the code that controls my GUI):
public class SimpleController implements Initializable{
public Button btn_Connect;
private Client client;
public Label chatPerson3;
public Label chatPerson1;
public Label lbl_Chatperson1_userName;
public TextField txt_userName;
public TextField textField_chat;
public TextField txt_ChatPerson1;
public Button Send;
public TextField txt_ChatPerson2;
#Override
public void initialize(URL location, ResourceBundle resources) {
// TODO Auto-generated method stub
btn_Connect.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
chatPerson1.setVisible(true);
lbl_Chatperson1_userName.setText(txt_userName.getText());
}
});
Send.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
String x = textField_chat.getText();
textField_chat.setText("");
txt_ChatPerson1.setVisible(true);
txt_ChatPerson1.setText(x);
System.out.println(x);
try {
client.Send(x);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}}
and last but not least my main:
public class Main extends Application{
public static void main(String[] args) throws IOException{
Application.launch(Main.class, (java.lang.String[]) null);
}
#Override
public void start(Stage primaryStage) throws Exception {
try {
Client c = new Client();
c.connect();
AnchorPane page = (AnchorPane) FXMLLoader.load(Main.class.getResource("testingBackground.fxml"));
Scene scene = new Scene(page);
primaryStage.setScene(scene);
primaryStage.setTitle("Chatten");
primaryStage.show();
} catch (Exception ex) {
java.util.logging.Logger.getLogger(Main.class.getName()).log(
java.util.logging.Level.SEVERE, null, ex);
}
}
}
The exception I get when I try to send is of course in my client.send() method and if I try to receive before I send then it is in the client.getInformation() method.
What have I done wrong? What am I missing?
I am a Java newbie trying to learn network programming and concurrency, and I thought I'd try out writing a simple chat server where input from a client is echoed to all the clients. That's not happening. I added a couple print statements so that the program will announce that it is waiting for connections and each time it receives a connection. I am using Telnet locally to connect to the port on my machine.
The program announces success for the first and second concurrent connections but then does not announce success for subsequent connections until I close all connections. So, for example, I'll connect from five separate terminals, and the program will announce "Connection 1" and "Connection 2" but will not announce "Connection 3", 4, and 5 until I close all the terminals.
I'm looking for help figuring out where my errors lie as well as general advice for how to approach debugging a situation like this.
In a nutshell, my program has
A Main class, which starts the other three threads
A ClientListener class, which uses a SocketReader to listen for connections and stores the Sockets inputstreams and outputstreams in two Sets.
A MessageReader, which iterates over the inputstreams. If it finds a message, it puts it in a SynchronousQueue and waits for the
MessageWriter to remove it. The MessageWriter sends the message to all the outputstreams.
The code is below. Thanks for any help!
public class Main {
public static void main(String[] args) {
ClientListener clientListener = new ClientListener();
Thread clientListenerThread = new Thread(clientListener);
clientListenerThread.setPriority(Thread.MAX_PRIORITY);
clientListenerThread.start();
MessageReader messageReader = new MessageReader(clientListener);
Thread messageReaderThread = new Thread(messageReader);
messageReaderThread.setPriority(Thread.MIN_PRIORITY);
messageReaderThread.start();
MessageWriter messageWriter = new MessageWriter(messageReader, clientListener);
Thread messageWriterThread = new Thread(messageWriter);
messageWriterThread.setPriority(Thread.NORM_PRIORITY);
messageWriterThread.start();
}
}
public class ClientListener implements Runnable {
private static final int DEFAULT_PORT = 5000;
private Set<Scanner> clientIn = Collections.synchronizedSet(
new LinkedHashSet<Scanner>());
private Set<PrintWriter> clientOut = Collections.synchronizedSet(
new LinkedHashSet<PrintWriter>());
public Set<Scanner> getClientIn() {
return clientIn;
}
public Set<PrintWriter> getClientOut() {
return clientOut;
}
#Override
public void run() {
try {
ServerSocket server = new ServerSocket(DEFAULT_PORT);
System.out.println("Listening for connections...");
int connectionNum = 0;
while(true) {
Socket socket = server.accept();
connectionNum++;
System.out.format("Connection %s%n", connectionNum);
Scanner in = new Scanner(socket.getInputStream());
PrintWriter out = new PrintWriter(socket.getOutputStream());
clientIn.add(in);
clientOut.add(out);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class MessageReader implements Runnable {
private ClientListener clientListener;
private BlockingQueue<String> messages = new SynchronousQueue<String>();
public MessageReader(ClientListener clientListener) {
this.clientListener = clientListener;
}
#Override
public void run() {
while(true) {
Set<Scanner> clients = clientListener.getClientIn();
synchronized (clients) {
for(Scanner client: clients) {
if(client.hasNext()) {
try {
messages.put(client.next());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
public String getMessage() throws InterruptedException {
return messages.take();
}
}
public class MessageWriter implements Runnable {
private ClientListener clientListener;
private MessageReader messageReader;
public MessageWriter(
MessageReader messageReader,
ClientListener clientListener) {
this.messageReader = messageReader;
this.clientListener = clientListener;
}
#Override
public void run() {
try {
while(true) {
String message = messageReader.getMessage();
Set<PrintWriter> clients = clientListener.getClientOut();
synchronized (clients) {
for(PrintWriter client: clients) {
client.println(message);
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I'm not a threading expert, but in class MessageReader there is this line
if(client.hasNext())
Javadoc for Scanner.hasNext() say's "This method may block while waiting for input to scan. The scanner does not advance past any input."
If the scanner is still in wait the synchronized method never proceeds and block all other inputs. And as said in my earlier comment the line which says clientIn.add(in); in class ClientListener probably gets blocked given that its a synchronized Set, but since the print statment is written before it, it might give the impression that Connection 2 was succesfully established.