So I am trying to do a chat type program using JavaFX for the GUI. I have it so a class that acts as a server will loop and keep adding client connections to it.
public void serverconnection()
{
// portnumber was saved from constructor
try (ServerSocket socket = new ServerSocket(this.portnumber))
{
// loop is a bool set to true
while (loop)
{
// this class extends Thread and has its own overwritten start method
new myclass(socket.accept()).start();
}
}
catch (IOException e)
{
System.exit(404);
}
}
so the problem is (I am assuming) was, this loop keeps looping until the program closes. but since I was calling this within the JavaFX's initialize method
public void initialize(URL url, ResourceBundle rb)
{
// constructor, nothing here is needed for this post
myclass z = new myclass(45234);
// problem here, since this has a loop, but
z.serverconnection();
// gui wont load till after this is done
// but serverconnection is only done after program ends
}
the problem with this is, apparently, the GUI will not load until AFTER initialize has finished, but it will not finish until program closes. After google searching, I could not find any fix for this. I need a way to call a method that will do all this, AFTER initialize method has finished. My client side class is similar to this, but the methods to connect on that are activated on events when clicking a login button. For this serverside one, I am trying to start without any interaction with the user. so is there a way to call a method or make this work AFTER initialize method has ran?
You might want to run this loop in a thread, so do something like
Thread t = new Thread(z::serverconnection)
t.start()
If you do this at the end of your initialization() method, it will run exactly then.
This will start a thread which runs forever; you might want to add a feature for interrupting the thread when the program is supposed to be terminated.
Remember that for changing anything in the GUI you need to sumbit a task via Platform.runLater(). This is because the GUI may only be modified from within that one thread. So in order to modify anything, you have to wrap that in a Runnable and submit it for execution.
You can do that in this way:
Platform.runLater(new Runnable() {
#Override
public void run() {
doWhateverNeedsToBeDone();
}
});
In Java 8, you can do anything of the following, depending on the extent of the work to be done:
Platform.runLater(() -> {
doWhateverNeedsToBeDone();
});
Platform.runLater(() -> doWhateverNeedsToBeDone());
Platform.runLater(this::doWhateverNeedsToBeDone);
The latter only works if doWhateverNeedsToBeDone() is a method of this.
Related
I am using eclipse's jobs API to run big task as a job, once task is completed I am setting boolean variable to true and if that variable is true I am executing WizardDialog in UI thread. My current code looks like this:
Job longRunningJob = new Job("Long running job...") {
#Override
protected IStatus run(IProgressMonitor monitor) {
boolean shouldShowDialog = doLongRunningJob();
if(shouldShowDialog) {
Display.getDefault().asyncExec(new Runnable() {
#Override
public void run() {
//Will open wizard dialog here
WizardDialog wizardDialog = new WizardDialog(Display.getCurrent().getActiveShell(), new TestWizard());
wizardDialog.setBlockOnOpen(true);
wizardDialog.open();
}
});
}
}
}
longRunningJob.setUser(true);
longRunningJob.schedule();
My problem is run inside Display thread not executing in reliable way, means sometime it goes inside run method where as sometimes it doesn't, I tried putting breakpoint inside run method and testing it out but same happens.
My question is, is what I am doing is correct way? Is this expected behaviour? So how do I handle this scenario ie once shouldShowDialog is true how do I execute code inside Display thread?
Edit: One behaviour I observed while debugging is dialog gets displayed but suddenly it get closes, I think it's exiting the thread.
The problem with disappearing dialogs is most commonly caused by using currently active Shell as the parent for the dialog. E.g. if there is a ProgressDialog open when you create your dialog then that other dialog will be the parent of your dialog. And when the other dialog closes, so does yours.
Instead, use something like:
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
I have developed an applet and I am using a JSP to upload it. I have worked it using Netbeans 6.9. The applet works fine without JSP. When I run JSP on Glassfish server, applet does not run.
My applet takes 43 seconds to do processing and get displayed, I think this may be the problem.
When I run the same JSP with the same applet but with slight modification, applet runs correctly with JSP. Modification is that I comment out a function call (called from init() method) which is responsible for large execution time. The long running method reads three files and generates the output in the choice buttons, i.e. generates the choices.
But I need that function in my applet, that is very important function.
Every catch statement has a printstacktrace() method call in it.
public void start(){
initialise_maps();
}
public void init() {
try {
java.awt.EventQueue.invokeAndWait(new Runnable()
{
public void run() {
initComponents();
}
});
} catch (Exception ex)
{
ex.printStackTrace();
}
// initialise_maps();
}
Modification is that I comment out a function call (called from init() method) which is responsible for large execution time.
It seems it will be necessary to refactor that method call to the start() method, or do it in a separate Thread (e.g. using a SwingWorker).
The long running method reads three files and generates the output in the choice buttons, i.e. generates the choices.
Add the choice boxes in the init() method, but populate them in the start() method (if not already done - the start method is called every time the browser is restored from minimized, as well as directly after init()).
public class Test {
public void buildGUI()
{
JFrame frame = new JFrame();
JButton send = new JButton("Send");
send.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
send();
frame.dispose();
}
});
frame.add(send);
frame.pack();
frame.setVisible(true);
}
}
if the method send() throws MyException how would I have that exception migrate its way out of the Swing thread to my class?
What I want to do with the Exception that's generated is have another class that instantiates it catch the exception like so.
public class AnotherTest
{
public AnotherTest()
{
Test t = new Test();
try
{
t.buildGUI();
}
catch(MyException e)
{
//do stuff.
}
}
}
That's what I want to happen conceptually, however I know that buildGUI will end before actionPerformed is ever called. So, how would I catch the potential exception in actionPerformed in AnotherTest?
A class may not thow an exception. Only methods can.
And a class isn't something that can be executed. A method can be executed.
And what executes the action listener method is the Swing event dispatch thread. The only thing you can do if some method throws an exception in a listener is to catch it and display it somehow : by opening an error dialog box, or putting the exception message in a text area, or anything.
public void actionPerformed(ActionEvent e) {
try {
send();
}
catch (MyException e) {
someTextArea.setText(e.getMessage());
}
}
If you in fact want to communicate from the Swing EDT with the main thread, you could use a BlockingQueue, and have the main thread call take on the queue and the listener offer the exception to the queue.
Any other thread communication mechanism would do. But make sure not to block the EDT, or the whole GUI will freeze.
A class cannot throw an exception, only methods can so the very first line is a mistake. Second thing, you can surround send() with try...catch() block to handle that exception in which you can either take some error recovery action or display an error message or something like that and that would still serve your purpose.
Well, why just don't do it? And instead make send() call some other thread where your logic runs? And if that thread encounters exception, you can handle it there.
There's no way to throw exception across thread boundaries. You can make send() pass info about occurred exception to outer world by setting some outer flag, which is visible to other threads of your app.
Swing isn't Thread safe, then idea to build Swing GUI inside try - catch - finally block is more that contraproductive, you have to preparing all us-safe code blocks separatelly
1) I'm starting with very bad way -> your idea must be wrapped into invokeLater(), if is there hard and long running Stream, File I/O, DB Conenction then to try wrap that into invokAndWait()
but you loading these data from some GUI that there exist, you have lots of time for
2) prepare and load data (Stream, File I/O, DB Conenction) before you needed them, then to put these Object to the GUI, when you needed (would be wrapped into invokeLater)
3) create GUI (would be wrapped into invokeLater), show this Container, then load data (Stream, File I/O, DB Conenction) if with success, then add a show these data in the GUI
3) create GUI (would be wrapped into invokeLater), show this Container, load data only for one of JComponents, if with success, then show this JComponent, same for 2nd. and so on ...
for all three options is required to redirect (Stream, File I/O, DB Conenction) load these data, value for JComponent(s), to the Background Task(s), you have two correct ways how to do it,
by using
Runnable#Thread
SwingWorker
I have a button in my program that, when pressed, is supposed to take you to my wiki page about the program. I used the following line to do so:
java.awt.Desktop.getDesktop().browse(new java.net.URI("http://supuh.wikia.com/wiki/BHT"));
The problem is that, no matter what environment in which the program is run, I always get the following error:
java.security.AccessControlException: access denied (java.awt.AWTPermission showWindowWithoutWarningBanner)
does anyone know how I can fix this? Note that this only works in the one program. Any other program I make can use the same method with no problem.
Exit hook
At the start of my program, this hook is added. The program runs fine without it...
System.setSecurityManager(new SecurityManager()
{
#Override
public void checkExit(int status)
{
closeFile(status);
}
});
this hook is needed, but the browse(URI uri) method in question won't work with it. Solutions?
This means you are running with a security manager:
SecurityException - if a security manager exists and it denies the AWTPermission("showWindowWithoutWarningBanner") permission, or the calling thread is not allowed to create a subprocess; and not invoked from within an applet or Java Web Started application
If this is an applet, or a Java Web Start app - sign your jar.
Update Adding a security manager to detect program exit is wrong. There are multiple ways to do this properly. In your case I guess this would be most appropriate:
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
#Override
public void run() {
closeFile();
}
));
Swing-specific solutions are:
if you don't have to perform extra actions, use frame.setDefaultCloseAction(Frame.EXIT_ON_CLOSE)
use addWindowStateListener and check for WindowEvent.WINDOW_CLOSED
That said, two notes:
you must not hold files open for a long time. Use try/catch/finally to open and close them whenever they are needed.
if you really need a security manager at some point, make sure you override the appropriate method of the SecurityManager that checks whether you can open the link. (won't tell you which one, so that you are not tempted to jump onto this solution, which is wrong)
To summarize, I'd go for setDefaultActionOnClose, and close each file right after I finish reading/writing it.
Update 2: After you linked to your original question describing what exactly are you trying to achieve, things change a bit. You are trying to prevent exit, so you do need a SecurityManager. This makes it so that you should override the checkPermission method and do nothing there (i.e. don't throw exceptions), at least when these permissions are checked (they are checked when browse is called):
new AWTPermission("showWindowWithoutWarningBanner")
new FilePermission("<<ALL FILES>>", SecurityConstants.FILE_EXECUTE_ACTION)
Update 3 Here's how exactly to override the method:
#Override
public void checkPermission(Permission permission) {
if (permission instanceof AWTPermission) {
if (permission.getName().equals("showWindowWithoutWarningBanner")) {
return;
}
}
if (permission instanceof FilePermission) {
if (permission.getActions().equalsIgnoreCase("execute")) {
return;
}
}
java.security.AccessController.checkPermission(permission);
}
(you can go without the outer if-s)
Update 4 The above method will work only if you have given permissions to your program. Otherwise it is a not-well documented behaviour of the JVM that overriding security managers are not allowed to be unprivileged. Take a look at this report - the comments say how to work it around.
To make your life simpler, you can simply #Override public void checkPermission(..) with an empty method body.
Instead of using your own SecurityManager, install a shutdown hook instead:
Runnable runnable = new Runnable() {
closeFile(status);
}
Runtime.getRuntime().addShutdownHook(new Thread (runnable, "Close file"));
I have an applet that calls a JDialog that contains a JProgressBar component. I subclass the JDialog to expose a method to update the JProgressBar, something like:
public class ProgressDialog extends javax.swing.JDialog {
public void setProgress(double progress) {
jProgressBar1.setValue(jProgressBar1.getMinimum() + (int) (progress * jProgressBar1.getMaximum()));
}
...
}
I use this dialog in the following manner:
public void test() throws Exception {
progressDialog = new ProgressDialog(null, true);
try {
progressDialog.setLocationRelativeTo(null);
// show the dialog
EventQueue.invokeLater(new Runnable() {
public void run() {
progressDialog.setVisible(true);
}
});
// business logic code that calls progressDialog.setProgress along the way
doStuff();
} finally {
progressDialog.setVisible(false);
progressDialog.dispose();
}
}
It works fine on Windows/any browser. However, when invoking the above function on Firefox 2/3/3.5 on a Mac, the progressDialog is displayed indefinitely, i.e. it doesn't close.
I suspected that calling setVisible(true) inside the EventQueue was causing the problem, since it's a blocking call and might block the queue completely, so I tried changing it to:
// show the dialog
new Thread() {
public void run() {
progressDialog.setVisible(true);
}
}.start();
With this change, the progressDialog now closes correctly, but a new problem emerged - the contents of the dialog (which included the progressbar, an icon and a JLabel used to show a message string) were no longer shown inside the dialog. It was still a problem only on Mac Firefox.
Any ideas? I realize it's probably some AWT threading issue, but I've been at this for a couple of days and can't find a good solution. Wrapping the doStuff() business logic in a separate new Thread seems to work, but it's not easy to refactor the actual business logic code into a separate thread, so I'm hoping there's a simpler solution.
The envt is:
Mac OSX 10.5
Java 1.5
Firefox 2/3/3.5
Found out that the problem was that the applet function was executing inside the AWT dispatcher thread, therefore the thread blocks and no events are processed until the applet function finishes execution.
Solution was to move the processing logic into a separate thread spawned by the ProgressDialog object before calling setVisible(true). setVisible(true) would block the main thread but still allow the event dispatcher to continue processing, hence rendering the contents of the dialog until the spawned thread calls setVisible(false) to hide the dialog.