Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

IBM WebSphere Developer Technical Journal: Binding Swing visual components to data with the Rational Application Developer Visual Editor

Sandy Minocha (minocha@ca.ibm.com), WebSphere JumpStart ISV Enablement, IBM Software Group, IBM Toronto Lab
Sandy Minocha works for the Rational ISV Enablement team, which engages with key Rational tools business partners, providing technical guidance and support as they integrate into the Rational suite of products. The team also performs technical validations of partner plug-ins for the Ready for Rational software partner program. Sandy has a BASc in Electrical Engineering degree from University of Waterloo and a MEng in Telecommunications degree from University of Toronto.

Summary:  IBM® Rational® Application Developer's Visual Editor provides easy to use tools to bind Swing visual components, such as textfields, tables, and buttons, with very little modification (if any) required to the actual source code.

Date:  11 May 2005
Level:  Intermediate

Activity:  5340 views
Comments:  

Introduction

The Java™ visual editor that enables users to graphically edit Java user interfaces has been enhanced in IBM Rational Application Developer for WebSphere® Software V6 to support the quick binding of visual components to data from a number of different sources, like a Web service or an EJB component. This article describes how to take advantage of the data binding feature to provide a quick and powerful way for you to specify how the user interface reads and writes its data.


An overview of Swing

The AWT (abstract windowing toolkit) and Swing GUI components are among the many features included in the Java Foundation Classes (JFC), which provide a framework for easily building graphical user interfaces (GUIs) and adding rich graphics functionality and interactivity to Java applications. Swing is a rich and versatile toolkit that offers many impressive features, but for our purposes, we will focus here on two important features most are relevant to understanding the Visual Editor's binders: models and actions.

Using data models for Swing

Most Swing components have models whose purpose is to provide flexibility when determining how application data is stored and retrieved. The two models that are used by the Rational Application Developer (hereafter referred to as Application Developer) data binding tools are the document and table models. Let's take a look at each of these.


Figure 1. Document model
Figure 1. Document model

In a document model (Figure 1), a text component separates its data (known as the model) from its view of the data. This model implements the javax.swing.text.Document interface, and provides these services:

  • Contains the text. A document stores the textual content in javax.swing.text.Element objects, which can represent any logical text structure, such as paragraphs, text runs that share styles, and so on.
  • Provides support for editing the text through the remove(String aString) and insertString(int position, String aString, AttributeSet anAttributeSet) methods.
  • Notifies document listeners and undoable edit listeners of changes to the text.
  • Manages Position objects, which track a particular location within the text even as the text is modified.
  • Enables you to get information about the text (for example, its length), as well as segments of the text as a string.

Here is an example of setting a document on a text field:

Document doc = new MyDocument();
...
textfield = new JTextField();
textfield.setDocument(doc);


Figure 2. Table model
Figure 2. Table model

In a table model (Figure 2), a graphical component that enables you to list row and column data, along with scroll bars to provide paging. Every table gets its data from an object that implements the javax.swing.table.TableModel interface. Generally though, you can implement your table model as a subclass of the javax.swing.table.AbstractTableModel class.

Your table model might hold its data in an array, list, or hash map, or it might instead get its contents from an outside source, such as a database. In some cases, the model might actually generate the data at execution time.

The JTable can be set up to display any data model that implements the TableModel interface with the following code:

TableModel myData = new MyTableModel(); 
JTable table = new JTable();
table.setModel(myData);

Using Swing actions

When you have two or more components that perform the same function, an action object is generally used to encapsulate the function and implement the javax.swing.Action interface. An action object is an action listener that provides action-event handling. Attaching an action to a component using the setAction method results in:

  • The component's state is updated to match the state of the Action. For example, if the Action's text and icon values were set, the component's text and icon are updated to reflect this.
  • The Action object is registered as an action listener on the component.
  • If the state of the Action changes, the component's state is updated to match the Action. For example, if you change the enabled status of the action, all components it is attached to change their enabled states to match the action.

Here is an example of setting an action on a button:

Action myAction = new MyAction();
...
button = new JButton();
button.setAction(myAction);


Data binding Swing visual components

The Visual Editor in Eclipse supports visual construction using AWT/Swing components. The common components, containers, menus and controls are included in the design palette and are organized using drawers that you can expand, collapse and pin open.

Binding Swing visual components without the Application Developer binders is a manual process that requires adding the correct code in the design source editor. With the binders, however, a combination of data source, data object, and Swing binder helper classes are used along with visual feedback to enable the simple and quick and simple data binding of visual components.

The default Swing visual components that are supported in Application Developer include text fields, tables, and buttons. If you wish, you can also write your own binders for other components by implementing the provided interfaces. The Visual Editor provides dialog boxes that help you create data objects and data sources that you can use to bind a visual component. Without the dialogs, however, you can still add basic data objects, data source data objects, and data sources from the palette, and configure them using the Properties view. The data source and data object classes are completely independent of the visual components, allowing for possible future support of other widget libraries.

As you bind visual components to data sources and data objects, binder code is generated as needed into your project source directory. By default, the generated classes are added to a jve.generated package in your project. You then have the freedom to extend, replace, or rewrite the data binding logic. Once you have modified the jve.generated classes to add any custom business logic, they will not be overwritten by the Visual Editor.

Swing binders
Binders connect visual components to a data object. There is a one-to-one relationship between a visual component and its binder. There is a one-to-many relationship between a data object and the binders that interact with it. In other words, more than one visual component can be bound to a given data object, but each visual component requires its own binder.

Data Source
A data source represents a data factory whose purpose is to serve up data for the data objects and broker the conversation to the raw data. Data sources supported by Application Developer's visual editor include J2EE session beans, Web services, and JavaBeans. A data source can be thought of as a factory for a facade, providing configuration properties that enable the instantiation and initialization of a data source facade. The facade is a class that provides a set of methods that can create data objects from the back end, or provide some other business function. It is up to the data source implementer to ensure that the facade is instantiated properly.

Data Object
A data object represents an object of data that is available locally with which client components can interact, and is a wrapper to an object that manages property change events for that object.

Figure 3 shows the design palette in Application Developer with drawers for the visual components as well as the data binders.


Figure 3. Rational Application Developer design palette
Figure 3. Rational Application Developer design palette

MyBooks sample application

The sample application we will use here is taken from a previously published developerWorks article, Building Applications with the WebSphere Studio Visual Editor and Java Beans Part 3: Working with XML data.

The MyBooks application has been modified here so that we can focus on the three Swing visual components supported by the Application Developer visual editor for data binding: JTextField, JTable, and JButton. Figure 4 shows a screen shot of the MyBooks application showing the XML data in a JTable, the XML file name in a JTextField, and the SAVE JButton.


Figure 4. MyBooks application table model
Figure 4. MyBooks application table model

MyBooks takes in a single argument: the name of the XML file that contains the list of books to be displayed in the table. When the SAVE button is selected, the contents of the table is saved in the XML file specified in the textfield.

To create the MyBooks application, we begin by laying out the basic GUI in Section A, and then use Application Developer to visually bind the GUI to the data in Section B.

A. Build the user interface and the Java Data Factory

To build the MyBooks user interface, we will use the visual editor:

  1. Create a Java project
    1. In Application Developer, select File => New => Project.
    2. Select Java Project and press Next.
    3. Type the name MyBooks for the Project and press Next.
    4. Add xsdbeans.jar from your Application Developer installation to the Java build path. This JAR file is located at <rad_install>/SDP/6.0/rwd/eclipse/plugins/com.ibm.etools.xsd.codegen.xsdbeans_6.0.0\jars\xsdbeans.jar.
    5. Press Finish.
    6. Create packages ve.eclipse and ve.rad.

  2. Add the main visual class
    1. In the Package Explorer, right-click on the project and select New => Other.
    2. Select Visual Class and press Next.
    3. Specify a Package name ve.
    4. Specify a Class name MyBooksApp.
    5. Make sure the Superclass is javax.swing.JFrame and that public static void Main(String[] args) is selected.
    6. Press Finish.

  3. Customize the JFrame
    1. Add a private variable filename of type String to this class.
    2. Modify the constructor MyBooksApp() so it looks like this:
      public MyBooksApp(String f) {
      	super();
      	filename = f;
      	initialize();
      }


    3. Modify main() so it looks like this:
      public static void main(String[] args) {
      	MyBooksApp app = new MyBooksApp(args[0]);
      	app.show();
      }


    4. Select the text JFrame in the visual editor window. In the editable text box that appears, enter MyBooks.
    5. Select the JFrame component in the visual editor window and make sure the Properties view is active.
    6. From the Properties view, set defaultCloseOperation property to EXIT and press Enter.
    7. From the Properties view, set size property to 400,200 and press Enter.

  4. Add a text field
    Function: This visual component will display the XML file name.
    1. Select JPanel in the Swing Containers section of the palette. Drag and drop it to a location outside the JFrame component in the visual editor.
    2. Select JLabel in the Swing Components section of the palette. Drag and drop into the JPanel.
    3. From the Properties view, set the JLabel's text property to XML filename: and press Enter.
    4. Select JTextField in the Swing Components section of the palette. Drag drop into the JPanel.
    5. Place the JPanel on the North section of JFrame.

  5. Add a button
    Function: This visual component will save the data from the table to the specified XML file.
    1. Select JButton in the Swing Components section of the palette and place it on the South section of the JFrame.
    2. From the Properties view, set the JButton's text property to SAVE and press Enter.

  6. Add a table
    Function: This visual component will display the contents of the XML file.
    1. Select JTable on JScrollPane in the Swing Containers section of the palette and place it on the Center section of the JFrame.
    2. Save the visual class by pressing CTRL-S and then close the editor.
    3. Copy the class to ve.eclipse and ve.rad.

The user interface portion of this exercise is now completed: We created a Java project that stores our visual class (JFrame), which consists of three key Swing components that include a JTextField, JButton and a JTable.

We are only halfway through Section 1, though. The next step is to write some business logic that will read/write data between our visual class and some data source, which in this case is an XML file. At this point, the GUI should look like Figure 5 in the visual editor.


Figure 5. MyBooks GUI
Figure 5. MyBooks GUI

The Java Data Factory is responsible for reading the contents of the XML file. Before we can create it, though, we first need to create the XML file and two data types:

  1. Create XML file
    Create a new file in the MyBooks project and name it books.xml and copy the following content to the generated file:
    <?xml version="1.0" encoding="UTF-8"?>
    <books>
    	<book>
    		<title>VisualAge for Java for Non-Programmers</title>
    		<author>Parkin, Burrus, Pullin</author>
    		<copyrightDate>2002</copyrightDate>
    	</book>
    	<book>
    		<title>Bird Life & Behavior</title>
    		<author>Sibley</author>
    		<copyrightDate>2001</copyrightDate>
    	</book>
    </books>
    


  2. Create book data type
    Each item in the XML file is stored in a book object. Create a new Java class, name it ve.book, and paste the following code into the contents of the file:
    =package ve;
    import com.ibm.etools.xmlschema.beans.*;
    
    public class book extends ComplexType {
    	public book() {
    	}
    	public void setTitle(String title) {
    		setElementValue("title", title);
    	}
    	public String getTitle() {
    		return getElementValue("title");
    	}
    	public boolean removeTitle() {
    		return removeElement("title");
    	}
    	public void setAuthor(String author) {
    		setElementValue("author", author);
    	}
    	public String getAuthor() {
    		return getElementValue("author");
    	}
    	public boolean removeAuthor() {
    		return removeElement("author");
    	}
    	public void setCopyrightDate(String copyrightDate) {
    		setElementValue("copyrightDate", copyrightDate);
    	}
    	public String getCopyrightDate() {
    		return getElementValue("copyrightDate");
    	}
    	public boolean removeCopyrightDate() {
    		return removeElement("copyrightDate");
    	}
    }


  3. Create books data type
    A books object stores a list of book items. Create a new Java class and name it ve.books setting its contents as follows:
    package ve;
    import com.ibm.etools.xmlschema.beans.*;
    
    public class books extends ComplexType {
    	public books() {
    	}
    	public void setBook(int index, book book) {
    		setElementValue(index, "book", book);
    	}
    	public book getBook(int index) {
    		return (book) getElementValue("book", "book", index);
    	}
    	public int getbookCount() {
    		return sizeOfElement("book");
    	}
    	public boolean removeBook(int index) {
    		return removeElement(index, "book");
    	}
    }
    


  4. Create Java Data Factory
    Create a new Java class and name it ve.MyBooksDataSource as follows:
    package ve;
    import com.ibm.etools.xmlschema.beans.*;
    
    public class MyBooksDataSource extends Factory {
    	public MyBooksDataSource() {
    		super();
    	}
    	public book[] getBooks() {
    		books iBooks = (books) loadDocument("books", getXMLFilename());
    		book[] result = new book[iBooks.getbookCount()];
    		for (int i = 0; i < iBooks.getbookCount(); i++) {
    			result[i] = iBooks.getBook(i);
    		}
    		return result;
    	}
    	public BaseType loadDocument(String className, String filename) {
    		return super.loadDocument(className, filename);
    	}
    }
    

Running the MyBooks application at this point would give you an empty application since none of the Swing components are bound to any data. In the next part of this exercise, we actually bind data to the visual components.

B. Bind the MyBooks user interface using the visual editor

As we continue to build the GUI in a top down fashion, the components have been laid out already, and once they are visually correct we can now provide the logic to enable them to access and update their data. We will now bind the visual components to their data.

  1. Open the JFrame
    1. In Application Developer, select File => Import.
    2. Select Existing Project into Workspace, then press Next.
    3. Select the MyBooks project created above, then press Finish.
    4. Open ve.rad.MyBooksApp in the visual editor.

  2. Bind the textfield
    1. Select the textfield. A Bind... option appears in the upper-left of the textfield.
    2. Select Bind... This will open a dialog that lets you to specify the details of how to bind to the data.
    3. In the Field Data Bindings window, select New Data Source Data Object....
    4. In the New Data Source Data Object window, select Java Bean Factory as the source type.
    5. Select New... next to the Data source drop-down box.
    6. In the Choose a Bean window, search and select ve.MyBooksDataSource. Press OK to add this data source.
    7. Select getXMLFilename() in the Source service text box. This is the name of a method on the data source facade MyBooksDataSource.java.
    8. In the Name textfield, change stringObject to xmlFilename, then OK.
    9. Press OK again.

  3. Bind the table
    1. Select the table. A Bind... option appears in the upper-left part of the table.
    2. Select Bind....
    3. In the Table Data Bindings window, select New Data Source Data Object....
    4. In the New Data Source Data Object window, only a single source service method getBooks() appears. This is the only method that returns array data that the table is able to use. Press OK having selected the getBooks() method.
    5. Add the data object properties author, copyrightDate and title to the Table columns list.
    6. Press OK.
    7. Select the MyBooksDataSource non-visual bean in the visual editor. Open or make active the Properties view.
    8. Expand the property dataSource.
    9. Set the encoding property to UTF-8 and press Enter.
    10. Set the encodingTab property to UTF-8 and press Enter.
    11. Set the packageName property to ve and press Enter.
    12. Set the xmlFilename property to filename and press Enter. Modify the generated code in source editor, from:

      myBooksDataSource1.setXMLFilename("filename");
      to:
      myBooksDataSource3.setXMLFilename(filename);.

  4. Bind the button
    1. Select the button. A Bind... option appears in the upper-left part of the table.
    2. Select Bind... .
    3. In the Component Action Bindings window, select save(java.lang.String) in the source service textbox.
    4. Select xmlFilename in the Argument drop-down box.
    5. Press OK.
    6. Save the file.
    Figure 6 shows a screen shot of the completed MyBooks application.
    Figure 6. MyBooks application completed
    Figure 6. MyBooks application completed
  5. Test the application
    To test your application, you need to supply the XML file name as an argument in a launch configuration:
    1. Select the arrow next to the Run icon in the toolbar, and select Run...
    2. In the Run window, select Java Application as the launch.
    3. Press New. A new launch configuration appears in the window, with the Main tab filled in with the names of your project MyBooks and application ve.rad.MyBooksApp.
    4. Select the Arguments tab, and enter the full path to your XML file name. The program arguments you enter on the Arguments tab are passed to the main(String[] args) method when your application starts, so this is how your program gets the argument values.
    5. Select Run.
    6. Modify the XML filename.
    7. Press Save. Verify the contents of the table are saved in the specified file and location.
    8. Close MyBooksApp.

C. Bind the MyBooks user interface using the Eclipse visual editor (optional)

This section is optional because it describes binding to the user interface created in Part 1 using Eclipse's visual editor, which has no data binding tools. This section is intended to highlight the value-add of having such data binding tools in Application Developer.

To work with Eclipse's visual editor, the following components are required (and can be downloaded from Eclipse Visual Editor Project):

  • Eclipse build eclipse-SDK 3.0.1
  • Visual Editor 1.0.2
  • EMF build 2.0.1
  • GEF build 3.0.1
  1. Create the table model
    To present a table at run time, you have to supply the actual data in a table model, and then associate that table model with the JTable bean. The table model provides several methods that the JTable bean calls to get such things as the number of columns and rows in the table, or the data for a particular table cell. You need to implement the methods in your table model class, so the JTable bean can access the data in the model and present it in its view of the table.

    Create a new Java class and name it ve.eclipse.MyBooksTableModel. Replace the contents of the generated file with this code:

    package ve.eclipse;
    import javax.swing.table.AbstractTableModel;
    import ve.*;
    
    public class MyBooksTableModel extends AbstractTableModel {
    	private MyBooksDataSource iBooksFactory;
    	private books iBooks;
    
    	public MyBooksTableModel() {
    		super();
    	}
    	public MyBooksTableModel(String xmlFile) {
    		super();
    		iBooksFactory = new MyBooksDataSource();
    		iBooksFactory.setPackageName("ve");
    		iBooksFactory.setEncoding("UTF8");
    		iBooksFactory.setEncodingTag("UTF-8");
    		iBooks = (books) iBooksFactory.loadDocument("books", xmlFile);
    	}
    	public String getXMLFile() {
    		return iBooksFactory.getXMLFilename();
    	}
    	public void setXMLFile(String filename) {
    		iBooksFactory.setXMLFilename(filename);
    	}
    	public void save(String fname) {
    		iBooksFactory.save(fname);
    	}
    public int getColumnCount() {
    		return 3;
    	}
    	public int getRowCount() {
    		return iBooks.getbookCount();
    	}
    	public Object getValueAt(int rowIndex, int columnIndex) {
    		switch (columnIndex) {
    			case 0:	return iBooks.getBook(rowIndex).getTitle();
    			case 1:	return iBooks.getBook(rowIndex).getAuthor();
    			case 2:	return iBooks.getBook(rowIndex).getCopyrightDate();
    		}
    		return null;
    	}
    	public String getColumnName(int arg0) {
    		switch (arg0) {
    			case 0:	return "Title";
    			case 1:	return "Author";
    			case 2:	return "Copyright Date";
    		}
    		return "";
    	}
    }


  2. Bind the table
    1. Open the ve.eclipse.MyBooksApp.java in the visual editor.
    2. Select Choose Bean from the palette. The Choose a Bean dialog appears.
    3. Search for ve.eclipse.MyBooksTableModel and press OK.
    4. Drop the non-visual bean on the visual editor surface outside the JFrame. This action will generate the method getMyBooksTableModel().
    5. Modify getMyBooksTableModel() to look like this:
      private MyBooksTableModel getMyBooksTableModel() {
      	if (myBooksTableModel == null) {
      		myBooksTableModel = new MyBooksTableModel(filename);
      	}
      	return myBooksTableModel;
      }


    6. Select the table in the Java Beans view.
    7. Modify getJTable(), so it looks like this:
      private JTable getJTable() {
      	if (jTable == null) {
      		jTable = new JTable();
      		jTable.setModel(getMyBooksTableModel());
      	}
      	return jTable;
      }


  3. Bind the textfield
    1. Select the text field in the Java Beans view.
    2. Modify getJTextField(), so it looks like this:
      private JTextField getJTextField() {
      	if (jTextField == null) {
      		jTextField = new JTextField();
      		jTextField.setText(filename);
      	}
      	return jTextField;
      }


  4. Bind the button
    1. Right-click on the SAVE button and select Events => actionPerformed.
    2. Modify getJButton(), so it looks like this:
      private JButton getJButton() {
         if (jButton == null) {
            jButton = new JButton();
            jButton.setText("SAVE");
            jButton.addActionListener(new java.awt.event.ActionListener() { 
      	  public void actionPerformed(java.awt.event.ActionEvent e) {    
      	     getMyBooksTableModel().save(getJTextField().getText());
                }
              });
         }
         return jButton;
      }


    3. Save the file.
  5. Test the application
    To test your application, you need to supply the XML file name as an argument in a launch configuration:
    1. Select the arrow next to the Run icon in the toolbar, and select Run...
    2. The Run window appears. Select Java Application as the launch.
    3. Press New. A new launch configuration appears in the window, with the Main tab filled in with the names of your project MyBooks and application ve.eclipse.MyBooksApp.
    4. Select the Arguments tab, and enter the full path to your XML file name. The program arguments you enter on the Arguments tab are passed to the main(String[] args) method when your application starts, so this is how your program gets the argument values.
    5. Select Run.
    6. Modify the XML filename.
    7. Press Save. Verify the contents of the table are saved in the specified file and location.
    8. Close MyBooksApp.

This completes the optional portion of this exercise. You will notice that many of the steps required hand coding of the data binding to the user interface, especially the table model. In contrast, Application Developer's visual editor provided a nice and simple user interface, plus it generated much of the code itself.


Conclusion

Application Developer's Visual Editor provides easy to use tools to bind Swing visual components, such as textfields, tables, and buttons, with very little modification (if any) required to the actual source code. Text on textfields is automatically set using the document model, and table models are automatically generated and added to tables. Actions are also automatically set on buttons. In contrast, accomplishing the same tasks with Eclipse is a much more manual process. You must create your own table models - plus edit the source code - to set text on textfields, add action listeners to buttons, and set table models on tables. Hopefully, the Application Developer value will be clear and you can begin immediately simplifying your J2EE application development.


Resources

About the author

Sandy Minocha works for the Rational ISV Enablement team, which engages with key Rational tools business partners, providing technical guidance and support as they integrate into the Rational suite of products. The team also performs technical validations of partner plug-ins for the Ready for Rational software partner program. Sandy has a BASc in Electrical Engineering degree from University of Waterloo and a MEng in Telecommunications degree from University of Toronto.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Rational, WebSphere
ArticleID=83208
ArticleTitle=IBM WebSphere Developer Technical Journal: Binding Swing visual components to data with the Rational Application Developer Visual Editor
publish-date=05112005
author1-email=minocha@ca.ibm.com
author1-email-cc=