Announcement Announcement Module
Collapse
No announcement yet.
Nested object's properties labels & validation Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Nested object's properties labels & validation

    I am having two (related) problems with nested object properties. The first is that the form is not displaying the labels for a nested object's properties. The second is that no validations (i.e. RuleSource...) are applied to the nested object's properties either. If the nested object is put on the form by itself, the labels and validation show up on the form.

    Example,

    Code:
    class Aggregate
     Child child;
     Child getChild() {return child;}
    
    class Child
     String value;
     String getValue(){return value;}
    In the message file,
    Code:
    value.label=Value:
    If an instance of Child is put on to a form, the label "Value:" show up.

    On the form for Aggregate, I have added "child.value" on the form but the label for value did not show up. The string "child.value.label" is displayed instead. The validation for value is not applied to the field either.

    I have found two workarounds so far for the labels part of the problem; both of which seem rather kludgy. The first, is to add another entry in the message file... i.e.

    Code:
    child.value.label=Value
    value.label=Value
    Shouldn't it be able to pick up the label for value for the nested object child instead of having to duplicate the entries in the message file?

    The second is for a to "nest" itself. e.g.

    Code:
    class Child
    {
      String value;
      String getValue(){return value;}
      Child getChild()
      {
          return this;
      }
    }
    This way I can have 1 entry in the message file, but writing a getter to get a reference to an instance of myself seems a bit odd.

    Any comments, folks?
    Thanks

    Henry

  • #2
    hszetu,

    I've refined the message key lookup strategy; it will now try to "unroll" any nested form property paths e.g. for the path "child.value" the system will first check for a message with key "child.value.label" and if that fails it will check for the key "value.label".

    I'm not sure about the validation problem you should probably file a bug in Jira.

    Ollie

    Comment


    • #3
      Thanks Ollie for your prompt response.

      Another question?

      If I have a common field name that I want to have different labels, how would I specify it in the message.properties file? For example, class Customer and class Employee, both have the field called "name". How do I configure my messages.properties file (and other files) such that the customer form displays "Customer Name" and the Employee form displays "Employee Name"?

      Currently, the only way I have found to do this is to introduce a "self-nesting" method into each class - i.e. in the Customer class I add a "getCustomer()" method that returns "this", and similarly in the Employee class I add a "getEmployee()" method that returns "this". "This" being an instance to its respective object.

      Then in my messages.properties file, I have the following:
      employee.name.label=Employee Name
      customer.name.label=Customer Name

      Although this works, and seems quite elegant in most places, it seems a bit funny that I have to code a getXXXX() methods that return instances of themselves...

      Any better way of doing this or other thoughts?

      Henry

      Comment


      • #4
        If your customer/employee forms have an id then this will be also used for the message key lookup. So say the customer form has id "customerForm" then the folowing messages keys will be used to resolve the label:

        customerForm.name.label
        name.label

        HTH

        Ollie

        Comment


        • #5
          Originally posted by oliverhutchison
          If your customer/employee forms have an id then this will be also used for the message key lookup. So say the customer form has id "customerForm" then the folowing messages keys will be used to resolve the label:

          customerForm.name.label
          name.label
          Ollie, this is good idea. I thinking is good to also allow message key lookup based on class name of domain object. That way, if you having Customer on more than one form (may seem strange but is actually common), you have to put its "Customer Name" in message file only once.

          So, you can have something like this:
          Code:
          Customer.class.name.label=Customer Name
          Instead of this:
          Code:
          customerForm.name.label=Customer Name
          anotherCustomerForm.name.label=Customer Name
          andYesYetAnotherCustomerForm.name.label=Customer Name
          What you thinking about this one?

          Comment


          • #6
            I would agree with Stefano, that is a very nice feature to have if labels can be also based on domain object classes. As the client name will eventually be put on many other forms that display other info related to the client. So, we don't have to add the label for each form in the message file.


            I have just got Ollie's update from CVS, when I run the app, I got this exception.
            Code:
            java.lang.ArrayIndexOutOfBoundsException: 2
            	at org.springframework.binding.form.support.MessageSourceFormPropertyFaceDescriptorSource.insertKeys(MessageSourceFormPropertyFaceDescriptorSource.java:167)
            	at org.springframework.binding.form.support.MessageSourceFormPropertyFaceDescriptorSource.getMessageKeys(MessageSourceFormPropertyFaceDescriptorSource.java:157)
            	at org.springframework.binding.form.support.MessageSourceFormPropertyFaceDescriptorSource.getMessage(MessageSourceFormPropertyFaceDescriptorSource.java:137)
            	at org.springframework.binding.form.support.MessageSourceFormPropertyFaceDescriptorSource.loadFormPropertyFaceDescriptor(MessageSourceFormPropertyFaceDescriptorSource.java:89)
            	at org.springframework.binding.form.support.AbstractCachingPropertyFaceDescriptorSource.getFormPropertyFaceDescriptor(AbstractCachingPropertyFaceDescriptorSource.java:56)
            	at org.springframework.binding.form.support.AbstractFormModel.getFormPropertyFaceDescriptor(AbstractFormModel.java:200)
            	at org.springframework.richclient.forms.SwingFormModel.getFormPropertyFaceDescriptor(SwingFormModel.java:302)
            	at org.springframework.richclient.forms.SwingFormModel.createLabel(SwingFormModel.java:465)
            	at org.springframework.richclient.form.builder.AbstractFormBuilder.getLabelFor(AbstractFormBuilder.java:86)
            	at org.springframework.richclient.forms.JGoodiesBeanFormBuilder.add(JGoodiesBeanFormBuilder.java:59)
            ...
            The problem seems to be in the class MessageSourceFormPropertyFaceDescriptorSource

            Code:
            protected String[] getMessageKeys(FormModel formModel, String formPropertyPath, String faceDescriptorProperty) {
                    boolean hasFormId = StringUtils.hasText(formModel.getId());
                    String[] formPropertyPathElements = StringUtils.delimitedListToStringArray(formPropertyPath, ".");
                    String[] keys = new String[hasFormId ? 2*formPropertyPathElements.length : formPropertyPathElements.length];
                    int keyCount = 0;
                    if (hasFormId) {
                        String prefix = formModel.getId() + '.';
                        insertKeys(keys, 0, prefix, formPropertyPathElements, faceDescriptorProperty);            
                    }
                    insertKeys(keys, formPropertyPathElements.length, "", formPropertyPathElements, faceDescriptorProperty);   
                    return keys;
                }

            My form might not have a form id and using formPropertyPathElements.length as startIndex throws that exception. The proposed fix is

            Code:
                    int startIndex = 0;
                    if (hasFormId) {
                        String prefix = formModel.getId() + '.';
                        insertKeys(keys, startIndex, prefix, formPropertyPathElements, faceDescriptorProperty);
                        startIndex = formPropertyPathElements.length;
                    }
                    insertKeys(keys, startIndex, "", formPropertyPathElements, faceDescriptorProperty);   
                    return keys;

            Comment


            • #7
              I would agree with Stefano, that is a very nice feature to have if labels can be also based on domain object classes. As the client name will eventually be put on many other forms that display other info related to the client. So, we don't have to add the label for each form in the message file.
              If someone has the time to write a patch for this I'll be happy to review and commit the change.

              I have just got Ollie's update from CVS
              :oops: i obviously only tested with a form id. fixed.

              Ollie

              Comment


              • #8
                Hi,

                I have form with id='searchForm' and in this form I have a model with a property 'reference'. Now I want to set a label for this property.

                If add in the message.properties:

                Code:
                reference.label=&Reference
                it works

                but with

                Code:
                searchForm.reference.label=&Reference
                it does'nt?!?

                This prevent me to have the same propertyname in different forms having different label, because the formId is not taking into account in the search lable key.

                The form extends AbstractForm and it is create with

                Code:
                        SearchForm searchForm = new SearchForm(searchFormModel,"searchForm");
                Any Idea?

                Comment


                • #9
                  I think that labels are looked up by FormModel id, not Form id. Try passing "searchForm" to your model's constructor, or calling formModel.setId(...), if your model is a ConfigurableFormModel.

                  Comment


                  • #10
                    Thanks it works, I added a parameter in the creation method

                    Code:
                    ValidatingFormModel searchFormModel = FormModelHelper
                    				.createFormModel(searchModel,"searchFormModel");
                    and then I can use:

                    Code:
                    searchFormModel.reference.label=&Reference
                    Thanks
                    Dominique

                    Comment

                    Working...
                    X