How to display shell command output on a jtextarea in java? - java

How to display shell command output on a jtextarea in java?
Kindly help
Thanks

You can get shell command output below snippet code, set jtextarea on while loop.
try {
String cmd = "java"; // Set shell command
Process child = Runtime.getRuntime().exec(cmd);
InputStream lsOut = child.getInputStream();
InputStreamReader r = new InputStreamReader(lsOut);
BufferedReader in = new BufferedReader(r);
// read the child process' output
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
// You should set JtextArea
}
} catch (Exception e) { // exception thrown
System.err.println("Command failed!");
}

You need to read the standard output as the process input stream and update the JTextArea using the event queue from another thread. See the example code below:
public class OutputDisplayer implements Runnable {
protected final JTextArea textArea_;
protected Reader reader_ = null;
public OutputDisplayer(JTextArea textArea) {
textArea_ = textArea;
}
public void commence(Process proc) {
InputStream in = proc.getInputStream();
reader_ = new InputStreamReader(in);
Thread thread = new Thread(this);
thread.start();
}
public void run() {
StringBuilder buf = new StringBuilder();
try {
while( reader_ != null ) {
int c = reader_.read();
if( c==-1 ) return;
buf.append((char) c);
setText( buf.toString() );
}
} catch ( IOException ioe ) {
buf.append("\n\nERROR:\n"+ioe.toString());
setText( buf.toString() );
} finally {
try {
reader_.close();
} catch ( IOException ioe ) {
ioe.printStackTrace();
}
}
}
private void setText(final String text) {
EventQueue.invokeLater(new Runnable() {
public void run() {
textArea_.setText(text);
}
});
}
}

In addition to my two links in my comments above, I created and used a TextAreaOutputStream that helps to redirect output stream data to a textarea:
import java.io.IOException;
import java.io.OutputStream;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class TextAreaOutputStream extends OutputStream {
private final JTextArea textArea;
private final StringBuilder sb = new StringBuilder();
private String title;
public TextAreaOutputStream(final JTextArea textArea, String title) {
this.textArea = textArea;
this.title = title;
sb.append(title + "> ");
}
#Override
public void flush() {
}
#Override
public void close() {
}
#Override
public void write(int b) throws IOException {
if (b == '\r')
return;
if (b == '\n') {
final String text = sb.toString() + "\n";
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textArea.append(text);
}
});
sb.setLength(0);
sb.append(title + "> ");
}
sb.append((char) b);
}
}

import java.io.OutputStream;
import javax.swing.JTextArea;
/**
* This class extends from OutputStream to redirect output to a JTextArrea
* #author www.codejava.net
*
*/
public class CustomOutputStream extends OutputStream {
private JTextArea textArea;
public CustomOutputStream(JTextArea textArea) {
this.textArea = textArea;
}
#Override
public void write(int b) throws IOException {
// redirects data to the text area
textArea.append(String.valueOf((char)b));
// scrolls the text area to the end of data
textArea.setCaretPosition(textArea.getDocument().getLength());
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package guiconsoleoutput;
/**
*
* #author root
*/
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.Date;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
public class TextAreaLogProgram extends JFrame {
/**
* The text area which is used for displaying logging information.
*/
private JTextArea textArea;
private JButton buttonStart = new JButton("Start");
private JButton buttonClear = new JButton("Clear");
private PrintStream standardOut;
public TextAreaLogProgram() {
super(" CONSOLE ");
textArea = new JTextArea(50, 10);
textArea.setEditable(false);
PrintStream printStream = new PrintStream(new CustomOutputStream(textArea));
// keeps reference of standard output stream
standardOut = System.out;
// re-assigns standard output stream and error output stream
System.setOut(printStream);
System.setErr(printStream);
// creates the GUI
setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridx = 0;
constraints.gridy = 0;
constraints.insets = new Insets(10, 10, 10, 10);
constraints.anchor = GridBagConstraints.WEST;
add(buttonStart, constraints);
constraints.gridx = 1;
add(buttonClear, constraints);
constraints.gridx = 0;
constraints.gridy = 1;
constraints.gridwidth = 2;
constraints.fill = GridBagConstraints.BOTH;
constraints.weightx = 1.0;
constraints.weighty = 1.0;
add(new JScrollPane(textArea), constraints);
// adds event handler for button Start
buttonStart.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
printLog();
}
});
// adds event handler for button Clear
buttonClear.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
// clears the text area
try {
textArea.getDocument().remove(0,
textArea.getDocument().getLength());
standardOut.println("Text area cleared");
} catch (BadLocationException ex) {
ex.printStackTrace();
}
}
});
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(480, 320);
setLocationRelativeTo(null); // centers on screen
}
/**
* Prints log statements for testing in a thread
*/
private void printLog() {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("Time now is " + (new Date()));
System.out.println("lol ");
String s = null;
/*try {
// run the Unix "ps -ef" command
// using the Runtime exec method:
Process p = Runtime.getRuntime().exec("dir");
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
System.exit(0);
}
catch (IOException e) {
System.out.println("exception happened - here's what I know: ");
e.printStackTrace();
System.exit(-1);
}*/
try {
String cmd = "cmd /c ping 8.8.8.8"; // Set shell command
Process child = Runtime.getRuntime().exec(cmd);
InputStream lsOut = child.getInputStream();
InputStreamReader r = new InputStreamReader(lsOut);
BufferedReader in = new BufferedReader(r);
// read the child process' output
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
// You should set JtextArea
}
} catch (Exception e) { // exception thrown
System.err.println("Command failed!");
}
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
});
thread.start();
}
/**
* Runs the program
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TextAreaLogProgram().setVisible(true);
}
});
}
}

Related

Understanding command line arguments

Basically I am just writing a socket.
For some reason I keep getting this error though
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at Main.ChatClient.main(ChatClient.java:143)
which is line " String server = args[0]; "
What does the args need to be to fix this issue?
package Main;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Observable;
import java.util.Observer;
// Class to manage Client chat Box.
public class ChatClient {
Main a = new Main();
/** Chat client access */
static class ChatAccess extends Observable {
private Socket socket;
private OutputStream outputStream;
#Override
public void notifyObservers(Object arg) {
super.setChanged();
super.notifyObservers(arg);
}
/** Create socket, and receiving thread */
public void InitSocket(String server, int port) throws IOException {
socket = new Socket(server, port);
outputStream = socket.getOutputStream();
Thread receivingThread = new Thread() {
#Override
public void run() {
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String line;
while ((line = reader.readLine()) != null)
notifyObservers(line);
} catch (IOException ex) {
notifyObservers(ex);
}
}
};
receivingThread.start();
}
private static final String CRLF = "\r\n"; // newline
/** Send a line of text */
public void send(String text) {
try {
outputStream.write((text + CRLF).getBytes());
outputStream.flush();
} catch (IOException ex) {
notifyObservers(ex);
}
}
/** Close the socket */
public void close() {
try {
socket.close();
} catch (IOException ex) {
notifyObservers(ex);
}
}
}
/** Chat client UI */
static class ChatFrame extends JFrame implements Observer {
private JTextArea textArea;
private JTextField inputTextField;
private JButton sendButton;
private ChatAccess chatAccess;
public ChatFrame(ChatAccess chatAccess) {
this.chatAccess = chatAccess;
chatAccess.addObserver(this);
buildGUI();
}
/** Builds the user interface */
private void buildGUI() {
textArea = new JTextArea(20, 50);
textArea.setEditable(false);
textArea.setLineWrap(true);
add(new JScrollPane(textArea), BorderLayout.CENTER);
Box box = Box.createHorizontalBox();
add(box, BorderLayout.SOUTH);
inputTextField = new JTextField();
sendButton = new JButton("Send");
box.add(inputTextField);
box.add(sendButton);
// Action for the inputTextField and the goButton
ActionListener sendListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
String str = inputTextField.getText();
if (str != null && str.trim().length() > 0)
chatAccess.send(str);
inputTextField.selectAll();
inputTextField.requestFocus();
inputTextField.setText("");
}
};
inputTextField.addActionListener(sendListener);
sendButton.addActionListener(sendListener);
this.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
chatAccess.close();
}
});
}
/** Updates the UI depending on the Object argument */
public void update(Observable o, Object arg) {
final Object finalArg = arg;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textArea.append(finalArg.toString());
textArea.append("\n");
}
});
}
}
public static void main(String[] args) {
System.out.println("troll");
String server = args[0];
System.out.println("reached here");
int port =2222;
ChatAccess access = new ChatAccess();
JFrame frame = new ChatFrame(access);
frame.setTitle("MyChatApp - connected to " + server + ":" + port);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
try {
access.InitSocket(server,port);
} catch (IOException ex) {
System.out.println("Cannot connect to " + server + ":" + port);
ex.printStackTrace();
System.exit(0);
}
}
}
Given:
String server = args[0];
I'd suggest you provide the server name as your first argument to your program
With
public static void main(String[] args)
args is the array of command line args passed in.

SwingWorker and command line process interrupts

I am trying to build a Swing solution for compressing files which is relayed on the rar command line. As the GUI needs to stay responsive I've wrapped the code for dealing with the command line into a SwingWorker class.
SwingWorker<Boolean, String> worker = new SwingWorker<Boolean, String>(){
protected Boolean doInBackground() throws Exception {
Runtime rt = Runtime.getRuntime();
try {
//daj processu da ode u background nekako, da ga ne sjebem sa ctrl + c (winrar umesto rar)
String command = "my command, this works just fine";
Process p = rt.exec(command, null, new File("C:\\Program Files\\WinRar"));
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
String s = null;
System.out.println("<INPUT>");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
System.out.println("</INPUT>");
InputStream stderr = p.getErrorStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(isr);
System.out.println("<ERROR>");
String line = null;
while ( (line = br.readLine()) != null){
System.out.println(line);
return false;
}
System.out.println("</ERROR>");
int exitVal = p.waitFor();
//EXIT VALUE IS ALWAYS 0, EVEN IF I INTERRUPT IT WITH CTRL+C
System.out.println("Process exitValue: " + exitVal);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
} catch (InterruptedException e) {
e.printStackTrace();
return false;
} catch (Exception e) {
return false;
}
return true;
}
#Override
protected void process(List<String> chunks) {
// TODO Auto-generated method stub
//SOME GUI UPDATES
}
#Override
protected void done() {
// TODO Auto-generated method stub
Boolean status = false;
try {
status = get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//MORE GUI UPDATES
if(status){
tableList.setValueAt("Done", row, 3);
} else{
tableList.setValueAt("Error", row, 3);
}
super.done();
}
};
worker.execute();
When I delete printing of input and error, exit value is printed as soon as rar appears on the screen. So there is no actual point of "waitFor()" method in my code. What I need is to check if rar closed without interrupts (like CTRL + C, or hitting "X" on cmd window) and get the exit code. I've tried adding shutdown hook on runtime (rt variable) but it reacts when I close the whole GUI.
You need to get your input and error streams, and read from them each in its own thread. Right now your error stream never has a chance because of the blocking while loop ahead of it.
I've used the following code (although it is years old...):
Enum: GobblerType.java
enum GobblerType {
ERROR, OUTPUT
}
Class StreamGobbler.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
public class StreamGobbler implements Runnable {
private InputStream is;
private GobblerType type;
private OutputStream os;
public StreamGobbler(InputStream is, GobblerType type) {
this(is, type, null);
}
public StreamGobbler(InputStream is, GobblerType type, OutputStream redirect) {
this.is = is;
this.type = type;
this.os = redirect;
}
public void run() {
try {
PrintWriter pw = null;
if (os != null) {
pw = new PrintWriter(os, true);
}
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
if (pw != null) {
pw.println(line);
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
And then have used it like so:
Process proc = Runtime.getRuntime().exec(.....); // TODO: Fix!
StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), GobblerType.ERROR);
StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), GobblerType.OUTPUT);
new Thread(errorGobbler).start();
new Thread(outputGobbler).start();
int exitVal = proc.waitFor();
proc.destroy();
OK, I created some code as a proof of concept program. I've modified my Gobbler a bit so that it doesn't require an OutputStream but rather uses a PropertyChangeListener to notify listeners of any text coming from the InputStream. For this to work, all my code is in the same package, and note that package names are key, and you would likely need to change yours. Running this code does behave as expected. It is a bit overly simplistic and probably should use some type of blocking queue for passing information between classes.
GobblerType.java
An enum to distinguish the two type of stream gobblers in use
package pkg2;
public enum GobblerType {
ERROR, OUTPUT
}
StreamGobbler2.java
The stream gobbler that uses an input stream reader to get text from the input stream, puts the text into a text field, and notifies listeners of new text. It uses a PropertyChangeListener for the notification. This is a crude way to producer-consumer, and risks not capturing all passed information. Better would be to use a blocking queue of some sort.
package pkg2;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.Callable;
public class StreamGobbler2 implements Callable<Void> {
private PropertyChangeSupport support = new PropertyChangeSupport(this);
private InputStream is;
private GobblerType type;
private String text;
public StreamGobbler2(InputStream is, GobblerType type) {
this.is = is;
this.type = type;
}
#Override
public Void call() throws Exception {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
setText(line);
}
return null;
}
public GobblerType getType() {
return type;
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
support.addPropertyChangeListener(listener);
}
public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
support.addPropertyChangeListener(propertyName, listener);
}
public void setText(String text) {
String oldValue = null;
String newValue = text;
this.text = text;
support.firePropertyChange(type.toString(), oldValue, newValue);
}
public String getText() {
return text;
}
}
ProcessLauncher.java
This is a non-Swing class that captures the information from the two gobblers. Again, better would be to use blocking queues (next iteration)
package pkg2;
import java.beans.PropertyChangeListener;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ProcessLauncher implements Callable<Integer> {
private ExecutorService execService = Executors.newFixedThreadPool(2);
private List<String> commands;
private List<PropertyChangeListener> listeners = new ArrayList<>();
public ProcessLauncher(List<String> commands) {
this.commands = commands;
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
listeners.add(listener);
}
#Override
public Integer call() throws Exception {
ProcessBuilder pb = new ProcessBuilder(commands);
Process p = pb.start();
int exitValue = 0;
try (InputStream inputStream = p.getInputStream();
InputStream errorStream = p.getErrorStream()) {
StreamGobbler2 errorGobbler = new StreamGobbler2(inputStream, GobblerType.OUTPUT);
StreamGobbler2 outputGobbler = new StreamGobbler2(errorStream, GobblerType.ERROR);
for (PropertyChangeListener listener : listeners) {
errorGobbler.addPropertyChangeListener(listener);
outputGobbler.addPropertyChangeListener(listener);
}
List<Future<Void>> futures = new ArrayList<>();
futures.add(execService.submit(errorGobbler));
futures.add(execService.submit(outputGobbler));
execService.shutdown();
exitValue = p.waitFor();
for (Future<Void> future : futures) {
future.get();
}
}
return exitValue;
}
}
SwingWorkerWrapper.java
Wrapper to use the above class in a Swing fashion
package pkg2;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import javax.swing.SwingWorker;
public class SwingWorkerWrapper extends SwingWorker<Integer, Void> {
private ProcessLauncher processLauncher;
public SwingWorkerWrapper(List<String> commands) {
processLauncher = new ProcessLauncher(commands);
processLauncher.addPropertyChangeListener(new LauncherListener());
}
#Override
protected Integer doInBackground() throws Exception {
return processLauncher.call();
}
private class LauncherListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
}
}
}
MainGui.java
GUI class that uses the above SwingWorker. Run this class to get the whole show on the road. Once running, press the "Launch Process" button for this program to run the TestProgram in a separate JVM.
package pkg2;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
import javax.swing.border.Border;
#SuppressWarnings("serial")
public class MainGui extends JPanel {
private static final String[] CMD_TEXT = {"java", "-cp"};
private static final String TEST_PROGRAM = "pkg2.TestProgram";
private JTextArea inputTextArea = new JTextArea(15, 30);
private JTextArea errorTextArea = new JTextArea(15, 30);
private List<String> commands = new ArrayList<>();
public MainGui() {
for (String cmd : CMD_TEXT) {
commands.add(cmd);
}
String classpath = System.getProperty("java.class.path");
commands.add(classpath);
commands.add(TEST_PROGRAM);
inputTextArea.setFocusable(false);
JScrollPane inputScrollPane = new JScrollPane(inputTextArea);
inputScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
Border outsideBorder = BorderFactory.createTitledBorder("Input Messages");
Border border = BorderFactory.createCompoundBorder(outsideBorder, inputScrollPane.getBorder());
inputScrollPane.setBorder(border);
errorTextArea.setFocusable(false);
JScrollPane errorScrollPane = new JScrollPane(errorTextArea);
errorScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
outsideBorder = BorderFactory.createTitledBorder("Error Messages");
border = BorderFactory.createCompoundBorder(outsideBorder, errorScrollPane.getBorder());
errorScrollPane.setBorder(border);
JPanel twoAreasPanel = new JPanel(new GridLayout(1, 0, 3, 3));
twoAreasPanel.add(inputScrollPane);
twoAreasPanel.add(errorScrollPane);
JPanel btnPanel = new JPanel(new GridLayout(1, 0, 3, 3));
btnPanel.add(new JButton(new LaunchProcessAction()));
btnPanel.add(new JButton(new ExitAction()));
setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
setLayout(new BorderLayout(3, 3));
add(twoAreasPanel, BorderLayout.CENTER);
add(btnPanel, BorderLayout.PAGE_END);
}
private class SwWrapperListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
SwingWorkerWrapper swW = (SwingWorkerWrapper) evt.getSource();
try {
int exitCode = swW.get();
inputTextArea.append("Exit Code: " + exitCode + "\n");
} catch (InterruptedException e) {
e.printStackTrace();
inputTextArea.append(e.getLocalizedMessage());
inputTextArea.append("\n");
} catch (ExecutionException e) {
e.printStackTrace();
inputTextArea.append(e.getLocalizedMessage());
inputTextArea.append("\n");
}
} else if (GobblerType.OUTPUT.toString().equals(evt.getPropertyName())) {
inputTextArea.append(evt.getNewValue() + "\n");
} else if (GobblerType.ERROR.toString().equals(evt.getPropertyName())) {
errorTextArea.append(evt.getNewValue() + "\n");
}
}
}
private class LaunchProcessAction extends MyAction {
public LaunchProcessAction() {
super("Launch Process", KeyEvent.VK_L);
}
#Override
public void actionPerformed(ActionEvent e) {
SwingWorkerWrapper swWrapper = new SwingWorkerWrapper(commands);
swWrapper.addPropertyChangeListener(new SwWrapperListener());
swWrapper.execute();
}
}
private class ExitAction extends MyAction {
public ExitAction() {
super("Exit", KeyEvent.VK_X);
}
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
private static abstract class MyAction extends AbstractAction {
public MyAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
}
private static void createAndShowGui() {
MainGui mainPanel = new MainGui();
JFrame frame = new JFrame("Main GUI");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
TestProgram.java
Don't run this program directly, but rather have the Main GUI run this. Be sure that this code and all the code is compiled however
package pkg2;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class TestProgram extends JPanel {
private JTextField textField = new JTextField(20);
private JSpinner exitCodeSpinner = new JSpinner(new SpinnerNumberModel(0, -10, 10, 1));
public TestProgram() {
SendTextAction sendTextAxn = new SendTextAction();
textField.setAction(sendTextAxn);
JPanel panel1 = new JPanel();
panel1.add(textField);
panel1.add(new JButton(sendTextAxn));
JPanel panel2 = new JPanel();
panel2.add(new JLabel("Exit Code:"));
panel2.add(exitCodeSpinner);
panel2.add(new JButton(new ExitCodeAction()));
panel2.add(new JButton(new ThrowExceptionAction()));
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
add(panel1);
add(panel2);
}
private static abstract class MyAction extends AbstractAction {
public MyAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
}
private class SendTextAction extends MyAction {
public SendTextAction() {
super("Send Text", KeyEvent.VK_S);
}
#Override
public void actionPerformed(ActionEvent e) {
String text = textField.getText();
textField.setText("");
System.out.println(text);
}
}
private class ExitCodeAction extends MyAction {
public ExitCodeAction() {
super("Exit Code", KeyEvent.VK_X);
}
#Override
public void actionPerformed(ActionEvent e) {
int exitCode = (int) exitCodeSpinner.getValue();
System.exit(exitCode);
}
}
private class ThrowExceptionAction extends MyAction {
public ThrowExceptionAction() {
super("Throw Exception", KeyEvent.VK_T);
}
#Override
public void actionPerformed(ActionEvent e) {
// throw some unchecked exception
throw new NumberFormatException("Unchecked exception thrown from within TestProgram");
}
}
private static void createAndShowGui() {
TestProgram mainPanel = new TestProgram();
JFrame frame = new JFrame("Test Program");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}

issue in sending the socket output to GUI

I wrote this simple multi threaded chatroom, and I am trying to send the client/server output to GUI to display it in chatroom text area but I get null pointer exception at the following line:
output.write(line + "\n");
here is the full code for GUI:
import java.awt.*;
import javax.swing.*;
import javax.swing.JTextField;
import javax.swing.JFrame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import javax.swing.JButton;
import java.io.Writer;
public class GUI {
private JFrame frame;
private JButton btnSend, btnConnect;
private JTextArea txtChat;
private JTextField fldText, fldName;
private JList clientList;
private DefaultListModel listModel;
private JScrollPane sc, scClients;
private JPanel jpS2All, jpS2Client, jpS2Text;
private String Name;
private JLabel lblErr;
private Writer output;
public GUI(String Name, Writer output) {
this.Name = Name;
this.output = output;
}
public GUI() {
}
class handler implements ActionListener, MouseListener {
handler(String Name) {
}
handler() {
}
#Override
public void actionPerformed(ActionEvent e) {
clients(); //it seems this line made the error because it creates the
listModel.addElement(Name);//gui and sends the output to textSend actionlistener
//to display it in gui
//while the output is empty, right?
//is there any way to handle this?
}
#Override
public void mouseClicked(MouseEvent e) {
fldName.setText("");
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
} //end of handler
class textSend implements ActionListener {
textSend(String Name, Writer output) {
}
#Override
public void actionPerformed(ActionEvent e) {
String line = fldText.getText();
try {
output.write(line + "\n"); // the null exception error shows the
output.flush(); // error source at this line!
} catch (IOException ioe) {
txtChat.append("Other party hung up!");
}
String contenet = Name + ":" + output;
txtChat.append(contenet);
fldText.setText("");
}
}//end of textSend
public void creatServer() {
frame = new JFrame("enter");
frame.setBounds(50, 50, 300, 200);
btnConnect = new JButton("connect");
lblErr = new JLabel();
lblErr.setText("");
frame.add(btnConnect, BorderLayout.EAST);
fldName = new JTextField();
fldName.setText("enter your name");
fldName.addMouseListener(new handler());
btnConnect.addActionListener(new handler(getName()));
frame.add(fldName, BorderLayout.CENTER);
frame.setVisible(true);
}
public void clients() { //to create the chatroom GUI
frame = new JFrame("friends");
frame.setBounds(100, 100, 400, 400);
jpS2All = new JPanel();
txtChat = new JTextArea();
txtChat.setRows(25);
txtChat.setColumns(25);
txtChat.setEditable(false);
sc = new JScrollPane(txtChat);
jpS2All.add(sc);
frame.add(jpS2All, BorderLayout.WEST);
jpS2Text = new JPanel();
////////////////////////
fldText = new JTextField();
fldText.setColumns(34);
fldText.setHorizontalAlignment(JTextField.RIGHT);
fldText.addActionListener(new textSend(getName(), output));
jpS2Text.add(fldText);
frame.add(jpS2Text, BorderLayout.SOUTH);
/////////
jpS2Client = new JPanel();
listModel = new DefaultListModel();
clientList = new JList(listModel);
clientList.setFixedCellHeight(14);
clientList.setFixedCellWidth(100);
scClients = new JScrollPane(clientList);
frame.add(jpS2Client.add(scClients), BorderLayout.EAST);
/////////
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.pack();
}//end of clients
public String getName() {
Name = fldName.getText();
return Name;
}
public void appendText(final String message) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
txtChat.append(message);
}
});
}
}
server code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
public class server {
public void start() throws IOException {
ServerSocket serverSocket = new ServerSocket(1234);
while (true) {
Socket socket = serverSocket.accept();
ClientThread t = new ClientThread(socket);
t.start();
}
}
public static void main(String[] args) throws IOException {
server server = new server();
server.start();
}
class ClientThread extends Thread {
Socket socket;
InputStream sInput;
OutputStream sOutput;
GUI gui = new GUI();
String Name;
ClientThread(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
BufferedReader sInput
= new BufferedReader(new InputStreamReader(socket.getInputStream()));
Writer sOutput = new OutputStreamWriter(socket.getOutputStream());
Name = gui.getName();
gui = new GUI(Name, sOutput);
try {
String line;
while ((line = sInput.readLine()) != null) {
gui.appendText(line);
}
} catch (IOException ex) {
Logger.getLogger(client.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (IOException e) {
}
}
}
}
client side:
import java.net.*;
import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class client {
private Socket s;
private String Name;
private GUI gui;
private Writer output;
private BufferedReader input;
public void start() {
try {
s = new Socket("127.0.0.1", 1234);
} catch (IOException ex) {
}
try {
input = new BufferedReader(new InputStreamReader(s.getInputStream()));
output = new OutputStreamWriter(s.getOutputStream());
} catch (IOException eIO) {
}
Name = gui.getName();
new GUI(Name, output);
new ListenFromServer().start();
}
public static void main(String[] args) {
client cl = new client();
GUI gui = new GUI();
gui.creatServer();
}
class ListenFromServer extends Thread {
public void run() {
try {
String line;
while ((line = input.readLine()) != null) {
gui.appendText(line);
}
} catch (IOException ex) {
Logger.getLogger(client.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
I know my question is a bit cumbersome but I really appreciate to help me handle this issue!
I am looking at your code and it is obvious that output is null when you attempt output.write(line + "\n"); Therefore I went and looked for the possible path of execution that could leave output un-initialized. This is where debugging comes in very handy.
Here is your execution path:
In your main method of client you create a new GUI and then call gui.creatServer();
public static void main(String[] args) {
client cl = new client();
GUI gui = new GUI();
gui.creatServer();
}
output has not been assigned and is still null
in the creatServer(); method you have this line:
fldName.addMouseListener(new handler());
which the actionPerformed method of handler calls the clients(); method which has the line:
fldText.addActionListener(new textSend(getName(), output));
note output is still null
(now your textSend class doesn't even do anything inside the constructor but that aside even if it did you are still using the output variable from the GUI class)
you have the actionPerformed method in the textSend class that has the line:
output.write(line + "\n");
Without ever initializing output it is still null, which gives you the NullPointer
Please see What is a NullPointerException, and how do I fix it? as #markspace linked in the comments. In addition you should really learn how to debug small programs.
See the following links:
http://ericlippert.com/2014/03/05/how-to-debug-small-programs/
http://blogs.msdn.com/b/smallbasic/archive/2012/10/09/how-to-debug-small-basic-programs.aspx
Again in addition, consider using Anonymous classes to ease up on those lines of code, which also makes the code easier to debug and more readable.
One last thought, remember to use standard Naming Conventions for the language you are using. your code currently has a lot of incorrect lowercase classes and some uppercase methods/properties.
the error message shows that one of the variable used in the expression was null. This may be either output or line.
As chancea already mentioned, you are calling the GUI() constructor with no arguments, so the output field is not initialized. You should remove the constructor with no arguments when you have no way to initialize the output field in it and only leave the one with arguments.

chat app: it freezes when creating a new socket

I have created a short java chat app. 3 classes: the GUI, the server and the client.
The gui has its own getters so that they are talked to by the objects of the other classes.
When I try to create the socket, it first popped me up the Firewall saying that it had blocked an app from trying to open a port in my computer, alright, I clicked on "allow app" and I further even expressly put it on the list of allowed apps of Firewall. The problem now is that when I click on the Menu to create the socket, it Freezes the app completely and you can't do anything but abort it.
The app, of course,is based on Threads, and every time I wanto to create a socket such as when I click on the menu item
if(ae.getSource() == servertalkstogui.getCreate()){
it then starts a Thread that is run at its Run method. But at that point it freezes. I dont know if I am on an infinite loop or what. Also, I dont like using a "sleep" in a Loop, but so far I dont know any other alternative, but the most important thing is to detect the bug that freezes the App
package backend;
import frontend.Gui;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* #author Alvarito
*/
public class Server implements ActionListener, Runnable {
private ServerSocket ss;
private Socket s;
private ObjectOutputStream oos;
private ObjectInputStream ois;
private Gui servertalkstogui;
public Server(Gui in) {
servertalkstogui = in;
}
#Override
public void actionPerformed(ActionEvent ae) {
if (ae.getSource() == servertalkstogui.getCreate()) {
servertalkstogui.getAreachat().append("hola");
System.out.println("creado");
Thread t = new Thread(this);
t.run();
}
if (ae.getSource() == servertalkstogui.getButton()) {
String linea = servertalkstogui.getTextField().getText();
writeLine(linea);
}
}
#Override
public void run() {
try {
ss = new ServerSocket(9999);
s = ss.accept();
oos = new ObjectOutputStream(s.getOutputStream());
ois = new ObjectInputStream(s.getInputStream());
}
catch (IOException e) {
try {
this.closeServer();
}
catch (IOException ex) {
System.out.println("se jodio");
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
e.getLocalizedMessage();
}
}
public void writeLine(String linea) {
try {
oos.writeObject(linea);
servertalkstogui.getAreachat().append(linea);
}
catch (IOException e) {
e.getLocalizedMessage();
}
}
public void readLine() throws InterruptedException {
try {
while (true) {
Object aux = ois.readObject();
if (aux != null && aux instanceof String) {
servertalkstogui.getAreachat().append((String) aux);
}
}
}
catch (IOException | ClassNotFoundException e) {
}
}
public void closeServer() throws IOException {
try {
oos.close();
s.close();
ss.close();
}
catch (Exception e) {
e.addSuppressed(e);
}
}
}
Now the Client class
package backend;
import frontend.Gui;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* #author Alvarito
*/
public class Client implements ActionListener, Runnable {
private Socket s;
private ObjectOutputStream oos;
private ObjectInputStream ois;
private Gui clienttalkstogui;
public Client(Gui in) {
clienttalkstogui = in;
}
#Override
public void actionPerformed(ActionEvent ae) {
if (ae.getSource() == clienttalkstogui.getConnect()) {
Thread t = new Thread(this);
t.run();
clienttalkstogui.getAreachat().append("me he conectado");
System.out.println("hola");
}
}
public void writeLine(String linea) {
try {
oos.writeObject(linea);
clienttalkstogui.getAreachat().append(linea);
}
catch (IOException e) {
e.getLocalizedMessage();
}
}
public void readLine() throws InterruptedException {
try {
while (true) {
Object aux = ois.readObject();
if (aux != null && aux instanceof String) {
clienttalkstogui.getAreachat().append((String) aux);
}
}
}
catch (IOException | ClassNotFoundException e) {
}
}
public void run() {
try {
s = new Socket("localhost", 9999);
oos = new ObjectOutputStream(s.getOutputStream());
ois = new ObjectInputStream(s.getInputStream());
}
catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void close() {
try {
ois.close();
oos.close();
s.close();
}
catch (Exception e) {
e.getLocalizedMessage();
}
}
}
Now the Gui class:
package frontend;
import backend.Client;
import backend.Server;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
/**
*
* #author Alvarito
*/
public class Gui extends JFrame {
private JMenuBar bar;
private JMenu menu;
private JMenuItem connect, create, exit;
private JTextArea areachat;
private JTextField campochat;
private JButton botonchat;
private JScrollPane scroll;
/* WE CREATE INSTANTIATED OBJECTS OF CLASSES INTERACTING WITH THE GUI */
Server servidor = new Server(this);
Client cliente = new Client(this);
/* CREATING THE CONSTRUCTOR */
public Gui() {
super("CHAT WINDOW");
this.setSize(400, 500);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
/* INSTANTIATE THE OBJECTS */
bar = new JMenuBar();
menu = new JMenu("Menu");
connect = new JMenuItem("Conectar");
create = new JMenuItem("Crear");
exit = new JMenuItem("Salir");
areachat = new JTextArea();
campochat = new JTextField(20);
botonchat = new JButton("Send");
scroll = new JScrollPane(areachat);
/* THE BAR IS PLACED IN THE JFRAME WINDOW */
this.setJMenuBar(bar);
/* THE MENU IS ADDED TO THE BAR */
bar.add(menu);
/* THE ITEMS ARE ADDED TO THE MENU */
menu.add(connect);
menu.add(create);
menu.add(exit);
/* MAKE ITEMS LISTEN TO THE EVENT FROM THE CODE CLASSES */
create.addActionListener(servidor);
connect.addActionListener(cliente);
exit.addActionListener(servidor);
exit.addActionListener(cliente);
botonchat.addActionListener(cliente);
botonchat.addActionListener(servidor);
/* CREATING THE LAYOUTS */
/* AREACHAT */
this.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 2;
gbc.gridheight = 1;
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1;
gbc.weighty = 1;
this.add(scroll, gbc);
/* TEXTFIELD */
gbc.gridx = 0;
gbc.gridy = 1;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
gbc.weighty = 0;
this.add(campochat, gbc);
/* BOTON */
gbc.gridx = 1;
gbc.gridy = 1;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.weightx = 0;
gbc.weighty = 0;
this.add(botonchat, gbc);
this.setVisible(true);
}
/* CREATING THE GETTERS AND SETTERS */
/* GETTERS */
public JTextArea getAreachat() {
return areachat;
}
public JMenuItem getCreate() {
return create;
}
public JMenuItem getConnect() {
return connect;
}
public JTextField getTextField() {
return campochat;
}
public JButton getButton() {
return botonchat;
}
/* SETTERS */
public static void main(String [] args) {
Gui objeto = new Gui();
}
}
You should use start() instead of run() in order to start a thread.
Calling run() just call the run method, without starting a thread. And you then block in the ui thread

NullPointException when I try to navigate forms on j2me using buttons

I'm having trouble linking the main page to the second page by the click of a button. It throws a NullPointException. Can someone please tell me where I've erred?
import java.io.InputStream;
import javax.microedition.lcdui.Displayable;
import javax.microedition.midlet.*;
import com.sun.lwuit.*;
import com.sun.lwuit.animations.CommonTransitions;
import com.sun.lwuit.events.ActionEvent;
import com.sun.lwuit.events.ActionListener;
import com.sun.lwuit.layouts.BorderLayout;
import com.sun.lwuit.layouts.BoxLayout;
import com.sun.lwuit.plaf.UIManager;
import com.sun.lwuit.util.Resources;
import java.io.IOException;
public class standings extends MIDlet implements ActionListener{
public Command cmdSelect;
public Form fform, selectLgform;
public Button btnSelectLeague,btnHelp,btnAbout,btnExit;
public TextArea taHome,taAbout, taHelp, taSelectLg;
private InputStream iStream;
private StringBuffer strBuffer;
private Form selectLgForm;
public void startApp() {
Display.init(this);
try {
Resources rs= Resources.open("/restheme.res");
UIManager.getInstance().setThemeProps(rs.getTheme("Theme2"));
} catch (Exception e) {
e.getMessage();
}
displayMainForm();
}
public void displayMainForm()
{
fform = new Form("Football League Standings");
taHome= new TextArea(5,20,TextArea.ANY);
fform.setLayout(new BorderLayout());
fform.setTransitionInAnimator(CommonTransitions.createFade(1000));
iStream = getClass().getResourceAsStream("/intro.txt");
strBuffer = new StringBuffer();
int next = 1;
try {
while((next = iStream.read()) != -1) {
char nextChar = (char) next;
strBuffer.append(nextChar);
}
} catch (IOException ex) {
ex.printStackTrace();
}
taHome.setText(strBuffer.toString());
strBuffer = null;
taHome.setFocusable(false);
taHome.setEditable(false);
taHome.setUIID("Label");
//fform.addComponent(BorderLayout.CENTER,taHome);
btnSelectLeague= (new Button("Select league"));
btnHelp= (new Button("Help"));
btnAbout= (new Button("About"));
btnExit= (new Button("Exit"));
Container mcont = new Container(new BoxLayout(BoxLayout.Y_AXIS));
mcont.addComponent(taHome);
mcont.addComponent(btnSelectLeague);
mcont.addComponent(btnHelp);
mcont.addComponent(btnAbout);
mcont.addComponent(btnExit);
fform.addComponent(BorderLayout.CENTER, mcont);
btnSelectLeague.addActionListener(this);
btnHelp.addActionListener(this);
btnAbout.addActionListener(this);
btnExit.addActionListener(this);
fform.show();
}
/* Command exitCommand = new Command("Exit");
fform.addCommand(exitCommand);
fform.addCommandListener(this);
}
}*/
public void selectLgForm()
{
selectLgForm= new Form("Select League");
taSelectLg= new TextArea(5,20,TextArea.ANY);
selectLgForm.setLayout(new BorderLayout());
selectLgForm.setTransitionInAnimator(CommonTransitions.createFade(1000));
iStream = getClass().getResourceAsStream("/selectlg.txt");
strBuffer = new StringBuffer();
int next = 1;
try {
while((next = iStream.read()) != -1) {
char nextChar = (char) next;
strBuffer.append(nextChar);
}
} catch (IOException ex) {
ex.printStackTrace();
}
taSelectLg.setText(strBuffer.toString());
strBuffer = null;
taSelectLg.setFocusable(false);
taSelectLg.setEditable(false);
taSelectLg.setUIID("Label");
selectLgForm.addComponent(BorderLayout.CENTER,taAbout);
//START OF MENU BUTTONS
selectLgForm.addCommand(new Command("Back")
{
public void actionPerformed(ActionEvent e)
{
displayMainForm();
}
});
selectLgForm.show();
}//END OF MENU BUTTONS
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void actionPerformed(ActionEvent ae) {
if(ae.getSource()==btnSelectLeague){
selectLgForm();
}
my best guesses are:
- selectLgForm.addComponent(BorderLayout.CENTER,taAbout) throws a NullPointerException because taAbout is null.
- or iStream = getClass().getResourceAsStream("/selectlg.txt"); throws a NullPointerException because the text file is not where you think it is.

Categories