SwingWorker: process() method is not being called - java

I have a SwingWorker thread which I'm using to update a UI JLabel, and aside from the the publish()/process() methods, the program works (in that the JLabel is successfully posted with the appropriate text/background/border etc.). However, I want to use a process() method to set the text of the JLabel to "Connecting..." while the doInBackground() does its work, but the process() method in my program is never called (I am obviously using the publish() method). Suggestions?
Here's the SwingWorker:
public class PcclientBackgroundWork extends SwingWorker < String, String> {
public JLabel connectionStatus2;
String msg;
/* Constructor */
public PcclientBackgroundWork(JLabel label){
connectionStatus2 = label;
}
/*Background work to determine Application connection status
and pass corresponding message (String msg) to done() */
#Override
public String doInBackground() throws Exception {
String serverName = "localhost"; //UDP is sent within same machine
int port = 6789;
try {
Socket client = new Socket(serverName, port);
BufferedReader in = new BufferedReader
(new InputStreamReader(client.getInputStream()));
while(!in.ready()){
publish("Connecting"); //Want this method called until the bufferedReader is ready.
} //Loops until ready
msg = in.readLine(); //Incoming text is only one line
if(msg.equals("Connection Unsuccessful"))
{
msg = "Application Connection Failed";
} else {
msg = "App Connected " + msg;
}
System.out.println("msg = " + msg);
in.close(); //Close reader
client.close(); //Close client socket
} catch (IOException e) {
e.printStackTrace();
msg = "Application Connection Failed"; //JLabel text set the same as
} //if connection is unsuccessful (lines 66-68)
return msg;
}
public void process(String msg){
System.out.println("process method called...");
connectionStatus2.setText(msg);
}
/*Method to set JLabel information when doInBackground() is complete */
#Override
public void done() {
try {
connectionStatus2.setText(get()); //get() is the return value of doInBackground (String msg)
connectionStatus2.setBorder(BorderFactory.createLineBorder(Color.black));
connectionStatus2.setVisible(true);
connectionStatus2.setOpaque(true);
if(get().equals("Application Connection Failed")){
connectionStatus2.setBackground(Color.PINK);
} else {
connectionStatus2.setBackground(Color.GREEN);
}
} catch (InterruptedException ex) {
} catch (ExecutionException ex) {
Logger.getLogger(PcclientUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
I did not post the UI thread because the SwingWorker functions to my liking aside from the publish/process methods. Thanks in advance!

The signature for process is process(List<V>), not process(V). Change your process method to process(List<String> list); you may get more than one item in the list, depending on how often publish was called before process has a chance to run.

Related

Server thread socket ignoring called method with readLine

I have a P2P network of nodes holding records of key:value, which can pass requests to other nodes on the network when the asked node doesn't hold the desired key. The operation always returns an "OK" or an "ERROR". However, when a server thread recieving the request passes it down to all the other connected nodes by calling a method, the anwser ("OK" or "ERROR") isn't captured by the method, but by the main loop in run().
Here is the simplified code:
the run() method of the server thread class:
public void run(){
String line;
try {
while (true){
line=in.readLine();
if(line!=null){
else{
switch (line.split(" ")[0]){
case "set-value":
out.println(setValue(line.split(" ")[1]));
break;
System.out.println("default:");
System.out.println(line);
break;
}
}
}
}
} catch (IOException e) {
System.out.println("connection closed with: "+socket.getInetAddress().getHostAddress()+":"+socket.getPort()+" (server socket)");
}
}
the setvalue() method:
private String setValue(String arg) throws IOException {
String setKey = arg.split(":")[0];
String setValue = arg.split(":")[1];
if(DatabaseNode.getKey().equals(setKey)){
DatabaseNode.setValue(setValue);
System.out.println("set-value successful, current record: "+DatabaseNode.getKey()+":"+DatabaseNode.getValue());
return "OK";
} else {
System.out.println("key not on this node, searching...");
for (ServerConnect sc : DatabaseNode.getConnectToClient()) {
System.out.println("sending set-value to: "+sc);
if(sc.sendRead("set-value "+arg ).equals("OK")) {
return "OK";
}
}
for (ServerThread st : DatabaseNode.getConnectedToServer()) {
if(st != this) {
System.out.println("sending set-value to: "+st);
if(st.sendRead("set-value "+arg).equals("OK")) {
return "OK";
}
}
}
}
return "ERROR";
}
and the problematic one, sendRead(), which is supposed to send a string and wait for the anwser, but instead is ignored and anwser is captured by the main run() method
public String sendRead(String str) throws IOException {
out.println(str);
String line;
System.out.println("sent "+str+" awaiting response...");
line = in.readLine();
System.out.println("got "+line);
return line;
}
Thank you for your help
I tried identifying the threads on incoming line, and I am absolutely sure that the same thread which is supposed to read from method just starts a new loop and does nothing with sendRead().
The socket is NOT static, autoFlush on BufferedReader is enabled.
I just figured out what was wrong, the readLine() call in run() steals the next line, leaving the method hanging.

How to IR remote control to IPTV with javaFx application?

I am trying to develop a JavaFx application for testing an IPTV. And my task is checking of channel changing successfully. There is no any component or device at the moment. But I am searching for this task, after that I will buy.
My application will send some remote control command over the IR device.
Here is an IR device, but It doesn't have a Java API.
Is there a way for this solution?
I searched and found a device which name was RedRat. It is usb-infrared device that we can use it linux and windows OS.
There is a utility for using it with a programming language.
Here is a sample java code, may be useful for somebody. But you should have a redrat device.
First step, you have to download this redRatHub and paste a direction
secondly, run main class which has same path with redrathub folders.
public class MyDemo {
private static Client client;
private static String DEVICE_NAME = "";
private static String DATA_SET = "";
public static void main(String[] args) {
try {
startRedRat();
client = new Client();
client.openSocket("localhost", 40000);
DEVICE_NAME = client.readData("hubquery=\"list redrats\"").split("]")[1].split("\n")[0].trim();
DATA_SET = client.readData("hubquery=\"list datasets\"").split("\n")[1];
sendCommand("power");
TimeUnit.SECONDS.sleep(5);
sendCommand("btn1", "btn1", "btn1", "btn1");
sendCommand("btnOK");
TimeUnit.SECONDS.sleep(30);
sendCommand("btnBACK");
sendCommand("channel+");
sendCommand("btn6", "btn1");
sendCommand("channel+");
sendCommand("channel-");
sendCommand("volume+");
sendCommand("volume-");
sendCommand("power");
client.closeSocket();
p.destroy();
} catch (Exception ex) {
System.err.println(ex.getMessage());
} finally {
System.out.println("Finished. Hit <RETURN> to exit...");
}
}
private static void sendCommand(String... command) {
try {
for (String cmd : command) {
client.sendMessage("name=\"" + DEVICE_NAME + "\" dataset=\"" + DATA_SET + "\" signal=\"" + cmd + "\"");
TimeUnit.MILLISECONDS.sleep(500);
System.out.println(cmd + " signal send");
}
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void startRedRat() {
try {
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
p = Runtime.getRuntime().exec("cmd /C C:\\RedRatHub\\RedRatHubCmd.exe C:\\RedRatHub\\TivibuDB.xml");
return null;
}
};
worker.run();
TimeUnit.SECONDS.sleep(5);
} catch (Exception e) {
e.printStackTrace();
}
}
}
this class is communicate with redrat device over the serial ports.
public class Client {
private Socket socket;
private DataOutputStream out;
private DataInputStream in;
/*
* Opens the socket to RedRatHubCmd.
*/
public void openSocket(String host, int port) throws UnknownHostException, IOException {
if (socket != null && socket.isConnected()) return;
socket = new Socket(host, port);
out = new DataOutputStream(socket.getOutputStream());
in = new DataInputStream(socket.getInputStream());
}
/*
* Closes the RedRatHubCmd socket.
*/
public void closeSocket() throws IOException {
socket.close();
}
/*
* Sends a message to the readData() method. Use when returned data from RedRatHub is not needed.
*/
public void sendMessage(String message) throws Exception {
String res = readData(message);
if (!res.trim().equals("OK")) {
throw new Exception("Error sending message: " + res);
}
}
/*
* Reads data back from RedRatHub. Use when returned data is needed to be output.
*/
public String readData(String message) throws IOException {
if (socket == null || !socket.isConnected()) {
System.out.println("\tSocket has not been opened. Call 'openSocket()' first.");
return null;
}
// Send message
out.write((message + "\n").getBytes("UTF-8"));
// Check response. This is either a single line, e.g. "OK\n", or a multi-line response with
// '{' and '}' start/end delimiters.
String received = "";
byte[] inBuf = new byte[256];
while (true) {
// Read data...
int inLength = in.read(inBuf);
//byte[] thisMSg = new byte[inLength];
String msg = new String(Arrays.copyOfRange(inBuf, 0, inLength), "UTF-8");
received += msg;
if (checkEom(received)) return received;
}
}
/*
* Checks for the end of a message
*/
public boolean checkEom(String message) {
// Multi-line message
if (message.trim().endsWith("}")) {
return message.startsWith("{");
}
// Single line message
return message.endsWith("\n");
//return true;
}
}

Handling multi Java TCP clients with Threads

I have been working with TCP server/client stuff for a while. I am actully good at UDP programming when it comes to connecting more than one user that is multiple clients. I tried to do the same on a TCP server that i made using Threads but whenever the Thread gets to this piece of code
String reader = (String)in.readObject();
an error is generated and the thread stops executing the code but the thread still runs the program keeping it alive.
Anyway here is the entire source code :
public class TestServer implements Runnable {
private Thread run, streams, connect, receive, send;
private ServerSocket socket;
private Socket conn;
private ObjectInputStream in;
private ObjectOutputStream out;
private boolean running, incomingMessage = false;
private int port;
public TestServer(int port) throws IOException {
this.port = port;
socket = new ServerSocket(port);
console("Server stated on : " + InetAddress.getLocalHost() + " : " + port);
run = new Thread(this, "Run");
run.start();
}
public void run() {
running = true;
connect();
receive();
}
private void connect() {
connect = new Thread("Connect") {
public void run() {
while(running) {
try {
conn = socket.accept();
} catch (IOException e) {
e.printStackTrace();
}
console("You are now connected" + conn.getInetAddress().toString() + " : " + conn.getPort());
try {
setupStreams();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}; connect.start();
}
private void setupStreams() throws IOException {
streams = new Thread("Streams") {
public void run() {
try {
console("Setting up Streams");
out = new ObjectOutputStream(conn.getOutputStream());
out.flush();
in = new ObjectInputStream(conn.getInputStream());
console("Streams are now setup");
incomingMessage = true;
receive.start();
} catch(IOException e) {
e.printStackTrace();
}
}
}; streams.start();
}
private void receive() {
receive = new Thread("Receive") {
public void run() {
while(incomingMessage) {
String message = "";
try {
message = (String) in.readObject();
//This is the only flaw the program
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
console("Client : " + message);
}
}
};
}
private void console(String message) {
System.out.println(message);
}
public static void main(String[] args) {
try {
new TestServer(1234);
} catch (IOException e) {
e.printStackTrace();
}
}
}
FYI am not new to this. The error is caused because the server starts receiving packets even when there are no packets to be received. But because the thread forces it to receive it, i generates the error in the thread and dont know any other way to counter this. So please help. Thanks in Advance.
You shouldn't need 2 threads per connection. One thread is all that's required. After the connection is accepted, pass it to a worker thread to start reading. This can be done in a while loop in the worker thread.
Even though the socket's input stream can be read, the ObjectInputStream() class is more sensitive. If there is any error, its state is corrupted and it can't be used.
while (true) {
try {
Object input = in.readObject();
message = (String) input;
} catch (IOException e) {
e.printStackTrace();
break; //unrecoverable
} catch (ClassNotFoundException e) {
e.printStackTrace();
break; //unrecoverable
}
console("Client : " + message);
}
It's a better design to use a specific message protocol instead of sending serialized Java objects. For example if you are sending Strings like your sample, an InputStreamReader can be used to convert bytes to characters more easily and with less error handling.
These resources would be helpful to you:
https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html#later
Java - Listening to a socket with ObjectInputStream
ObjectInputStream(socket.getInputStream()); does not work

Why does my Client freeze when awaiting a response from the Server? [duplicate]

I have a small bit of code that runs in an applet that contains SWING controls and is used to write information to a socket on a certain port and then listens for a response. This works fine, but there is a problem with it. The port listener is essentially in a loop until null is received by the server. I want users to be able to perform other actions in the GUI instantiated by the applet while waiting for the server to respond (this could take minutes to occur). I also need to worry about the connection between the server and the client disconnecting. But the way the code is written, the applet appears to freeze (its really in a loop) until the server responds. How can I allow the listener to do its listening in the background, allowing other things to occur in the program. I assume I need to use threads and I'm sure for this application, it is easy to implement, but my lack of a solid thread foundation is hampering me. Below is the code (you can see how simple it is). How can I improve it to make it do what I need it to do>
public String writePacket(String packet) {
/* This method writes the packet to the port - established earlier */
System.out.println("writing out this packet->"+packet+"<-");
out.println(packet);
String thePacket = readPacket(); //where the port listener is invoked.
return thePacket;
}
private String readPacket() {
String thePacket ="";
String fromServer="";
//Below is the loop that freezes everything.
try {
while ((fromServer = in.readLine()) != null) {
if (thePacket.equals("")) thePacket = fromServer;
else
thePacket = thePacket+newLine+fromServer;
}
return thePacket; //when this happens, all listening should stop.
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
Thanks,
Elliott
There lots of different means of getting the IO performed on a different thread, but in this case you probably want to use SwingWorker.
Your code would look something like:
private final Executor executor = Executors.newSingleThreadExecutor();
public void writePacket(final String packet)
{
// schedules execution on the single thread of the executor (so only one background operation can happen at once)
//
executor.execute(new SwingWorker<String, Void>()
{
#Override
protected String doInBackground() throws Exception
{
// called on a background thread
/* This method writes the packet to the port - established earlier */
System.out.println("writing out this packet->"+packet+"<-");
System.out.println(packet);
String thePacket = readPacket(); //where the port listener is invoked.
return thePacket;
}
#Override
protected void done()
{
// called on the Swing event dispatch thread
try
{
final String thePacket = get();
// update GUI with 'thePacket'
}
catch (final InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (final ExecutionException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
private String readPacket()
{
String thePacket ="";
String fromServer="";
//Below is the loop that freezes everything.
try
{
while ((fromServer = in.readLine()) != null)
{
if (thePacket.equals(""))
thePacket = fromServer;
else
thePacket = thePacket+newLine+fromServer;
}
return thePacket; //when this happens, all listening should stop.
}
catch (IOException e)
{
e.printStackTrace();
return null;
}
}
All the network I/O should be in a separate thread.
BTW readLine() returns null when the server closes the connection, not when it has finished sending data for the moment.

Why does it return a null value?!!(client/server application)

i have asked this question 2 days before but I can not edit that(I don't know why)also i have changed some part of my classes.also I have checked it a lot but really I don't know that why it returns null value(on the console is written :Client says: null
),please help me.
at first i get the text from a text area which get text from client and then i will set it to my text area which is the output(like chat frame in Yahoo Messenger) and then i will send that text to my MainClient class.
my send button action performed in my chat frame:(I have tested the String text in the chat frame and it wasn't null)
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
submit();
clear();
}
private void submit() {
String text = jTextArea1.getText();
jTextArea2.append(client.getCurrentName() + " : " + text + "\n");
MainClient.setText(client.getCurrentName() + " : " + text + "\n");
}
my MainClient class:(a part of that)
private static String text;
public static String getText() {
return text;
}
public static void setText(String text) {
MainClient.text = text;
}
static boolean closed = false;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
String teXt = getText();
try {
os = new PrintWriter(c.getOutputStream(), true);
is = new BufferedReader(new InputStreamReader(c.getInputStream()));
} catch (IOException ex) {
Logger.getLogger(MainClient.class.getName()).log(Level.SEVERE, null, ex);
}
if (c != null && is != null && os != null) {
try {
os.println(teXt);//send data over socket.
String line = is.readLine();//recieve text from server.
System.out.println("Text received: " + line);
c.close();
} catch (IOException ex) {
System.err.println("read Failed");
}
}
}}
my MainServer class:(a part of that)
try {
BufferedReader streamIn = new BufferedReader(new InputStreamReader(client.getInputStream()));
boolean done = false;
String line =null;
while (!done ) {
line = streamIn.readLine();
if (line.equalsIgnoreCase("bye")) {
done = true;
} else {
System.out.println("Client says: " + line);
}
}
streamIn.close();
client.close();
server.close();
} catch (IOException e) {
System.out.println("IO Error in streams " + e);
}
}}
At first I will run the MainServer and then I will run the MainClient(which will show the chat frame).
EDIT:please start reading from this part: these are two classes ,one for gui and the other for client.(network) it returns nothing on the console for server so it will return nothing to the client.please help me thanks. my GUI class:(a part of that) (like a chat frame which by clicking on the Send button .I will send something for the server)
my gui class(chat frame) a part of that:
private void SendActionPerformed(java.awt.event.ActionEvent evt) {
setButtonIsSelected(true);
submit();
clear();
}
private void submit() {
String text = jTextArea1.getText();
jTextArea2.append(client.getCurrentName() + " : " + text + "\n");
MainClient.setText(client.getCurrentName() + " : " + text + "\n");
}
private static boolean buttonIsSelected = false ;
public static boolean isButtonIsSelected() {
return buttonIsSelected;
}
public static void setButtonIsSelected(boolean buttonIsSelected) {
ChatFrame.buttonIsSelected = buttonIsSelected;
}
my MainClient class:(a part of that)
show a chat frame.
if ( ChatFrame.isButtonIsSelected() == true) {
String teXt = getText();
System.out.println(teXt);
os.println(teXt);
String line;
line = is.readLine();
System.out.println("Text received: " + line);
}
at first I will run the client class So the gui class will be run which name is chat Frame.
It seems your main client is connecting to the server and sending text right on startup, not when someone enters something. So variable text is null.
You should send text over the wire when the user presses the button and receive lines from server always. So you should dedicate a thread (the main thread is ok) to read from server and nothing more.
Of course, if you use the main thread to receive server responses you have to be careful to update your UI because you cannot do it from any thread. In Swing you have to call a special method (SwingUtilities#invokeLater if I remember well) but in AWT I don't know.
Hope it helps. Maybe I'm not getting the correct point after all! :D
Try calling:
os.flush();
on your PrintWriter immediately after calling:
os.println(teXt);
A trivial solution could be, that your teXt variable is null or empty at the time you send it to the socket. Please insert a System.out.println(teXt) right before your os.println(teXt) call to double check, that you really send something to the client.
Edit
So at last the tricky client/server part is working as it should. I think helios has the right answer in his comments: When you start the client with something like
java -cp <your classpath> your.pckg.here.MainClient
it will immediatly call getText() which returns null because that's how the text field gets initialized. So you assign that null value to teXt and that's what you send.
This code does not react on anything you do or change in the chat frame.
So the solution is to redesign the flow in the application so that the client really sends something if and only if a button is pressed on the chat frame.
Edit
This is a very simple but working example of a client/server system with a GUI. The code is extremely bad (bad exception handling, client and server won't terminate and have to be 'killed', ugly GUI) but it demonstrates the basics.
Server:
public class Server {
public static void main(String[] args) throws Exception {
ServerSocket socket = new ServerSocket(12345);
while(true) {
Socket client = socket.accept();
InputStream in = client.getInputStream();
int i = in.read();
while (i != -1) {
System.out.print((char) i);
i = in.read();
}
System.out.println();
in.close();
}
}
}
The server listens on port 12345 and simply dumps all incoming bytes as characters to the console. It will do this forever (real server can be stopped...)
GUI:
public class GUI extends JFrame {
public GUI() {
setSize(100, 100);
Container contentPane = getContentPane();
Button button = new Button("Press me");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Client.send("Button pressed");
}
});
contentPane.add(button);
}
}
Nothing but a titleless frame showing a single button. If you press this button, it will send a text message to the Client class (iaw - call the Client.send method with a static text)
The Client:
public class Client {
public static void main(String[] args) throws Exception {
GUI gui = new GUI();
gui.setVisible(true);
}
public static void send(String msg) {
try {
Socket socket = new Socket("localhost", 12345);
OutputStream out = socket.getOutputStream();
out.write("Hello world".getBytes());
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
The client creates and spawnd the gorgeous GUI. And it contains the send service. Upon request (calling send method) it will establish a connection to the server and send the String as bytes.
So the point is: in order to send something, you have to tell the client to do so. And that's the same on your code: just setting a field on the client class will not trigger the send routine. Implement a send method and call it whenever you have something to send.
(I didn't include packagenames and imports in the examples, but I only used standard java (swing) classes.)

Categories