Download NetBeans!

20080422 Tuesday April 22, 2008

Converting Spring to Lookup

In the screenshot below, the content of the "Spring Window" is injected via a Spring configuration file:

The highlighted classes above are the Swing components and behavior that Spring injects into the TopComponent (except for 'SpringAction', which opens the window). In the editor area above, the following constructor is shown:

private SpringTopComponent() {

    initComponents();

    setName(NbBundle.getMessage(SpringTopComponent.class, "CTL_SpringTopComponent"));
    setToolTipText(NbBundle.getMessage(SpringTopComponent.class, "HINT_SpringTopComponent"));

    String[] contextPaths = new String[]{"org/netbeans/nbspringdemo/app-context.xml"};
    ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(contextPaths);

    Lookup lookup = NbSpring.create(ctx);
    Item item = lookup.lookupItem(new Template(JPanel.class, null, null));
    JPanel foo = (JPanel) ctx.getBean(item.getId()); 

    add(foo, java.awt.BorderLayout.CENTER);

}

The line in bold above is possible as a result of the new Spring/NetBeans API that is in 'contrib', as highlighted in my blog yesterday. That line is the thing that makes this possible at all. Without it, i.e., without being able to convert my Spring configuration file to Lookup, none of this would be possible. And what does my Spring configuration file look like? Exactly this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
           
    <bean id="mainPanel" class="org.netbeans.nbspringdemo.MyJPanel" init-method="init">
        <property name="axis">
            <value>1</value>
        </property>
        <property name="panelComponents">
            <list>
                <ref bean="textField1"/>
                <ref bean="textField2"/>
                <ref bean="textField3"/>
                <ref bean="buttonPanel"/>
            </list>
        </property>
    </bean>

    <bean id="buttonPanel" class="org.netbeans.nbspringdemo.MyJPanel" init-method="init">
        <property name="axis">
            <value>0</value>
        </property>
        <property name="panelComponents">
            <list>
                <ref bean="button1"/>
            </list>
        </property>
    </bean>

    <bean id="textField1" class="org.netbeans.nbspringdemo.MyJTextField" init-method="init">
        <property name="text">
            <value>hello 1</value>
        </property>
        <property name="rColor">
            <value>255</value>
        </property>
        <property name="gColor">
            <value>51</value>
        </property>
        <property name="bColor">
            <value>102</value>
        </property>
    </bean>

    <bean id="textField2" class="org.netbeans.nbspringdemo.MyJTextField" init-method="init">
        <property name="text">
            <value>hello 2</value>
        </property>
        <property name="rColor">
            <value>0</value>
        </property>
        <property name="gColor">
            <value>100</value>
        </property>
        <property name="bColor">
            <value>0</value>
        </property>
    </bean>

    <bean id="textField3" class="javax.swing.JTextField">
        <property name="text">
            <value>goodbye world</value>
        </property>
    </bean>

    <bean id="button1" class="org.netbeans.nbspringdemo.MyJButton" init-method="init">
        <property name="actionListener">
            <ref bean="myButtonActionListener"/>
        </property>
        <property name="text">
            <value>Click me!</value>
        </property>
    </bean>

    <bean id="myButtonActionListener" class="org.netbeans.nbspringdemo.MyActionListener"/>

</beans>

That's the Spring configuration file that I discussed in Spring: How to Create Decoupled Swing Components on JavaLobby. The definition of the classes, i.e., the JPanel, JButton, and JTextField, are also described in that article. Read the comments to that article to see some use cases where you might want to assemble your user interface via decoupled Swing components and Spring.

Pretty cool that this is now also possible on the NetBeans Platform. I am not advocating this approach, I am merely pointing out that this is possible.

In other news. Read this blog entry about NetBeans Day Fortaleza!

Apr 22 2008, 05:49:51 AM PDT Permalink

Trackback URL: http://blogs.sun.com/geertjan/entry/converting_spring_to_lookup
Comments:

That's very cool. I wonder: is there a way to tell Spring (or, I guess, NetBeans) to ensure that the JPanel is created on the EDT? I suppose one only has to ensure that Spring doesn't pre-create these singletons, but defers their creation until accessed, and since the ApplicationContext is accessed by the EDT that would probably do it....

Posted by Laird Nelson on April 22, 2008 at 08:30 AM PDT #

Sure, that could be done on the Java side, I believe. By the way, see this page for more info on Spring in NetBeans IDE:

http://wiki.netbeans.org/SpringAndNetBeans

And a typed approach to my code above would be like this:

Lookup lookup = NbSpring.create(ctx);
Item<JPanel> item = lookup.lookupItem(new Template<JPanel>(JPanel.class, null, null));
JPanel foo = item.getInstance();

Posted by Geertjan on April 22, 2008 at 08:44 AM PDT #

In fact, this is not a very good example. I could have simply gotten the JPanel from the Spring context, without using Lookup:

JPanel foo = (JPanel) ctx.getBean("mainPanel", JPanel.class);

On the other hand, above I needed to hardcode the id of the JPanel. It's not possible to do this:

JPanel foo = (JPanel) ctx.getBean(null, JPanel.class);

Therefore, this way, I get the first JPanel:

Lookup lookup = NbSpring.create(ctx);
Item item = lookup.lookupItem(new Template(JPanel.class, null, null));
JPanel foo = (JPanel) ctx.getBean(item.getId());

Posted by Geertjan on April 22, 2008 at 09:04 AM PDT #

Post a Comment:

Name:
E-Mail:
URL:

Your Comment:

HTML Syntax: NOT allowed