Search code examples
javaipojo

Sleep a iPOJO component, all disable


I have a simple question relating to iPOJO.

When a component iPOJO sleeps, all remaining components will also disable although there are not dependencies between them. Why? Here's an example:

Component 1:

@Component(name="frame1", immediate=true)
@Instantiate(name="iframe1")
public class Frame1 implements Runnable{

    String str;
    Label lb = new Label();
    TextField tf = new TextField();
    Frame fr;
public void run() {
    fr = new Frame("Frame1");
    fr.setLayout(new BorderLayout());
    fr.setSize(230, 200);
    fr.setLocation(900,250);
    fr.add(tf, BorderLayout.NORTH);
    lb.setText("Result");
    fr.add(lb, BorderLayout.CENTER);
    Panel pn = new Panel();
    fr.add(pn, BorderLayout.SOUTH);
    pn.setLayout(new GridLayout(1,4,1,1));
    Button bt = new Button("Printer 1");
    pn.add(bt);
    bt.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            try {
                System.out.println("start sleep");
                Thread.sleep(5000);
                System.out.println("stop sleep");
            } catch (InterruptedException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        }

    });

    fr.setVisible(true);
 }
 @Validate
 public void start() {
     //this.delayService = dls;
     Thread th = new Thread(this);
     th.start();
 }
 @Invalidate
 public void stop() {
     System.out.println("stop");
     fr.setVisible(false);
 }
}    

Component 2:

@Component(name="frame2", immediate=true)
@Instantiate(name="iframe2")
public class Frame2 implements Runnable{

String str;
Label lb = new Label();
TextField tf = new TextField();
Frame fr;
public void run() {
    System.out.println("start component 2");
    fr = new Frame("Frame2");
    fr.setLayout(new BorderLayout());
    fr.setSize(230, 200);
    fr.setLocation(900,250);
    fr.add(tf, BorderLayout.NORTH);
    lb.setText("Result");
    fr.add(lb, BorderLayout.CENTER);

    Panel pn = new Panel();
    fr.add(pn, BorderLayout.SOUTH);
    pn.setLayout(new GridLayout(1,4,1,1));
    Button bt = new Button("Printer 2");
    pn.add(bt);
    bt.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("in 2");
        }
    });

    fr.setVisible(true);
}
@Validate
 public void start() throws Exception {
     //this.delayService = dls;
     System.out.println("start thread 2");
     Thread th = new Thread(this);
     th.start();

     //fr.setVisible(true);
 }
 @Invalidate
 public void stop() throws Exception {
     System.out.println("stop");
     fr.setVisible(false);
 }
}

Two components are deployed and running. There are two independent components. But I click the "Printer 1" button. "frame1" component is sleeping during 5s. And during these 5 seconds, i can't click "Printer 2" of "frame2" component.


Solution

  • This is not an ipojo issue. Swing uses one thread (and only one thread) in order to dispatch events such as clicks. When you click your first button, swing runs your actionPerformed in this thread. This method puts your thread to sleep for 5 seconds. This means that the thread responsible for event handling cannot do anything during this time. This is why your program does not respond to your second click.

    Whenever you have a long computation in swing (and also osgi), it is often a good idea to run your code in a separate thread in order to avoid blocking the execution (here you have a useless Thread.sleep() but I guess you could have an http request or anything that may take a long time instead). You should probably use an executor service or anything similar.