My Java Applet works perfectly fine when I run from Netbeans and the jar file created works fine too. However, when I embed the applet into the browser, I have this error "RuntimeException java.lang.reflect.InvocationTargetException" I have surfed through to debug this error but I couldn't seem to find a solution for my codes. Please help. Thank You.
Here are my codes:
SerialTest.java (this is my main class, in the main method, I call the applet so that whatever that should be printed in the Java console will be printed in the applet instead)
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Enumeration;
import java.util.Scanner;
public class SerialTest implements SerialPortEventListener {
SerialPort serialPort;
/**
* The port we're normally going to use.
*/
public static final String PORT_NAMES[] = {
"/dev/cu.usbserial-A9014NQP" //, Mac OS X
//"/dev/ttyUSB0", // Linux
//"COM3", // Windows
};
/**
* A BufferedReader which will be fed by a InputStreamReader converting the
* bytes into characters making the displayed results codepage independent
*/
public BufferedReader input;
/**
* The output stream to the port
*/
public OutputStream output;
/**
* Milliseconds to block while waiting for port open
*/
public static final int TIME_OUT = 2000;
/**
* Default bits per second for COM port.
*/
public static final int DATA_RATE = 9600;
public void initialize() {
CommPortIdentifier portId = null;
Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
//First, Find an instance of serial port as set in PORT_NAMES.
while (portEnum.hasMoreElements()) {
CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement();
for (String portName : PORT_NAMES) {
if (currPortId.getName().equals(portName)) {
portId = currPortId;
break;
}
}
}
if (portId == null) {
//portnotdetected = "Could not find COM port.";
System.out.println("Could not find COM port.");
return;
}
try {
// open serial port, and use class name for the appName.
serialPort = (SerialPort) portId.open(this.getClass().getName(),
TIME_OUT);
// set port parameters
serialPort.setSerialPortParams(DATA_RATE,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
// open the streams
input = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
output = serialPort.getOutputStream();
// add event listeners
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
} catch (Exception e) {
System.err.println(e.toString());
}
}
/**
* This should be called when you stop using the port. This will prevent
* port locking on platforms like Linux.
*/
public synchronized void close() {
if (serialPort != null) {
serialPort.removeEventListener();
serialPort.close();
}
}
/**
* Handle an event on the serial port. Read the data and print it.
*/
public synchronized void serialEvent(SerialPortEvent oEvent) {
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
String inputLine = input.readLine().trim();
//String readID = inputLine.substring(1);
System.out.println("Read Tag ID: " + inputLine); //this is the tagID read
Connection conn = null;
try {
String userName = "root";
String password = "root";
String url = "jdbc:mysql://localhost:8889/RFID";
Class.forName("com.mysql.jdbc.Driver").newInstance();
conn = DriverManager.getConnection(url, userName, password);
//System.out.println("Database connection established");
Statement stmt = null;
ResultSet rs = null;
//SQL query command
String SQL = "SELECT * FROM Inventory WHERE (SerialID = '" + inputLine + "')";
//String SQL = "SELECT * FROM Inventory";
stmt = conn.createStatement();
rs = stmt.executeQuery(SQL);
if (rs != null && rs.next()) {
String SerialID = rs.getString("SerialID");
String name = rs.getString("Name");
String description = rs.getString("Description");
if (inputLine.equals(SerialID)) {
System.out.println(SerialID + "\t " + name + "\t " + description + "\n"); //from Database
}
} else {
System.out.println("Sorry Tag ID " + inputLine + " not found database \n");
}
} catch (Exception e) {
System.err.println("Cannot connect to database server");
e.printStackTrace();
}
} catch (Exception e) {
System.err.println(e.toString());
}
}
// Ignore all the other eventTypes, but you should consider the other ones.
}
public static void main(String[] args) throws Exception {
new SerialApp();
SerialTest main = new SerialTest();
main.initialize();
Thread t = new Thread() {
public void run() {
//the following line will keep this app alive for 1000 seconds,
//waiting for events to occur and responding to them (printing incoming messages to console).
try {
Thread.sleep(1000000);
} catch (InterruptedException ie) {
}
}
};
t.start();
System.out.println("Started");
/*
Scanner scanner = new Scanner(System.in);
String userInput = scanner.next();
if ("q".equals(userInput)) {
System.exit(0);
}
*/
}
}
SerialApp.java (this is where I create my applet)
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JApplet;
import javax.swing.JFrame;
public class SerialApp extends JApplet implements Runnable, ActionListener
{
public JFrame frame;
public TextArea textArea;
public Thread reader;
public Thread reader2;
public boolean quit;
public final PipedInputStream pin=new PipedInputStream();
public final PipedInputStream pin2=new PipedInputStream();
Thread errorThrower; // just for testing (Throws an Exception at this Console
public void init() {
}
public SerialApp()
{
// create all components and add them
frame=new JFrame("RFID");
Dimension screenSize=Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize=new Dimension((int)(screenSize.width/2),(int)(screenSize.height/2));
int x=(int)(frameSize.width/2);
int y=(int)(frameSize.height/2);
frame.setBounds(x,y,frameSize.width,frameSize.height);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textArea=new TextArea();
textArea.setEditable(false);
Container container = getContentPane();// Get the content pane of the frame
container.setLayout(new BorderLayout());
container.add(textArea, BorderLayout.CENTER);
//Button button=new Button("clear"); //create button
/*
Panel panel=new Panel();
panel.setLayout(new BorderLayout());
panel.add(textArea,BorderLayout.CENTER);
//panel.add(button,BorderLayout.SOUTH); //button location
*/
frame.add(container);
frame.setVisible(true);
//button.addActionListener(this); //add button
try
{
PipedOutputStream pout=new PipedOutputStream(this.pin);
System.setOut(new PrintStream(pout,true));
}
catch (java.io.IOException io)
{
textArea.append("Couldn't redirect STDOUT to this console\n"+io.getMessage());
}
catch (SecurityException se)
{
textArea.append("Couldn't redirect STDOUT to this console\n"+se.getMessage());
}
try
{
PipedOutputStream pout2=new PipedOutputStream(this.pin2);
System.setErr(new PrintStream(pout2,true));
}
catch (java.io.IOException io)
{
textArea.append("Couldn't redirect STDERR to this console\n"+io.getMessage());
}
catch (SecurityException se)
{
textArea.append("Couldn't redirect STDERR to this console\n"+se.getMessage());
}
quit=false; // signals the Threads that they should exit
// Starting two seperate threads to read from the PipedInputStreams
//
reader=new Thread(this);
reader.setDaemon(true);
reader.start();
//
reader2=new Thread(this);
reader2.setDaemon(true);
reader2.start();
}
public synchronized void actionPerformed(ActionEvent evt)
{
textArea.setText("");
}
public synchronized void run()
{
try
{
while (Thread.currentThread()==reader)
{
try { this.wait(100);}catch(InterruptedException ie) {}
if (pin.available()!=0)
{
String input=this.readLine(pin);
textArea.append(input);
}
if (quit) return;
}
while (Thread.currentThread()==reader2)
{
try { this.wait(100);}catch(InterruptedException ie) {}
if (pin2.available()!=0)
{
String input=this.readLine(pin2);
textArea.append(input);
}
if (quit) return;
}
} catch (Exception e)
{
textArea.append("\nConsole reports an Internal error.");
textArea.append("The error is: "+e);
}
// just for testing (Throw a Nullpointer after 1 second)
if (Thread.currentThread()==errorThrower)
{
try { this.wait(1000); }catch(InterruptedException ie){}
throw new NullPointerException("Application test: throwing an NullPointerException It should arrive at the console");
}
}
public synchronized String readLine(PipedInputStream in) throws IOException
{
String input="";
do
{
int available=in.available();
if (available==0) break;
byte b[]=new byte[available];
in.read(b);
input=input+new String(b,0,b.length);
}while( !input.endsWith("\n") && !input.endsWith("\r\n") && !quit);
return input;
}
}
applet.html
<html>
<head>
<title>Applet</title>
</head>
<body>
<applet code="SerialTest.class" archive="SerialApplet.jar" width="550" height="550">
</applet>
</body>
</html>
I have this error "RuntimeException
java.lang.reflect.InvocationTargetException"
This is because You are putting the applet code tag as :
<applet code="SerialTest.class" archive="SerialApplet.jar" width="550" height="550">
And SerialTest is not an Applet..Applets don't use a main method to execute. Instead they are started with their init() and start() methods. Have a look at the following official tutorial to know more about Applets : Java Applets
I have this error "RuntimeException
java.lang.reflect.InvocationTargetException"
Because , You are overruling the rules provided by sandbox of java Applet. I guess, gnu.io.SerialPort has something to do with this. Look at here to know more about applet sandbox: What Applets Can and Cannot Do
Related
Now I do realize there are lots of the same question but even after reading the answers I seem not to undertsand. So here is the code and I'll explain the problem.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Server implements Runnable {
String firstName;
String lastName;
String password;
private ArrayList<ConnectionHandler> connections;
private ServerSocket server;
private boolean done;
private ExecutorService pool;
public Server() {
connections = new ArrayList<>();
done = false;
}
#Override
public void run() {
try {
server = new ServerSocket(9999);
pool = Executors.newCachedThreadPool();
while (!done) {
Socket client = server.accept();
ConnectionHandler handler = new ConnectionHandler((client));
connections.add(handler);
pool.execute(handler);
}
} catch (Exception e) {
shutdown();
}
}
public void shutdown() {
try {
done = true;
pool.shutdown();
if (!server.isClosed()) {
server.close();
}
for (ConnectionHandler ch : connections) {
ch.shutdown();
}
} catch (IOException e) {
// ignore
}
}
class ConnectionHandler implements Runnable {
private Socket client;
private BufferedReader in;
private PrintWriter out;
public void broadcast(String message) {
for (ConnectionHandler ch : connections) {
if (ch != null) {
ch.sendMessage(message);
}
}
}
public ConnectionHandler(Socket client) {
this.client = client;
}
#Override
public void run() {
try {
out = new PrintWriter((client.getOutputStream()), true);
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out.println("To register type 1,to sign in type 2");
//TODO:for loop so only answer is 1 or 2
String message = in.readLine();
switch (message) {
case "1":
out.println("In order to register please enter your first and last name then set a password.");
out.println("Enter first name:");
firstName = in.readLine();
out.println("Enter last name:");
lastName = in.readLine();
out.println("Finally please set a password.");
password = in.readLine();
//TODO: add parameters for passcode
out.println("Now please type 2 to login");
message = in.readLine();
if (message.equals("2")) {
//TODO: copy paste from line 104-x
}
case "2":
out.println("Please enter your first name:");
String messageLogInFN= in.readLine();
out.println("Please enter your last name:");
String messageLogInLN = in.readLine();
out.println("Enter your password:");
String messageLogInPass = in.readLine();
boolean adminAccount = (messageLogInFN.equals("admin") && messageLogInLN.equals("admin") && messageLogInPass.equals("admin123cat"));
if (adminAccount) {
//TODO: add admin permissions
}
boolean Authentication = ((messageLogInFN.equals(firstName) && messageLogInLN.equals(lastName) && messageLogInPass.equals(password)));
if (Authentication) {
out.println("Welcome " + firstName + " " + lastName + "!");
System.out.println(firstName + " " + lastName + " has logged in." );
} else
out.println("Your name or password incorrect!");
}
} catch (IOException e) {
shutdown();
}
}
public void sendMessage(String message) {
out.println(message);
}
public void shutdown() {
try {
in.close();
out.close();
if (!client.isClosed()) {
client.close();
}
} catch (IOException e) {
//ignore
}
}
}
public static void main(String[] args) {
Server server = new Server();
server.run();
}
So I am learning java and saw a tutorial on youtube for a chat room, I programed it following the tutorial, and then I wanted to have a chat room with accounts so I got to coding. Now here is the thing even though I am able to have several devices connected to the server when 2 accounts register the server forgets the first one so there can only be 1 account at the same time. What I am trying to do is have an account system where everyone has their own account that they log in with their first name, last name and passwords. But it doesnt seem to work. How can I make it so that the server doesn't forget all accounts except for the last one that registered?
Edit: Here is the client code if it helps.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client implements Runnable {
private boolean done;
private Socket client;
private BufferedReader in;
private PrintWriter out;
#Override
public void run() {
try {
client = new Socket("127.0.0.1", 9999);
out = new PrintWriter((client.getOutputStream()), true);
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
InputHandler inHandler = new InputHandler();
Thread t = new Thread(inHandler);
t.start();
String inMessage;
while ((inMessage = in.readLine()) != null) {
System.out.println(inMessage);
}
} catch (IOException e) {
shutdown();
}
}
public void shutdown() {
done = true;
try {
in.close();
out.close();
if(!client.isClosed()) {
client.close();
}
} catch (IOException e) {
//ignore
}
}
class InputHandler implements Runnable {
#Override
public void run() {
try {
BufferedReader inReader = new BufferedReader(new InputStreamReader(System.in));
while (!done) {
String message = inReader.readLine();
if(message.equals("/quit")) {
out.println(message);
inReader.close();
shutdown();
} else {
out.println(message);
}
}
} catch (IOException e) {
shutdown();
}
}
}
public static void main(String[] args) {
Client client = new Client();
client.run();
}
}
Also as I said most of this isnt my code and I followed a yt tutorial.
import javax.swing.*;
import java.io.Serializable;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Server implements Serializable{
public static void main(String[] args) {
String test1= JOptionPane.showInputDialog(null,"Port(0-65535):","Port",JOptionPane.QUESTION_MESSAGE);
int portnumber = tryParse(test1);
if (portnumber !=0) {
try {
Registry reg = LocateRegistry.createRegistry(portnumber); //Creates and exports a Registry instance on the local host that accepts requests
RmiImplementation imp = new RmiImplementation("C://ServerStorage");
reg.bind("remoteObject", imp);
System.out.println("Server is ready.");
System.out.println(portnumber);
} catch (Exception e) {
System.out.println("Server failed: " + e);
}
}
}
private static Integer tryParse(String text) {
try {
return Integer.parseInt(text);
} catch (Exception e) {
return 0;
}
}
}
The above code helps me to set up my file server.
when the application is run, the dialog port number is requested.
If I type letters instead of numbers the program stops running, but I want it to continue and show me the dialog again.
Try with a do-while,
int portnumber = 0;
do {
String text= JOptionPane.showInputDialog(null,"Port(0-65535):","Port",JOptionPane.QUESTION_MESSAGE);
portnumber = tryParse(text);
}while(portnumber==0);
I declared a twoWaySerialComm object to to configure the port connection. Inside the twoWaySerialComm class I created a thread to read the incoming serial data in a class called 'SerialReader'. How can access the serial data from the main thread 'twoWaySerialComm'?
I had read the incoming serial data into 'hex' string in the 'SerialReader' class inside a while loop. I am able to print the incoming data inside the while loop, But i am unable to access this 'hex' string in the 'twoWaySerialComm' class. Why can't I access the 'hex' string outside the while loop? how can this be done?
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.UnsupportedCommOperationException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* #author asanka
*/
public class TwoWaySerialComm {
private static TwoWaySerialComm twoWaySerialComm;
String read;
private TwoWaySerialComm() throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException, IOException {
String portName = "/dev/ttyUSB0";
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
if (portIdentifier.isCurrentlyOwned()) {
System.out.println("Error: Port is currently in use");
} else {
CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000);
if (commPort instanceof SerialPort) {
SerialPort serialPort = (SerialPort) commPort;
serialPort.setSerialPortParams(115200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
InputStream in = serialPort.getInputStream();
OutputStream out = serialPort.getOutputStream();
SerialReader reader;
(new Thread(reader = new SerialReader(in))).start();
read = reader.readHex();
} else {
System.out.println("Error: Only serial ports are handled by this example.");
}
}
}
public static TwoWaySerialComm getTwoWaySerialComm() throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException, IOException {
if (twoWaySerialComm == null) {
twoWaySerialComm = new TwoWaySerialComm();
}
return twoWaySerialComm;
}
public String data() {
return read;
}
/**
*
*/
public static class SerialReader implements Runnable {
String hex;
InputStream in;
public SerialReader(InputStream in) {
this.in = in;
}
public void run() {
byte[] buffer = new byte[1024];
int len;
try {
while ((len = this.in.read(buffer)) > -1) {
hex = new String(buffer, 0, len).replaceAll("\\s", "");
Thread.sleep(1000);
System.out.println(hex);
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException ex) {
Logger.getLogger(TwoWaySerialComm.class.getName()).log(Level.SEVERE, null, ex);
}
}
public String readHex() {
return hex;
}
}
/**
*
*/
public static class SerialWriter implements Runnable {
OutputStream out;
public SerialWriter(OutputStream out) {
this.out = out;
}
public void run() {
try {
int c = 0;
while ((c = System.in.read()) > -1) {
this.out.write(c);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
As far as I can see, you're running the read operation in another Thread. When calling the readHex() method, that Thread probably hasn't filled in the hex field yet.
You'll need to call join() on the new Thread first, to ensure it has finished.
Or use the CompletableFuture from the java.util.concurrent package.
I'm facing a problem regarding of using the data from rf transmision on a class that I wish to use to store on the database. Code 1 is the code for the RF transmission. Is there anyway I can use the data in the
highlight of data to be used in code 1?
public synchronized void serialEvent(SerialPortEvent oEvent) {
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
String inputLine=input.readLine();
String[] parts = inputLine.split(",");
String part1 = parts[0];
String part2 = parts[1];
System.out.print(part1); // data to be used
System.out.print(" , ");
System.out.println(part2); //data to be used
//System.out.println(data);
code 1
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.util.Enumeration;
public class test implements SerialPortEventListener {
SerialPort serialPort;
/** The port we're normally going to use. */
private static final String PORT_NAMES[] = {
"COM4", // Windows
};
/**
* A BufferedReader which will be fed by a InputStreamReader
* converting the bytes into characters
* making the displayed results codepage independent
*/
private BufferedReader input;
/** The output stream to the port */
private OutputStream output;
/** Milliseconds to block while waiting for port open */
private static final int TIME_OUT = 2000;
/** Default bits per second for COM port. */
private static final int DATA_RATE = 9600;
public void initialize() {
CommPortIdentifier portId = null;
Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
//First, Find an instance of serial port as set in PORT_NAMES.
while (portEnum.hasMoreElements()) {
CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement();
for (String portName : PORT_NAMES) {
if (currPortId.getName().equals(portName)) {
portId = currPortId;
break;
}
}
}
if (portId == null) {
System.out.println("Could not find COM port.");
return;
}
try {
// open serial port, and use class name for the appName.
serialPort = (SerialPort) portId.open(this.getClass().getName(),
TIME_OUT);
// set port parameters
serialPort.setSerialPortParams(DATA_RATE,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
// open the streams
input = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
output = serialPort.getOutputStream();
// add event listeners
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
} catch (Exception e) {
System.err.println(e.toString());
}
}
/**
* This should be called when you stop using the port.
* This will prevent port locking on platforms like Linux.
*/
public synchronized void close() {
if (serialPort != null) {
serialPort.removeEventListener();
serialPort.close();
}
}
/**
* Handle an event on the serial port. Read the data and print it.
*/
public synchronized void serialEvent(SerialPortEvent oEvent) {
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
String inputLine=input.readLine();
String[] parts = inputLine.split(",");
String part1 = parts[0];
String part2 = parts[1];
System.out.print(part1); // data to be used
System.out.print(" , ");
System.out.println(part2); //data to be used
//System.out.println(data);
} catch (Exception e) {
System.err.println(e.toString());
}
}
// Ignore all the other eventTypes, but you should consider the other ones.
}
public static void main(String[] args) throws Exception {
test main = new test();
main.initialize();
Thread t=new Thread() {
public void run() {
//the following line will keep this app alive for 1000 seconds,
//waiting for events to occur and responding to them (printing incoming messages to console).
try {Thread.sleep(1000000);} catch (InterruptedException ie) {}
}
};
t.start();
System.out.println("Started");
}
I am probably still confused as to what your asking. I think the simplest way for another class to use the variables would be for it to be passed the values in arguments to one of its functions.
eg.
class ClassThatUsesPart1Part2 {
public void usePart1Part2(String part1, String part2) {
// put code that uses part1 and part2 here
}
}
Add another variable to your class.
private BufferedReader input;
/** The output stream to the port */
private OutputStream output;
/** Milliseconds to block while waiting for port open */
private static final int TIME_OUT = 2000;
/** Default bits per second for COM port. */
private static final int DATA_RATE = 9600;
/** Variable of class that will use part1, part2.*/
private ClassThatUsesPart1Part2 part12User = new ClassThatUsesPart1Part2();
Then use it within your function.
String inputLine=input.readLine();
String[] parts = inputLine.split(",");
String part1 = parts[0];
String part2 = parts[1];
part12User.usePart1Part2(part1,part2);
Is this what you were looking for or have I just completely misunderstood?
I am trying to create some local chat software.
Everything is working fine but just sticks on one point;
when a user clicks on a button my program gets stuck.
I wrote a modified class which behaves for both the server and the client.
Below is my code:
package connections;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.channels.SocketChannel;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import ui.ChatWindow;
public class Chat{
private SocketChannel socketChannel;
private ConnectionType connectionType;
private ObjectOutputStream out;
private ObjectInputStream in;
private String strClientName;
private ChatWindow chatWindow;
private String strMessage;
public Chat(SocketChannel socketChannel, ConnectionType connectionType) {
this.socketChannel = socketChannel;
this.connectionType = connectionType;
init();
}
private void init() {
new Thread(this::initThread).start();
}
private void initThread() {
try {
out = new ObjectOutputStream(socketChannel.socket().getOutputStream());
in = new ObjectInputStream(socketChannel.socket().getInputStream());
if (connectionType == ConnectionType.SERVER) {
getClientName();
sendMyName();
} else {
sendMyName();
getClientName();
}
chatWindow = new ChatWindow();
chatWindow.btnSend.addActionListener(this::eventBtnSend);
chatWindow.setTitle(strClientName);
chatWindow.setSize(600, 400);
chatWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
if (connectionType == ConnectionType.CLIENT) {
chatWindow.setVisible(true);
chatWindow.requestFocus();
}
System.out.println("here");
beginChat();
System.out.println("thread ends");
} catch (IOException ex) {
Logger.getLogger(Chat.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void getClientName() {
try {
strClientName = (String) in.readObject();
} catch (IOException | ClassNotFoundException ex) {
Logger.getLogger(Status.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void sendMyName() {
try {
out.writeObject(main.Config.myName);
out.flush();
} catch (IOException ex) {
Logger.getLogger(Status.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void beginChat() {
while (true) {
try {
waitForMessage();
} catch (IOException | ClassNotFoundException ex) {
Logger.getLogger(Chat.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private void waitForMessage() throws IOException, ClassNotFoundException {
System.out.println("waiting for Message : " + connectionType);
strMessage = (String) in.readObject();
System.out.println("Message received");
chatWindow.txtDisplay.append(strClientName + " : " + strMessage + "\n");
if(chatWindow.isVisible() == false){
chatWindow.setVisible(true);
}
}
private void sendMessage(String strMessage) {
try {
out.writeObject(strMessage);
out.flush();
} catch (IOException ex) {
Logger.getLogger(Chat.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void eventBtnSend(ActionEvent ae){
System.out.println("a");
sendMessage(chatWindow.txtMessage.getText());
System.out.println("b");
chatWindow.txtDisplay.append("Me : " + chatWindow.txtMessage.getText() + "\n");
System.out.println("c");
chatWindow.txtMessage.setText("");
}
}
When the server and client connects I can see this output:
here
waiting for Message : SERVER
here
waiting for Message : CLIENT
But when I click on the send button my program becomes stuck.
After clicking the button I can see:
a on console.
The word is 'blocks'. It's blocking I/O. It blocks.
Don't perform blocking operations on the event thread. All the networking code should run on separate threads. That includes readObject() and writeObject(), and flush(), and creating the streams too.