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 developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

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]

JDNC simplifies Java UI development

Open source API adds components, aids data-centric development

Jack Li Guojie
Jack Li Guojie is an independent Java developer who has been building various types of Java applications since 1998. His areas of interest and experience include artificial intelligence, user interfacing, Web applications, and enterprise system architecture. He has contributed articles to many leading software journals. He is the author of the book Professional Java Native Interfaces with SWT/JFace (2005, Wrox).

Summary:  JDNC is an open source project that aims to make Java™ UI development easier. It offers a number of prebuilt components that provide functionality that many developers have to laboriously add to their Swing widgets. But perhaps more interestingly, it also provides data binding features that might change the way you link your data to your interfaces. In this hands-on tutorial, Java UI developer Jack Li Guojie guides you through using JDNC Swing Extensions to improve your Java UI without changing much of your existing code. You'll also see how to simplify your data-centric Java UI development by taking advantage of JDNC data binding and the DataSet API.

Date:  27 Sep 2005
Level:  Intermediate PDF:  A4 and Letter (1138 KB | 56 pages)Get Adobe® Reader®

Activity:  5916 views
Comments:  

Data binding

Data binding overview

In previous sections, you learned how to use JDNC Components to improve your user interface. In this section, you will learn about data binding, which may fundamentally change your data-centric programming model.

Data binding provides an easy mechanism for you to create a read/write link between the UI controls and the data in your application. You can bind arbitrary data objects to front-end controls. In order to bind your data to the UI control, you first adapt the data structure to a common data model interface, called a DataModel. A DataModel contains all the information about your data fields. It allows uniform access to all properties of the model regardless the nature of the data. A DataModel provides access to:

  • Metadata: A description of the properties of each data field, such as the data's type.
  • Value: The current value for each data field.

To bind your DataModel to a UI control, you use a binding. The binding takes care of all the wiring between the data model and the UI control. Figure 14 illustrates the basic process of data binding in JDNC.


Figure 14. How data binding works
How data binding works

The next panel examines a simple program that illustrates these concepts.


Data binding example

Suppose we have the class in Listing 12.


Listing 12. A data binding example
                     
public class Person {

 private String firstName;
 private String lastName;
 private int age;
 
 public Person(String firstName, String lastName, int age) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.age = age;
 }
 
 ... all the getters and setters.

}


Imagine we want to bind an object of the Person class to the UI controls shown in Figure 15.


Figure 15. We want to bind the Person class to these UI controls
We want to bind the Person class to these UI controls

First, you need to get your data object and the UI controls ready, as Listing 13 illustrates.


Listing 13. Preparing your data object and UI controls
                    
final Person person = new Person("Homer", "Simpson", 40);

JTextField textFirstName = new JTextField(6); JTextField

textLastName = new JTextField(6);

As I mentioned, we need to adapt our data to a data model first. Because our object is a JavaBean, we can use the JavaBeanDataModel to adapt it to a data model, as Listing 14 shows.


Listing 14. Adapting a JavaBean to a data model
                    
DataModel dataModel = new JavaBeanDataModel(Person.class, person);

The JavaBeanDataModel class introspects the Person class for all its properties and create corresponding metadata to describe them. Additionally, JavaBeanDataModel retrieves the current value for each property from the JavaBean object that you pass.

Now that you have adapted your data to the proper data model, you use Binding to bind the data model to the UI controls. There are quite a few binding classes available in JDNC, including TextBinding (which binds a data field to a text control like JTextField) and TableBinding (which binds a data field to a JTable). Instead of specifying the binding class directly, we'll use the factory method provided in the BindingMap class, shown in Listing 15.


Listing 15. Binding data to our UI controls
                    
final Binding bindingFirstName = 
  BindingMap.getInstance().createBinding(textFirstName, 
    dataModel, "firstName"); 

final Binding bindingLastName =
  BindingMap.getInstance().createBinding(textLastName, 
    dataModel, "lastName");

Note that the createBinding() method of BindingMap takes three arguments:

  • The UI control to be bound
  • The data model
  • The name of the field (property) in the data model that you want to bind

You can use the binding to control the communication between the data model and the UI control. You use the pull() method to retrieve the current value from the data model and update the UI, as in Listing 16.


Listing 16. Retrieving the data and updating the UI
                    
bindingFirstName.pull();

bindingLastName.pull();

Listing 17 shows the push() method that you use to update the data model using the values of the UI control.


Listing 17. Updating the data model
                    

ActionListener actionListener = new ActionListener() { 
 public void actionPerformed(ActionEvent arg0) { 
   System.out.println("Before push: " + person);
   bindingFirstName.push(); 
   bindingLastName.push();
   System.out.println("After push: " + person); 
 } 

};

textFirstName.addActionListener(actionListener);

textLastName.addActionListener(actionListener);

Finally, you draw the UI, as Listing 18 shows.


Listing 18. Drawing the UI
                    
frame.getContentPane().add(new JLabel("Name:")); 

frame.getContentPane().add(textFirstName);

frame.getContentPane().add(textLastName);

frame.pack(); 

frame.setVisible(true);

All the code on this panel may seem very tedious. However, it shows you the details of how data binding works. In later panels, you will learn techniques that can simplify data binding dramatically. Before that, though, let's quickly go through two important interfaces involved in data binding: DataModel and Binding.


The DataModel interface

The DataModel interface represents a record of named data fields. A DataModel can be constructed for a row of data in a database or for an arbitrary JavaBean. DataModel not only provides the current value of each field, it also provides the corresponding metadata for each field. For example, we can use the code in Listing 19 to peek at the MetaDatas that have been created for us when we construct a JavaBean-based data model.


Listing 19. Examining metada
                     
final Person person = new Person("Homer", "Simpson", 40);

DataModel dataModel = 
  new JavaBeanDataModel(Person.class, person);



System.out.println("Metadatas: ");

MetaData[] metaDatas = dataModel.getMetaData();

for (int i = 0; i < metaDatas.length; i++) {
 System.out.println("Name: " + metaDatas[i].getName() + ", " + 
   "Element class: " + metaDatas[i].getElementClass());

}
 	

System.out.println("\nCurrent values: ");

String[] fields = dataModel.getFieldNames();

for (int i = 0; i < fields.length; i++) {
 Object value = dataModel.getValue(fields[i]);
 System.out.println("Field: " + fields[i] + ", " +
   "Current Value: " + value + ", Type: " + value.getClass());

}

When you run the code, you should see the following output:

Metadatas: 

Name: age, Element class: int 

Name: class, Element class: class java.lang.Class 

Name: firstName, Element class: class java.lang.String 

Name: lastName, Element class: class java.lang.String


Current values: 

Field: age, Current Value: 40, Type: class java.lang.Integer 

Field: class, Current Value: 
  class com.asprise.jdnc.demo.Person, 
    Type: class java.lang.Class

Field: firstName, Current Value: Homer, 
  Type: class java.lang.String 

Field: lastName, Current Value: Simpson, 
  Type: class java.lang.String

Note that age, firstName, and lastName are properties defined in our Person class. The JavaBeanDataModel class introspects the object and finds the getClass() method (inherited from java.lang.Object); thus, it creates the class field.

The following are two data exchange methods declared in the DataModel interface:

  • getValue(String fieldName): Returns the current value of the specified field.
  • setValue(String fieldName, Object value): Sets the current value of the specified field to the given value.

Once you have the data model ready, you can bind it to proper UI controls. To perform such binding, you need the Binding interface.


Binding

The Binding interface binds a data model to a UI control. The main functions of Binding include:

  • Pulling a value from the data model into the UI control
  • Validating the value contained in the UI control
  • Pushing the validated value from the UI controls to the data model

The following are the key methods declared in the Binding interface:

  • pull(): Pulls the value of the data model into the UI control
  • push(): Pushes the current value contained in the UI control into the data model
  • isModified(): Returns a Boolean that indicates whether or not the value contained in the UI control has been modified since the value was last pushed or pulled
  • isValid(): Returns a Boolean that indicates whether or not the value contained in the UI control is valid
  • getDataModel(), getFieldName(): Return the data model and the field bound to the UI control, respectively
  • getComponent(): Returns the UI control bound to the data model

The createBinding() method of the BindingMap class is very handy for creating a binding between a UI control and a data model:

Binding createBinding(JComponent component, 
DataModel model, String fieldName)

At this point, you should have a basic understanding of how DataModel and Binding make data binding happen. In the following panels, you'll see how to customize and simplify data binding.


Using converters

In this panel, we will try to bind the age property of our Person class to a UI control. Earlier in this section, you saw how to construct a data model and bind firstName and lastName to the UI controls. Listing 20 is our first attempt to bind age to a JTextField.


Listing 20. Binding age to a JTextField
                    
JTextField textFirstName = new JTextField(6);

JTextField textLastName = new JTextField(6);

JTextField textAge = new JTextField(2);


final Person person = new Person("Homer", "Simpson", 40);

DataModel dataModel = 
  new JavaBeanDataModel(Person.class, person);


final Binding bindingFirstName = 
 BindingMap.getInstance().createBinding(textFirstName,
    dataModel, "firstName"); 

final Binding bindingLastName =
 BindingMap.getInstance().createBinding(textLastName,
   dataModel, "lastName");

final Binding bindingAge =
 BindingMap.getInstance().createBinding(textAge, 
   dataModel, "age");


bindingFirstName.pull(); 

bindingLastName.pull();

bindingAge.pull();


ActionListener actionListener = new ActionListener() { 
 public void actionPerformed(ActionEvent arg0) {
   System.out.println("Before push: " + person);
   bindingFirstName.push(); bindingLastName.push();
   bindingAge.push(); 
 	
   System.out.println("After push: " + person); 
 } 

};


textFirstName.addActionListener(actionListener);

textLastName.addActionListener(actionListener);

textAge.addActionListener(actionListener);


frame.getContentPane().add(new JLabel("Name: "));

frame.getContentPane().add(textFirstName);

frame.getContentPane().add(textLastName); 

frame.getContentPane().add(new JLabel("Age: "));

frame.getContentPane().add(textAge);

When you run the code, you'll see that the UI pops up as expected; it should look like Figure 16.


Figure 16. The UI looks as we expect it to
The UI looks as we expect it to

However, if you modify the age and press Enter, the following exception will be thrown:

java.lang.IllegalArgumentException
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.jdesktop.swing.data.JavaBeanDataModel.setValueImpl
   (JavaBeanDataModel.java:115)
 at org.jdesktop.swing.data.AbstractDataModel.setValue
   (AbstractDataModel.java:45)
 at org.jdesktop.swing.binding.AbstractBinding.push
   (AbstractBinding.java:119)
 at com.asprise.jdnc.demo.BindingDemoV3$1.actionPerformed
   (BindingDemoV3.java:54)
 at javax.swing.JTextField.fireActionPerformed(Unknown Source)
 at javax.swing.JTextField.postActionEvent(Unknown Source)
 at javax.swing.JTextField$NotifyAction.actionPerformed
   (Unknown Source)
 at javax.swing.SwingUtilities.notifyAction(Unknown Source)
 ...

When you pressed the Enter key, the action listener was invoked. bindingAge.push() pushes the current value of the JTextField -- which is a String -- to the model. But because the model only accepts Integers as values for age, we get the exception shown above. To solve this kind of problem, we need to use a converter to convert the value in the UI to the type accepted by the data model. For the age property, we use the code in Listing 21 to set up the converter.


Listing 21. Setting up the converter
                    
... 

final Person person = new Person("Homer", "Simpson", 40); 

DataModel dataModel = new JavaBeanDataModel(Person.class, person); 

MetaData metaDataAge = dataModel.getMetaData("age");

metaDataAge.setConverter(Converters.get(Integer.class));

...

Now, you can update the age property when you run the code.


JDNC converters

In the last panel, you saw how to use a converter to convert the value contained in a UI control to the type accepted by the data model. In JDNC, the Converter interface defines a bidirectional conversion between string values and Java objects. There are only two methods in the Converter interface:

  • Object decode(String value, Object format): Converts the specified text value to an object of the specified type
  • String decode(Object value, Object format): Converts the specified object to a string representation

In JDNC, the Converters class contains a static registry of a set of converters for the common Java data types. The Converters class has proper converters for the following types:

  • Boolean
  • Date
  • Double
  • Float
  • Integer
  • Long
  • Short
  • String

To obtain a converter for a certain type, use the following method of the Converters class:

public static Converter get(Class klass)

You can also implement a converter and put it into the Converters class as follows:

public static void put(Class klass, Converter converter)

Once you obtain a proper converter, you can then provide it to the field through its MetaData, as in Listing 22.


Listing 22. Providing a converter to a field
                    
MetaData metaDataAge = dataModel.getMetaData("age");

metaDataAge.setConverter(Converters.get(Integer.class));

The converter will be used by the data binding to perform conversion when pull() or push() methods are called.


Using validators

The Validator interface represents a validator that performs validation on a value in the UI control before it can be pushed to the data model. There is only one method declared in the Validator interface:

boolean validate(Object value, Locale locale, String[] error)

In our example code, we want to add a validator to the age property in order to validate the user input. To do so, you simply obtain the MetaData for age and add a validator to it, as in Listing 23.


Listing 23. Adding a validator to the age property
                     

MetaData metaDataAge = dataModel.getMetaData("age");

metaDataAge.setConverter(Converters.get(Integer.class)); 

metaDataAge.addValidator(new Validator() { 
 public boolean 
   validate(Object value, Locale locale, String[] error) { 
     int val = ((Integer)value).intValue(); 
     if(val < 0 || val > 200) { 
       error[0] = "Invalid age: " + val; 
       return false; 
     } 
     return true; 
 } 

});

Now, when users enter an invalid value and presses Enter, they will be told that the value is invalid, as shown in Figure 17.


Figure 17. A validator flags an invalid value
A validator flags an invalid value

Similarly, you can add one or more validators for other properties.


Simplify data binding with JForm and JNForm

At this point, you might feel that performing data binding in JDNC is a very tedious task. Earlier in this section, you needed to create the data model first. Then you created a UI component and a binding for each property. After that, you needed to implement action listeners to monitor UI events and push the values back to the data model. If you use JForm or JNForm, however, most of these tedious procedures are greatly simplified. In Listing 24, I've rewritten our sample application to use JNForm.


Listing 24. Our data binding application, rewritten
                       
public class BindingDemoV5 { 
 public static void main(String[] args) throws
   IntrospectionException { 
     JFrame frame = new JFrame("Simple Binding Demo");
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     frame.getContentPane().setLayout(new FlowLayout()); 
     final Person person = new Person("Homer", "Simpson", 40);
     DataModel dataModel = 
       new JavaBeanDataModel(Person.class, person);
     MetaData metaDataAge = dataModel.getMetaData("age");
     metaDataAge.setConverter(Converters.get(Integer.class));
 	
     JNForm form = new JNForm(); 
     try { 
       form.bind(dataModel, "firstName"); 
       form.bind(dataModel, "lastName");
       form.bind(dataModel, "age"); 
     } catch (BindException e) {
       e.printStackTrace(); 
     }
 	
     frame.add(form); 
     frame.pack(); 
     frame.setVisible(true);
 } 

}

If you compare this version to the original version, you'll see that the amount of code has been significantly reduced. If you run the code in Listing 24, you should see the screen illustrated in Figure 18.


Figure 18. JNForm in action
JNForm in action

When the user clicks Reset, data is pulled from the model and filled into the UI controls. When the user clicks Submit, data is synchronized from the UI controls to the data model.

You might notice that there is no way to update the age, because it is rendered in a JLabel. Fortunately, JForm allows us to specify the control for a field in the data model; Listing 25 illustrates this.


Listing 25. Specifying the control for a field
                    
JNForm form = new JNForm(); 

try {
 form.bind(dataModel, "firstName"); 
 form.bind(dataModel, "lastName"); 

 // form.bind(dataModel, "age");
 	
 form.getForm().bind(dataModel, "age", new JTextField(2));

} catch (BindException e) { 
 e.printStackTrace(); 

}

Here, we've made the age field editable, as shown in Figure 19.


Figure 19. The age field is no editable
The age field is no editable

Extended TableModel

The DefaultTableModelExt class, extending the java.swing.table.AbstractTableModel class, represents a tabular data model; it's capable of loading data from a text file.

Basically, a DefaultTableModelExt consists of two portions: the structure of the model and the data cells. You use MetaData to specify the structure of the model. After the structure has been properly defined, you can either add and remove data programmatically or load data from a text file.

Suppose we have a tab-separated values (TSV) file named books.txt:

Professional Java Native Interfaces with SWT/JFace	
  Jackwind Li Guojie	0470094591	$16.00
  http://images.amazon.com/images/P/0470094591.01._SCMZZZZZZZ_.jpg

Head First Java	
  Kathy Sierra, Bert Bates	0596009208	$29.67	
  http://images.amazon.com/images/P/0596009208.01._SCMZZZZZZZ_.jpg

Effective Java Programming Language Guide
  Joshua Bloch 	0201310058	$28.55	
  http://images.amazon.com/images/P/0201310058.01._SCMZZZZZZZ_.jpg

Java In A Nutshell
  David Flanagan	0596007736	$15.28	
  http://images.amazon.com/images/P/0596007736.01._SCMZZZZZZZ_.jpg

...

We can use the code in Listing 26 to load it and display it in a JNTable.


Listing 26. Loading TSV data and displaying it in a JNTable
                     
public class TableModelExt {
 public static void main(String[] args)
   throws IOException, BindException {
     JFrame frame = new JFrame("DefaultTableModelExt Demo");
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


     DefaultTableModelExt tableModelExt = new DefaultTableModelExt();
     tableModelExt.setColumnCount(5);
 	
     // Metadata
     MetaData columnMetaData = tableModelExt.getColumnMetaData(0);
     columnMetaData.setName("Title");
     columnMetaData = tableModelExt.getColumnMetaData(1);
     columnMetaData.setName("Author");
     columnMetaData = tableModelExt.getColumnMetaData(2);
     columnMetaData.setName("ISBN");
     columnMetaData = tableModelExt.getColumnMetaData(3);
     columnMetaData.setName("Price");
     columnMetaData = tableModelExt.getColumnMetaData(4);
     columnMetaData.setName("Cover_URL");
 	
     tableModelExt.setSource("file:///F:/Writing/TUTORIAL/
 	code/data/books.tsv");
     tableModelExt.startLoading();
 	
     frame.add(new JNTable(tableModelExt));
 
     frame.pack();
     frame.setVisible(true);
 }

}

In the code in Listing 26, we create an instance of DefaultTableModelExt. Then we define each column with a MetaData object. After that, we use the setSource() method to set the source file from which the data should be loaded. Then we call startLoading() to load the data asynchronously. Finally, we use the table model constructed to create a JNTable and display it in the frame, as shown in Figure 20.


Figure 20. A JNTable with an extended TableModel
A JNTable with an extended TableModel

In the next panel, you will learn how to convert a DefaultTableModelExt into a data model and take advantage of data binding.


Using TableModelExtAdapter

In the last panel, you saw how to use DefaultTableModelExt to load data from a TSV file. The TableModelExtAdapter class can adapt a DefaultTableModelExt into a data model. Thus, you can use the data model to do data binding. In the last panel, we simply displayed the book information using a JNTable. Now, we want to display the book cover when the user selects a book from the table.

First, we need to define metadata and start to load data for the TSV file, which we do with the code in Listing 27.


Listing 27. Defining metadata and loading data.
                    
DefaultTableModelExt tableModelExt = 
  new DefaultTableModelExt(); 

tableModelExt.setColumnCount(5);


Metadata MetaData columnMetaData =
  tableModelExt.getColumnMetaData(0);

columnMetaData.setName("Title"); 


columnMetaData = tableModelExt.getColumnMetaData(1);

columnMetaData.setName("Author"); 


columnMetaData = tableModelExt.getColumnMetaData(2);

columnMetaData.setName("ISBN"); 


columnMetaData = tableModelExt.getColumnMetaData(3);

columnMetaData.setName("Price"); 


columnMetaData = tableModelExt.getColumnMetaData(4);

columnMetaData.setName("Cover_URL"); 

tableModelExt.setSource("file:///F:/Writing/TUTORIAL/
  code/data/books.tsv");

tableModelExt.startLoading();

Because the data is loaded asynchronously, we want to wait until it finishes loading. The code in Listing 28 does this.


Listing 28. Waiting for the data to finish loading
                    
// wait till data loaded. 

while(true) { 
 if(!tableModelExt.isLoading()) 
 	break;
 try { 
 	Thread.sleep(20); 
 }catch(InterruptedException ie) {
 	continue; 
 } 

}

Then we adapt the DefaultTableModelExt into a TableModelExtAdapter:

final TableModelExtAdapter adapter = 
  new TableModelExtAdapter(tableModelExt);

In Listing 29, we create an instance of JXImagePanel, which is a JPanel with image display capability.


Listing 29. Creating an instance of JXImagePanel
                     
final JXImagePanel imagePanel = new JXImagePanel();

imagePanel.setPreferredSize(new Dimension(200, 200));

We have the data model and the UI control ready. Now we can use a binding to bind them together:

ImagePanelBinding binding = new	
  ImagePanelBinding(imagePanel, adapter, "Cover_URL");

ImagePanelBinding binds a field with type java.lang.String with a JXImagePanel. For this binding, the metadata is quite clear, but what are the current values (because there are so many rows)? By default, a TableModelExtAdapter does not have any current value. You can use the setRecordValue() method to use the specified row to supply current values. For example, you use could setRecordValue(0) to take the values contained in the first row as the current values to be supplied by the TableModelExtAdapter.

In Listing 30, we create the JNTable for displaying book information and add a selection listener to it.


Listing 30. Creating the JNTable
                    
final JNTable table = new JNTable(tableModelExt);

table.getTable().setSortable(false); 

table.getTable().getSelectionModel().addListSelectionListener(
 new ListSelectionListener() { 
 	public void valueChanged(ListSelectionEvent se) {
        adapter.setRecordIndex(table.getTable().getSelectedRow());
 	} 
 });


frame.add(table, BorderLayout.CENTER);

frame.add(imagePanel, BorderLayout.SOUTH); frame.pack();

frame.setVisible(true);

When you run the code in Listing 30, you should see the screen illustrated in Figure 21.


Figure 21. Adding the image panel
Adding the image panel

When you select a book, the corresponding book cover will be displayed in the bottom panel.

5 of 10 | Previous | Next

Comments



Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology
ArticleID=131826
TutorialTitle=JDNC simplifies Java UI development
publish-date=09272005
author1-email=jackliguojie@hotmail.com
author1-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).