Platinum Partner
netbeans

Getting Further with Spring RCP

In Getting Started with Spring RCP, the initial stages of working with Spring RCP were covered—from setting up a project, to creating views, establishing a docking system, and working with commands. I believe that those topics, without anything else, should be enough to create Spring RCP applications. You can use those instructions to provide the basis of your application and then simply work with all of the standard Swing components and, where applicable, roll your own field validation, while using the Matisse GUI Builder, or something similar, for laying out your views. However, instead of (or together with) that, optionally, you can make use of a wide range of components and services that Spring RCP offers on top of those components and services discussed in that article. Therefore, in this article, the optional next stages are covered—how to create forms, in the specific way made possible by Spring RCP, via its special support for data binding, validation, and component construction.

At the end of this article, the following new classes will have been created, on top of those created in the earlier article:

When deployed, the application will look as follows, presenting data in a Spring RCP "AbstractObjectTable" displayed in a Spring RCP "AbstractView", which is the Customer View that you created in the first article:

Indeed, the application you will build via this article will be very similar to the simple example that is bundled with the Spring RCP distribution. It will, in fact, be a subset of that example. (And many of the insights and comments in this article come from the comments in that example.) The domain objects will be much more limited than those provided by the example, as will the functionality you will add to the application, so that you will be able to focus on some very specific aspects. For example, you will learn how to add a popup item to the table, via a Spring RCP "CommandGroup", as shown below:

When the popup item is selected, a Spring RCP "TitledPageApplicationDialog" will be displayed. The dialog will be backed by a Spring RCP "AbstractForm", constructed by means of a Spring RCP "TableFormBuilder". A Spring RCP "DefaultRulesSource" will be used to ensure that, for example, the user will not be able to set a name with less than two characters, as shown below:

Again, all of these items are purely optional. Ignore them if you have your own alternatives. However, it's handy to know what's available and, potentially, one or more of these features might pique your interest and be relevant within your own Spring RCP applications.

Table of Contents


By the end of this article, you should have a general idea about what the topics above mean and how they relate to Spring RCP. Hopefully, you'll have enough information to begin playing with these features yourself!

Note: The completed example is available as a NetBeans project, as part of the Spring RCP Tooling plugin in the NetBeans Plugin Portal, from version 1.3 of the plugin onwards. Open the New Project wizard (Ctrl-Shift-N) and you should find "Spring RCP Tutorial Part 1" in the "Samples | Spring Rich Client" category.

 

Before continuing, make sure you have a Spring RCP application, in the state reached by the end of the second part of "Getting Started with Spring RCP", i.e., Creating a View. That is, you must be able to successfully run your Spring RCP application and display an empty "AbstractView" class, which is assumed to be called "CustomerView", in the instructions that follow. We will display our table in the "AbstractView" class, so it is important that you have one ready to be used.

 

Creating the Domain Objects

We begin with our domain objects, two of them, so as not to make life too simple, nor too complex. We have an Address POJO and a Customer POJO, in a new package called "domain":

package domain;

public class Address {

private String street;
private String city;
private String state;
private String zip;

public String getStreet() {
return street;
}

public void setStreet(String street) {
this.street = street;
}

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}

public String getState() {
return state;
}

public void setState(String state) {
this.state = state;
}

public String getZip() {
return zip;
}

public void setZip(String zip) {
this.zip = zip;
}

}

 

Notice that our next domain object, Customer, makes use of a nested object. The nested object is the Address object, defined above. By using this nesting mechanism, we can use nested property paths in forms. So, for example, we can refer to "firstname" and "lastname", because these are not nested, while when dealing with the Address object, we can refer to "address.street" and "address.city". Later you will see how that can come in handy, as an easy way of seeing how the fields relate to each other.

package domain;

public class Customer {

private int id;
private String firstName;
private String lastName;
private Address address;

public Customer() {
setAddress(new Address());
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public Address getAddress() {
return address;
}

public void setAddress(Address address) {
this.address = address;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

}

Finally, let's create an in-memory data store to hook our two domain objects together and provide some dummy data:
package domain;

import java.util.HashSet;

public class CustomerDataStore {

private static int nextId = 1;

private HashSet customers = new HashSet();

public CustomerDataStore() {
loadData();
}

public Customer[] getAllCustomers() {
return (Customer[]) customers.toArray(new Customer[0]);
}

private void loadData() {
customers.add(makeCustomer(
"Larry", "Streepy", "123 Some St.", "New York", "NY", "10010"));
customers.add(makeCustomer(
"Keith", "Donald", "456 WebFlow Rd.", "Cooltown", "NY", "10001"));
customers.add(makeCustomer(
"Steve", "Brothers", "10921 The Other Street", "Denver", "CO", "81234-2121"));
customers.add(makeCustomer(
"Carlos", "Mencia", "4321 Comedy Central", "Hollywood", "CA", "91020"));
customers.add(makeCustomer(
"Jim", "Jones", "1001 Another Place", "Dallas", "TX", "71212"));
customers.add(makeCustomer(
"Jenny", "Jones", "1001 Another Place", "Dallas", "TX", "75201"));
customers.add(makeCustomer(
"Greg", "Jones", "9 Some Other Place", "Chicago", "IL", "60601"));
}

private Customer makeCustomer(
String first, String last, String street,
String city, String state, String zip) {

Customer customer = new Customer();
customer.setId(nextId++);
customer.setFirstName(first);
customer.setLastName(last);

Address address = customer.getAddress();
address.setStreet(street);
address.setCity(city);
address.setState(state);
address.setZip(zip);

return customer;

}

}

As can plainly be seen, there's nothing here that's specific to Spring RCP. We've simply set up our domain and provided a simple way of accessing the data it represents, via CustomerDataStore.getAllCustomers(). However, here's the special twist that brings us into the world of Spring RCP—in our richclient-application-context.xml we need to register our store of data as a property of our CustomerView, so that we can make use of it there, via a getter and setter that we will create later in our CustomerView. So, open the richclient-application-context.xml and add the "viewProperties" below to the CustomerView bean, as well as creating a new bean called "customerDataStore", which references the class above that defines the data store:
<bean id="CustomerView" class="org.springframework.richclient.application.support.DefaultViewDescriptor">
<property name="viewClass" value="simple.CustomerView" />
<property name="viewProperties">
<map>
<entry key="customerDataStore" value-ref="customerDataStore" />
</map>
</property>
</bean>

<bean id="customerDataStore" class="domain.CustomerDataStore" />

 

Creating a Table

Let's now display our data in a table.

First, we create the table, using the Spring RCP "AbstractObjectTable" class. This is a convenience class provided by Spring RCP, with some handy methods for setting up our table in an intuitive manner, providing a simple layer between our domain and our view.

Then we add the related messages to the messages.properties file.

And, finally, we add the table to the CustomerView.

So, let's start by creating a new class called "CustomerTable", with this content:

package simple;

import javax.swing.JTable;
import javax.swing.table.TableColumnModel;

import domain.CustomerDataStore;
import org.springframework.richclient.table.support.AbstractObjectTable;

public class CustomerTable extends AbstractObjectTable {

private CustomerDataStore dataStore;

public CustomerTable(CustomerDataStore dataStore) {
super("customers", new String[]{
"lastName",
"firstName",
"address.street",
"address.city",
"address.state",
"address.zip"});
this.dataStore = dataStore;
}

@Override
protected void configureTable(JTable table) {
TableColumnModel tcm = table.getColumnModel();
tcm.getColumn(0).setPreferredWidth(100);
tcm.getColumn(1).setPreferredWidth(100);
tcm.getColumn(2).setPreferredWidth(200);
tcm.getColumn(3).setPreferredWidth(50);
tcm.getColumn(4).setPreferredWidth(10);
tcm.getColumn(5).setPreferredWidth(50);
}

@Override
protected Object[] getDefaultInitialData() {
return dataStore.getAllCustomers();
}

}

 

Next, add the strings referred to above to the messages.properties file, with values that will be displayed as the labels of the columns in the table:

firstName.label=First Name
lastName.label=Last Name
address.street.label=Street
address.city.label=City
address.state.label=State
address.zip.label=Zip

 

And then we display the table in our CustomerView, the same CustomerView that we had at the end of the 2nd part of "Getting Started with Spring RCP". We first need a getter and a setter for the data store that we registered in the richclient-application-context.xml and then we need to override AbstractView.createControl() to return a JComponent that consists of our AbstractObjectTable within a JPanel:

package simple;

import domain.CustomerDataStore;
import java.awt.BorderLayout;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import org.springframework.richclient.application.support.AbstractView;

public class CustomerView extends AbstractView {

private CustomerDataStore customerDataStore;
private CustomerTable customerTable;

protected CustomerDataStore getCustomerDataStore() {
return customerDataStore;
}

public void setCustomerDataStore(CustomerDataStore customerDataStore) {
this.customerDataStore = customerDataStore;
}

@Override
protected JComponent createControl() {

customerTable = new customerTableFactory().createCustomerTable();
JPanel view = new JPanel(new BorderLayout());
JScrollPane sp = getComponentFactory().createScrollPane(customerTable.getControl());
view.add(sp, BorderLayout.CENTER);
return view;

}

private class customerTableFactory {

public CustomerTable createCustomerTable() {

CustomerTable customerTable = new CustomerTable(customerDataStore);
return customerTable;

}

}

}

 

Now deployment will result in our table being displayed in the CustomerView:

 

 

Adding Functionality to the Table

Let's now add a popup item to our table. Whenever the user right-clicks in the table, the popup item should appear. The starting point is to override "AbstractView.registerLocalCommandExecutors()", similar to how we did it in the section Adding Context Sensitivity, in "Getting Started with Spring RCP". Here we specify that we want to use our PropertiesExecutor to handle the Properties command. That executor returns a simple JOptionPane as a placeholder for code that we will add later.

Then we use the Spring RCP "CommandGroup" class and the Spring RCP "ValueModel" class to display the popup item within the table. One or more commands can be gathered up together into a "CommandGroup", which has several useful utility methods, such as "setPopupCommandGroup", for creating popups. A "ValueModel", on the other hand, is useful for ensuring that a command is only active when something is selected. We create a new "ListSingleSelectionGuard", which selects a list selection model that is held by the ValueModel. Then the related commands (which are the guarded objects) are either enabled or disabled. You will find that, if you don't set a ValueModel, the command will always be disabled.

It is this interaction, i.e., the fact that changes in the GUI are reflected in ValueModels (and the fact that the values of the ValueModels are committed back to the related form objects, once the values in the ValueModel change), that is called "data binding", in the context of Spring RCP.

So, replace the content of your current CustomerView with the following:

package simple;

import domain.CustomerDataStore;
import java.awt.BorderLayout;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import org.springframework.binding.value.ValueModel;
import org.springframework.richclient.application.PageComponentContext;
import org.springframework.richclient.application.support.AbstractView;
import org.springframework.richclient.command.ActionCommand;
import org.springframework.richclient.command.CommandGroup;
import org.springframework.richclient.command.GuardedActionCommandExecutor;
import org.springframework.richclient.command.support.AbstractActionCommandExecutor;
import org.springframework.richclient.command.support.GlobalCommandIds;
import org.springframework.richclient.list.ListSelectionValueModelAdapter;
import org.springframework.richclient.list.ListSingleSelectionGuard;

public class CustomerView extends AbstractView {

private CustomerTable customerTable;
private CustomerDataStore customerDataStore;

private GuardedActionCommandExecutor propertiesExecutor = new PropertiesExecutor();

protected CustomerDataStore getCustomerDataStore() {
return customerDataStore;
}

public void setCustomerDataStore(CustomerDataStore customerDataStore) {
this.customerDataStore = customerDataStore;
}

@Override
protected void registerLocalCommandExecutors(PageComponentContext context) {
context.register(GlobalCommandIds.PROPERTIES, propertiesExecutor);
}

@Override
protected JComponent createControl() {

customerTable = new customerTableFactory().createCustomerTable();
JPanel view = new JPanel(new BorderLayout());
JScrollPane sp = getComponentFactory().createScrollPane(customerTable.getControl());
view.add(sp, BorderLayout.CENTER);
return view;

}

private class customerTableFactory {

public CustomerTable createCustomerTable() {

CustomerTable customerTable = new CustomerTable(customerDataStore);

CommandGroup popup = new CommandGroup();
popup.add((ActionCommand) getWindowCommandManager().getCommand(GlobalCommandIds.PROPERTIES, ActionCommand.class));
customerTable.setPopupCommandGroup(popup);

ValueModel selectionHolder = new ListSelectionValueModelAdapter(customerTable.getSelectionModel());
new ListSingleSelectionGuard(selectionHolder, propertiesExecutor);

return customerTable;

}

}

private class PropertiesExecutor extends AbstractActionCommandExecutor {

@Override
public void execute() {
JOptionPane.showMessageDialog(null, "Placeholder for showing TitledPageApplicationDialog...");
}

}

}

 

Now when you right-click in the table, you should see your new popup item:

When you select the item, a JOptionPane appears, as a placeholder for the code you will add in the next section.

And now you might be wondering how to set a double-click event, so that the PropertiesExecutor will be invoked when the user double-clicks on the table. Here it is, simply add this to the createCustomerTable() method, somewhere between lines 56 and 63 above:

customerTable.setDoubleClickHandler(propertiesExecutor);

 

Then run the application again and double-click in the table and you will have the same result as when you right-clicked the table and then invoked the popup item.

 

Creating a Dialog

Next, when the popup item is selected, we want to display a dialog showing the values of the currently selected row. You can use standard Swing dialogs, if you like. However, if you use the dialogs provided by Spring RCP, you can make use of the Spring RCP rules based validation and the Spring RCP Form Builder. (Both of these topics are discussed later.) Spring RCP provides 4 types of dialogs: ConfirmationDialog, InputApplicationDialog, TitledPageApplicationDialog, and WizardDialog.

In this section, we use the TitledPageApplicationDialog, which gives you a dialog with a title area and an area for information or for an error message. The content of this dialog is managed either by a FormBackedDialogPage, which is what we use in this article, or a CompositeDialogPage, which is applicable when you're dealing with multiple DialogPages simultaneously.

Get started by creating a new class called "CustomerPropertiesDialog" and let it extend the Spring RCP "TitledPageApplicationDialog" class, as shown below, with several of its methods overridden:

package simple;

import org.springframework.richclient.dialog.FormBackedDialogPage;
import org.springframework.richclient.dialog.TitledPageApplicationDialog;
import org.springframework.richclient.form.Form;
import domain.Customer;

public class CustomerPropertiesDialog extends TitledPageApplicationDialog {

private Form form;

public CustomerPropertiesDialog(Customer Customer) {
form = new CustomerForm(Customer);
setDialogPage(new FormBackedDialogPage(form));
}

@Override
protected void onAboutToShow() {
Customer Customer = (Customer) form.getFormModel().getFormObject();
String title =
getMessage(
"customerProperties.edit.title",
new Object[]{
Customer.getFirstName(),
Customer.getLastName()
});
setTitle(title);
}

@Override
protected boolean onFinish() {
form.getFormModel().commit();
return true;
}

@Override
protected void onCancel() {
super.onCancel();
}

}

 

Notice the definition of the "title" string in line 22 above. It refers to a message, which you need to define as follows in the "messages.properties" file:

customerProperties.edit.title=Edit Contact: {0} {1}

 

In this way, because we retrieve the firstname and lastname in the second argument to the "getMessage" call, we will be able to display the current line's firstname and lastname in the dialog that we are creating here.

Also, note that line 13 above will create an error in your code because it refers to a form that you have not yet created. And here is our form, extending the Spring RCP "AbstractForm" class, which is a placeholder for the code that we will add there in the next section:

package simple;

import domain.Customer;
import javax.swing.JComponent;
import javax.swing.JPanel;
import org.springframework.richclient.form.AbstractForm;

public class CustomerForm extends AbstractForm {

CustomerForm(Customer customer) {
super(customer);
setId("customer");
}

@Override
protected JComponent createFormControl() {
JPanel panel=new JPanel();
return panel;
}

}

 

In line 12 above, we set the form's ID to "customer". This is a unique ID that needs to be passed in the constructor and is used for label construction. As a result, we need to bear this ID in mind when setting the form's title and description, because these are used to set the labels in the form, in the messages.properties file:

customer.title=Customer Information
customer.description=Enter the details of the customer below.

 

Now, back in the CustomerView, let the PropertiesExecutor open the dialog that you created above:

private class PropertiesExecutor extends AbstractActionCommandExecutor {

@Override
public void execute() {
new CustomerPropertiesDialog(customerTable.getSelectedCustomer()).showDialog();
}

}

 

The code above refers to a method in the CustomerTable that you have not created yet. Open that class and then add the following to it, for retrieving the data for the currently selected row in the table:

public Customer[] getSelectedCustomers() {
int[] selected = getTable().getSelectedRows();
Customer[] customer = new Customer[selected.length];
for (int i = 0; i < selected.length; i++) {
customer[i] = (Customer) getTableModel().getElementAt(selected[i]);
}
return customer;
}

public Customer getSelectedCustomer() {
return (Customer) getSelectedCustomers()[0];
}

 

Run the application again and this time when you invoke the Properties popup item, you should see the following result:

 

Using the Form Builder

Now we use the Spring RCP Form Builder.

You will see that the Form Builder lets you

  • create the form's layout very easily

  • while, magically, removing the need to worry about the type of Swing components you want to have rendered for the fields to which you want to give your users access.

Start off by replacing the content of your existing CustomerForm with the code below:

package simple;

import javax.swing.JComponent;
import javax.swing.JTextField;

import org.springframework.richclient.form.AbstractForm;
import domain.Customer;
import org.springframework.richclient.form.builder.TableFormBuilder;

public class CustomerForm extends AbstractForm {

private JComponent firstNameField;

public CustomerForm(Customer customer) {
super(customer);
setId("customer");
}

@Override
protected JComponent createFormControl() {
TableFormBuilder formBuilder = new TableFormBuilder(getBindingFactory());
formBuilder.setLabelAttributes("colGrId=label colSpec=right:pref");
formBuilder.addSeparator("General");
formBuilder.row();
firstNameField = formBuilder.add("firstName")[1];
formBuilder.add("lastName");
formBuilder.row();
formBuilder.addSeparator("Address");
formBuilder.row();
formBuilder.add("address.street");
formBuilder.row();
formBuilder.add("address.city", "colSpan=1 align=left");
formBuilder.row();
formBuilder.add("address.state", "colSpan=1 align=left");
formBuilder.row();

JComponent zipField = formBuilder.add("address.zip", "colSpan=1 align=left")[1];
((JTextField) zipField).setColumns(8);
formBuilder.row();

return formBuilder.getForm();
}

public boolean requestFocusInWindow() {
return firstNameField.requestFocusInWindow();
}

}

 

Note: It seems to me that a central problem with so many strings being set in the Form Builder (and elsewhere in Spring RCP applications) is that an IDE is not going to be very helpful in providing you with hints (or code completion or intellisense, call it what you will). How is one supposed to know of the existence of properties such as "colSpan" and "align" in lines 32, 34, and 37 above? Only be reading the documentation. I haven't yet found documentation on the above properties. If I were able to use code completion in my IDE, I wouldn't need documentation at all. But strings do not encourage code completion. However, it is clear, from the above lines of code (and the screenshot below), that one can influence the width (and so on...) of fields displayed in a Spring RCP AbstractForm.

Now, when you run the application again and then invoke the Properties popup item, you should now see this:

 

However, since all our fields are strings, the true power of the Spring RCP Form Builder is not really proven yet. To drive the point home, go back to the Customer domain object. There, add a new boolean with the name "married", together with a getter and setter:

private boolean married;

public boolean getMarried() {
return married;
}

public void setMarried(boolean married) {
this.married = married;
}

 

Next, in the CustomerDataStore, add the boolean to the "makeCustomer" method:

private Customer makeCustomer(
String first, String last, boolean married, String street,
String city, String state, String zip) {

Customer customer = new Customer();
customer.setId(nextId++);
customer.setFirstName(first);
customer.setLastName(last);
customer.setLastName(last);
customer.setMarried(married);

Address address = customer.getAddress();
address.setStreet(street);
address.setCity(city);
address.setState(state);
address.setZip(zip);

return customer;

}

 

Finally, in the "loadData" method, again in the CustomerDataStore, add a "true" or a "false" to each of your customers, depending on whether you want them to be married or single:

private void loadData() {
customers.add(makeCustomer(
"Larry", "Streepy", true, "123 Some St.", "New York", "NY", "10010"));
customers.add(makeCustomer(
"Keith", "Donald", false, "456 WebFlow Rd.", "Cooltown", "NY", "10001"));
customers.add(makeCustomer(
"Steve", "Brothers", true, "10921 The Other Street", "Denver", "CO", "81234-2121"));
customers.add(makeCustomer(
"Carlos", "Mencia", false, "4321 Comedy Central", "Hollywood", "CA", "91020"));
customers.add(makeCustomer(
"Jim", "Jones", true, "1001 Another Place", "Dallas", "TX", "71212"));
customers.add(makeCustomer(
"Jenny", "Jones", false, "1001 Another Place", "Dallas", "TX", "75201"));
customers.add(makeCustomer(
"Greg", "Jones", false, "9 Some Other Place", "Chicago", "IL", "60601"));
}

 

OK. Now simply add the "married" field to the CustomerForm.createFormControl, as shown here:

@Override
protected JComponent createFormControl() {
TableFormBuilder formBuilder = new TableFormBuilder(getBindingFactory());
formBuilder.setLabelAttributes("colGrId=label colSpec=right:pref");
formBuilder.addSeparator("General");
formBuilder.row();
firstNameField = formBuilder.add("firstName")[1];
formBuilder.add("lastName");
formBuilder.row();
formBuilder.add("married");
formBuilder.row();
formBuilder.addSeparator("Address");
formBuilder.row();
formBuilder.add("address.street");
formBuilder.row();
formBuilder.add("address.city", "colSpan=1 align=left");
formBuilder.row();
formBuilder.add("address.state", "colSpan=1 align=left");
formBuilder.row();

JComponent zipField = formBuilder.add("address.zip", "colSpan=1 align=left")[1];
((JTextField) zipField).setColumns(8);
formBuilder.row();

return formBuilder.getForm();
}

 

Notice that above you didn't do anything different for the "married" field than you did for any of the others. One small step you need to do still at this point: add a new property in the messages.properties, for the label of the field that will be displayed on the form:

married.label=Married?

 

Now, when you run the application, you see that the "Married?" label is next to a checkbox, because the Form Builder understood that that is what needs to be created when the field's type is a boolean:

 

In summary, the Spring RCP Form Builder lets you easily create complex form layouts, without requiring you to use a GUI Builder, such as the Matisse GUI Builder. And, in addition to the TableFormBuilder that you've seen demonstrated in this section, there's also a GridBagLayoutFormBuilder and an HTMLFormBuilder, together with an AbstractFormBuilder which, I imagine, could be used to build your own custom Form Builders.

 

Adding Rules Based Validation

Next we set some rules for field validation.

As the user types, feedback needs to be given about the validity of the entered text.

Spring RCP validation rules are provided separately from the domain object, although they are, in this case, within the same package.

The validation rules need to be registered in the richclient-application-context.xml, as shown at the end of this section.

package domain;

import org.springframework.core.closure.Constraint;
import org.springframework.rules.Rules;
import org.springframework.rules.support.DefaultRulesSource;

public class SimpleValidationRulesSource extends DefaultRulesSource {

private final Constraint NAME_CONSTRAINT = all(new Constraint[]{required(), minLength(2),
regexp("[-'.a-zA-Z ]*", "alphabeticConstraint")
});
private final Constraint ZIPCODE_CONSTRAINT = all(new Constraint[]{required(), minLength(5), maxLength(10),
regexp("[0-9]{5}(-[0-9]{4})?", "zipcodeConstraint")
});

public SimpleValidationRulesSource() {
super();
addRules(createCustomerRules());
}

private Rules createCustomerRules() {

return new Rules(Customer.class) {
@Override
protected void initRules() {
add("firstName", NAME_CONSTRAINT);
add("lastName", NAME_CONSTRAINT);
add(not(eqProperty("firstName", "lastName")));
add("address.street", required());
add("address.state", required());
add("address.zip", ZIPCODE_CONSTRAINT);
}
};

}

}

 

Now we need to register the class in the richclient-application-context.xml. Anywhere within that file, add the following:

<bean id="rulesSource" class="domain.SimpleValidationRulesSource" />

 

Validating forms will interrogate the rules source for rules that apply to the class of a form object, which in this case is the "Customer" object. Therefore, when the user types something that breaks the rules, Spring RCP will give a warning and disable the OK button, as shown below:

 

 

Conclusion

Though the application is by no means complete (and even the modification code is very rudimentary, just enough is there to perform the modification, but not much more), many of Spring RCP's unique treasures have been covered in this article—in particular, you have seen how the Spring RCP Form Builder and its rules based validation can be used within the context of Swing applications. In general, you have seen how these features fit together within the context of a Spring RCP application that uses views, dialogs, and forms.

(And now continue to the next part!) 

 

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}