开发者

lazy-init="true". What does it do?Why I can not get a Spring bean from a Swing app without lazy-init set to true?

开发者 https://www.devze.com 2023-04-11 15:08 出处:网络
I have an application that in the back-end deploys a lightweight HTTP server (Jetty). The servle开发者_高级运维ts basically update a MySQL database.

I have an application that in the back-end deploys a lightweight HTTP server (Jetty).

The servle开发者_高级运维ts basically update a MySQL database.

I have wired everything using Spring.

So far ok.

I have a UI that I want to use to interact with the server.

If the UI runs locally I want it to display in a JTree the currently logged-in users.

So I decided to start the server i.e. start Spring when launching the main frame.

On top of that, in order to update the UI's JTree to show all the logged-in users I thought to use the Observer-Observable and have the code that accepts connections be an Observable.

A ConnectionListener would be notified of incoming connections storing them in an ArrayBlockingQueue and background thread (having a reference to the DefaultMutableTreeNode root) of the Jtree would update it -in the EDT thread of course via SwingUtilities.

My problem is the following:

If I do:

  public class AdminFrame extends JFrame {
      public static ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("myBeans");    

public static void main(String[] args){    
      EventQueue.invokeLater(new Runnable() {
                public void run() {
        //Show GUI
         }
        }
    }

The GUI is not drawn but I can understand that since once Spring start and the server starts the thread does not return.

So I start Spring in a back-end thread as follows:

public class ServerThread extends Thread {  
    @Override
    public void run() {  
    ClassPathXmlApplicationContext ctx = ApplicationCtx.getApplicationCtx();  
    }  
}

and

public class ApplicationCtx {  

  private static ClassPathXmlApplicationContext ctx;
  private ApplicationCtx(){}
  public static synchronized ClassPathXmlApplicationContext getApplicationCtx(){  
    if(ctx == null){  
    ctx = new ClassPathXmlApplicationContext("myBeans.xml");  
    }  
    return ctx;  
}  

}

The GUI now shows up and seems ok BUT I am missing the notification.

PROBLEM:

It is not possible to get notification for the new connections:

1) If I register for notification as follows:

public class AdminFrame extends JFrame {  
    public static void main(String[] args) {  
       ServerThread lightweightServer = new ServerThread();  
       lightweightServer.start();
       Thread.sleep(9000);//Temporary solution to make sure the server is started up before GUI
        ConnectHandler connectHandler = (ConnectHandler) ApplicationContext.getApplicationCtx().getBean("connectHandler");
        connectHandler.addObserver(new ConnectionListener());  
        EventQueue.invokeLater(new Runnable() {  
        public void run() {  
              //SHOW GUI
              }  
         }

The GUI never shows up. If I remove the line:

 ConnectHandler connectHandler = (ConnectHandler) ApplicationContext.getApplicationCtx().getBean("connectHandler");  

The GUI shows up.

2) If I register inside the EDT i.e. inside the constructor of AdminFrame the GUI does not show up either.

I.e.

public class AdminFrame extends JFrame {  
    public static void main(String[] args) {  
       ServerThread lightweightServer = new ServerThread();  
       lightweightServer.start();
       Thread.sleep(9000);//Temporary solution to make sure the server is started up before 
       EventQueue.invokeLater(new Runnable() {
            public void run() {

       AdminFrame frame = new AdminFrame();  
       //Other code

       }

Again if I remove the following line the GUI shows up but this way I can not register to get notifications:

 ConnectHandler connectHandler = (ConnectHandler) ApplicationContext.getApplicationCtx().getBean("connectHandler");  

This must be a thread issue but I can not understand what is the problem.

Why is the second call to Spring application context to get the ConnectHandler make the thread not return?

What am I doing wrong here?


UPDATE:

The problem is solved if I add in the Spring configuration file the attribute lazy-init="true" to the bean that starts the Jetty server.

But I can not understand why it solves it or what is the problem.

Thanks


  • Serializable or Observate required wraping GUI rellated code into (in most cases) invokeAndWait()

  • output from SwingWorker (since is guaranteed but I saw some cases that not works as I expecting) or Runnable#Thread required raping GUI rellated code into invokeLater()

  • you can prepare your GUI (then there EDT exists) before, and visibility

.

JFrame#pack(); 
JFrame#setVisible(true);

.

for this Container you have to invoke inside invokeXxx(); or best would be from javax.swing.Action()


If setting up lazy-init to true solve your problem, i think its not solved completely.

By default, all beans initialized at startup so you get the problem in starting if any of the bean is not initialized correctly.

If you set it to false, bean will not be invoked and you will not face any isssue. So the problem is not solved but deferred.

0

精彩评论

暂无评论...
验证码 换一张
取 消