If you like digging into tapestry I suggest you start by removing beanutils dependancy and adding: @Inject private PropertyAccess propertyAccess;
into SelectObject.java after that use propertyAccess instead of beanutils... .... I'm currently building a version that doesn't need SelectObject component, but uses normal select component. The code is more complicated than it should be, so I suppose I might post an enhancement ticket for the Select component. ... if you like to start with working code ... here's the changed version that works for me ... ------------------------------------------------------------------------------------------------------------------------------------------- package test.tapestry; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import org.apache.tapestry.OptionGroupModel; import org.apache.tapestry.OptionModel; import org.apache.tapestry.internal.OptionModelImpl; import org.apache.tapestry.ioc.services.PropertyAccess; import org.apache.tapestry.ioc.services.PropertyAdapter; import org.apache.tapestry.util.AbstractSelectModel; /** * @author jued * * @param <T> */ public class GenericSelectionModel<T> extends AbstractSelectModel { private String labelField; private List<T> list; private final PropertyAccess adapter; public GenericSelectionModel(List<T> list, String labelField, PropertyAccess adapter) { this.labelField = labelField; this.list = list; this.adapter = adapter; } public List<OptionGroupModel> getOptionGroups() { return null; } public List<OptionModel> getOptions() { List<OptionModel> optionModelList = new ArrayList<OptionModel>(); for (T obj : list) { if (labelField == null) { optionModelList.add(new OptionModelImpl(obj + "", false, obj, new String[0])); } else { optionModelList.add(new OptionModelImpl( adapter.get(obj, labelField)+"", false, obj, new String[0])); } } return optionModelList; } } ------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------- package test.tapestry; import java.lang.reflect.InvocationTargetException; import java.util.List; import org.apache.tapestry.ValueEncoder; import org.apache.tapestry.ioc.services.PropertyAccess; import org.apache.tapestry.ioc.services.PropertyAdapter; public class GenericValueEncoder<T> implements ValueEncoder<T> { private List<T> list; private final PropertyAccess access; private final String fieldName; public GenericValueEncoder(List<T> list, String fieldName, PropertyAccess propertyAccess) { this.list = list; this.fieldName = fieldName; this.access = propertyAccess; } public String toClient(T obj) { if (fieldName == null) { return obj + ""; } else { return access.get(obj,fieldName)+""; } } public T toValue(String string) { for (T obj : list) { if (fieldName == null) { if ((obj + "").equals(string)) { return obj; } } else { if (access.get(obj, fieldName).equals(string)) { return obj; } } } return null; } } ------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------- package test.tapestry.components; import java.util.List; import java.util.Locale; import org.apache.tapestry.Binding; import org.apache.tapestry.ComponentResources; import org.apache.tapestry.FieldValidator; import org.apache.tapestry.MarkupWriter; import org.apache.tapestry.OptionModel; import org.apache.tapestry.SelectModel; import org.apache.tapestry.SelectModelVisitor; import org.apache.tapestry.ValidationException; import org.apache.tapestry.ValidationTracker; import org.apache.tapestry.ValueEncoder; import org.apache.tapestry.annotations.BeforeRenderTemplate; import org.apache.tapestry.annotations.Environmental; import org.apache.tapestry.annotations.Inject; import org.apache.tapestry.annotations.Parameter; import org.apache.tapestry.corelib.base.AbstractField; import org.apache.tapestry.internal.util.SelectModelRenderer; import org.apache.tapestry.ioc.services.PropertyAccess; import org.apache.tapestry.services.FieldValidatorDefaultSource; import org.apache.tapestry.services.FormSupport; import org.apache.tapestry.services.Request; import org.apache.tapestry.services.ValueEncoderFactory; import org.apache.tapestry.services.ValueEncoderSource; import org.apache.tapestry.util.EnumSelectModel; import test.tapestry.GenericSelectionModel; import test.tapestry.GenericValueEncoder; /** * Select an item from a list of values, using an [X]HTML <select> element on the client side. * An validation decorations will go around the entire <select> element. * <p> * A core part of this component is the [EMAIL PROTECTED] ValueEncoder} (the encoder parameter) that is used to * convert between server-side values and client-side strings. In many cases, a [EMAIL PROTECTED] ValueEncoder} * can be generated automatically from the type of the value parameter. The * [EMAIL PROTECTED] ValueEncoderSource} service provides an encoder in these situations; it can be overriden * by binding the encoder parameter, or extended by contributing a [EMAIL PROTECTED] ValueEncoderFactory} into * the service's configuration. */ public final class SelectObject extends AbstractField { private class Renderer extends SelectModelRenderer { public Renderer(MarkupWriter writer) { super(writer, _encoder); } @Override protected boolean isOptionSelected(OptionModel optionModel) { Object value = optionModel.getValue(); return value == _value || (value != null && value.equals (_value)); } } @Inject private FieldValidatorDefaultSource _fieldValidatorDefaultSource; @Inject private Locale _locale; @Inject private PropertyAccess propertyAccess; @Parameter(required = true) private List<Object> _list; @Parameter private String _labelField = null; // Maybe this should default to property "<componentId>Model"? /** * The model used to identify the option groups and options to be presented to the user. This * can be generated automatically for Enum types. */ // @Parameter(required = true) // private SelectModel _model; private GenericSelectionModel<Object> _model; /** * Allows a specific implementation of [EMAIL PROTECTED] ValueEncoder} to be supplied. This is used to * create client-side string values for the different options. * * @see ValueEncoderSource */ // @Parameter // private ValueEncoder _encoder; private GenericValueEncoder<Object> _encoder; @Inject private Request _request; @Inject private ComponentResources _resources; @Environmental private ValidationTracker _tracker; /** Performs input validation on the value supplied by the user in the form submission. */ @Parameter(defaultPrefix = "validate") @SuppressWarnings("unchecked") private FieldValidator<Object> _validate = NOOP_VALIDATOR; /** The value to read or update. */ @Parameter(required = true, principal = true) private Object _value; @Inject private ValueEncoderSource _valueEncoderSource; @Override protected void processSubmission(FormSupport formSupport, String elementName) { _encoder = new GenericValueEncoder<Object>(_list, _labelField, propertyAccess); String primaryKey = _request.getParameter(elementName); Object selectedValue = _encoder.toValue(primaryKey); try { _validate.validate(selectedValue); _value = selectedValue; } catch (ValidationException ex) { _tracker.recordError(this, ex.getMessage()); return; } } void afterRender(MarkupWriter writer) { writer.end(); } void beginRender(MarkupWriter writer) { writer.element("select", "name", getElementName(), "id", getClientId()); _encoder = new GenericValueEncoder<Object>(_list, _labelField, propertyAccess); _model = new GenericSelectionModel<Object>(_list, _labelField, propertyAccess); // Disabled, informals via mixins } @SuppressWarnings("unchecked") ValueEncoder defaultEncoder() { return _valueEncoderSource.createEncoder("value", _resources); } @SuppressWarnings("unchecked") SelectModel defaultModel() { Class valueType = _resources.getBoundType("value"); if (valueType == null) return null; if (Enum.class.isAssignableFrom(valueType)) return new EnumSelectModel(valueType, _resources.getContainerMessages()); return null; } /** * Computes a default value for the "validate" parameter using * [EMAIL PROTECTED] FieldValidatorDefaultSource}. */ FieldValidator defaultValidate() { Class type = _resources.getBoundType("value"); if (type == null) return null; return _fieldValidatorDefaultSource.createDefaultValidator( this, _resources.getId(), _resources.getContainerMessages(), _locale, type, _resources.getAnnotationProvider("value")); } Binding defaultValue() { return createDefaultParameterBinding("value"); } @BeforeRenderTemplate void options(MarkupWriter writer) { SelectModelVisitor renderer = new Renderer(writer); _model.visit(renderer); } // For testing. void setModel(GenericSelectionModel model) { _model = model; } void setValue(Object value) { _value = value; } void setValueEncoder(GenericValueEncoder encoder) { _encoder = encoder; } } ------------------------------------------------------------------------------------------------------------------------------------------- On 8/29/07, Marcelo lotif <[EMAIL PROTECTED]> wrote: > > Hi Davor, > Can you send it to me? > > 2007/8/29, Davor Hrg <[EMAIL PROTECTED]>: > > > > thnx, > > very nice example, > > > > I've liked it and modified it to use Tapestry builtin service: > > PropertyAccess > > instead of beanutils. If you like I can update the wiki.. > > > > Davor Hrg > > > > On 8/28/07, Marcelo lotif <[EMAIL PROTECTED]> wrote: > > > > > > http://wiki.apache.org/tapestry/Tapestry5SelectObject > > > > > > -- > > > Atenciosamente, > > > Marcelo Lotif > > > > > > > > > -- > Atenciosamente, > Marcelo Lotif >