3

I had a problem that I posted before but got no clear solution

How to prevent JFrame from closing.

So I am posting a SSCCE may be this might help in better understanding the problem being faced

package myApp;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.swing.JFrame;

import App2.Applic2;

public class MYApp {

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static void main(String arg[]){
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setTitle("Application frame 1");
        f.setSize(200,200);
        f.setVisible(true);
        Class cls = Applic2.class;
        Object[] actuals = { new String[] { "" } };


        Method m = null;
        try {
            m=cls.getMethod("main", new Class[] { String[].class } );
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
            try {
                m.invoke(null,actuals);
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    }

}

second package

package App2;

import javax.swing.JFrame;

public class Applic2  {

    @SuppressWarnings("unused")
    public static void main(String args[]){

        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(200,200);
        f.setVisible(true);
        f.setTitle("This needs not to be changed");
        NewFrame3 Frame3 = new  NewFrame3();
    }

}

Second class of App2 package.

package App2;

import javax.swing.JFrame;

public class NewFrame3 {

    public NewFrame3(){

        JFrame f = new JFrame();
            f.setTitle("f3");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setSize(200,200);
            f.setLocation(200, 200);
            f.setVisible(true);
    }

}

MYAPP invokes instance of Applic2 which further invokes instance of NewFrame3. Like we can see if I close instance of 'NewFrame3' or instance of Applic2 the entire program closes (due to EXIT_ON_CLOSE) statement.

I want a solution in which MYAPP should not close on closing Applic2 or NewFrame3.

I cannot make any changes to APPlic2 or NewFrame3. via reflection If we try to turn EXIT_ON_CLOSE to DISPOSE_ON_CLOSE How do we access these frames and their setDefaultCloseOperation() when we do not have our classes extended JFrames ?

In another solution as mentioned a new JVM instance should be created and Applic2 should be executed in a new process on this new JVM instance. but then I encountered that runtime.exec takes Java commands as input and not Java statements like method.invoke().

I have access to the Applic2 via loader that loaded Applic2 I can only access the class files of Applic2 in memory so no way I can use jar to run in runtime.exec(). Now how do I solve it?

Adding these statements to MYApp classensures that on clicking close button of a frame nothing happens but this does not seem the be the case

Frame[] f2 = JFrame.getFrames();

            for(Frame fx: f2){
                System.out.println(fx.getTitle());
                fx.addWindowListener(new WindowAdapter(){
                      public void windowClosing(WindowEvent we){


                      }
                      });

and this code needs to be added to the last frame that was instantiated else it does returns all frames. i.e, if this frame is added to JFrame3 class all instantiated frames are returned if added to MyApp JFrame in MyApp is returned and if added Applic2 then frames instantiated in MYApp and Applic2 are returned. Why this behaviour ??

Community
  • 1
  • 1
Sanyam Goel
  • 2,138
  • 22
  • 40

3 Answers3

2

You could use JFrame.getFrames() which returns an array of Frame (you could also getWindows() for a much lower level list of those windows created within the current application context).

Then, you need to walk through, checking each frame to see if it meets your requirements. After, that, you don't need reflection, you gain direct access to the frames

The only only way to communicate with other JVM's is via socket comms (such as RMI).

UPDATE WITH EXAMPLE

Frame[] listOfFrames = JFrame.getFrames();
for (Frame : listOfFrames) {
  if (frame instanceof JFrame) {

      JFrame aFrame = (JFrame)frame;

  }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • +1 for your answer This solution seems to be helpful let me implement it and post the answer here thnak you. But how to do it other way using new JVM instance can you suggest. – Sanyam Goel Jul 20 '12 at 05:24
  • How do you mean other JVM? Do you want to talk to it (cross process communications) or execute it?? – MadProgrammer Jul 20 '12 at 05:29
  • Yes exactly !! cross process communications. A new process to execute the application – Sanyam Goel Jul 20 '12 at 05:35
  • but getFrames() returns awt frames and how do I change DefaultCloseOperation of these frames ( awt frame does not have any such method ) – Sanyam Goel Jul 20 '12 at 06:06
  • JFrame extends from java.awt.Frame, you should check to see if the frame is an instanceof JFrame and then cast it – MadProgrammer Jul 20 '12 at 06:38
  • Casting produces an error as follows : ---> Exception in thread "main" java.lang.ClassCastException: [Ljava.awt.Frame; cannot be cast to [Ljavax.swing.JFrame; at myApp.MYApp.main(MYApp.java:48) – Sanyam Goel Jul 20 '12 at 06:42
  • That's because you're trying to cast an array of Frames. See my updated example ;) – MadProgrammer Jul 20 '12 at 06:45
1

Cross Process Communications is not a simple thing. Basically, each process you want to talk to needs to have a ServerSocket with which it can accept incoming requests. If you want to perform two way communication, each process would need to have it's own ServerSocket, this will allow ANY process to start the communications.

This raises issues with port numbers and the like, but you could actually do a muticast to over come that (basically, "hay everybody, I'm here, come talk to me") which could be used to determine who's available or not - take a look at Broadcasting to Multiple Recipients for an example.

So. When you're ready, you would open a socket connection to the process in question (localhost/127.0.0.1) on it's port and start chatting.

Now. The problem I see with what you've described, is the fact that in order to get this to run, you're going to need some kind of launcher that can create the server socket and then execute the existing program (as you've already described), which raises the question of why? If you're only goal is to get these frames to stop closing your application, simply launching the program in a new JVM achieves that goal. Obviously, if you still need more information from them, then that's a reasonable excuse for all the hard work.

Now, the good news, you can serialize objects across sockets (that is, you can send Java objects via the socket connection), check Discover the secrets of the Java Serialization API for more info.

Now, if that hasn't scared you off, check out All About Sockets for more information.

And finally, the big question of "how" to execute a new JVM, check out Java ProcessBuilder, it actually describes a means by which you can execute a new JVM!!

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
1

So have completed the solution with the help provided by MadProgrammer amd mKorbel and here is the updated MYApp class

package myApp;

import java.awt.Frame;
import java.awt.Window;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.swing.JFrame;

import App2.Applic2;

public class MYApp {

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static void main(String arg[]){
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setTitle("Application frame 1");
        f.setSize(200,200);
        f.setVisible(true);
        Class cls = Applic2.class;
        Object[] actuals = { new String[] { "" } };




        Method m = null;
        try {
            m=cls.getMethod("main", new Class[] { String[].class } );


            Method[] m1  =Frame.class.getDeclaredMethods();







        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
            try {
                m.invoke(null,actuals);
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }


            Frame[] f2 = JFrame.getFrames();
            //  Window[] f23=  JFrame.getFrames();

                for(Frame fx: f2){
                    System.out.println(fx.getTitle());
                    //  fx.setVisible(false);

                      if (fx instanceof JFrame) {

                          JFrame aFrame = (JFrame)fx;
                          aFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

                      }
                    }

    }

}
Sanyam Goel
  • 2,138
  • 22
  • 40