Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Pass list of strings to custom DMI

    I'm trying to pass a List of Strings to our custom DMI. I keep getting "cannot cast String to Collection" exceptions.

    The DSRequest payload debug output shows something like:
    Code:
    ...
    values:{
        stringList:"[string A, string B, string 0, string 3, string 6]",
    }
    ...
    Below are the relevant code snippets...

    Code to set attribute:
    Code:
    // otherList is an ArrayList<String>
    valuesManager.setValue("stringList", record.getAttribute("otherList"));
    Custom DMI:
    Code:
    public DSResponse add(DSRequest dsRequest) throws Exception {
        Map<String,Object> map = dsRequest.getValues();
        
        List<String> coiRecords = ((List<List<String>>) map.remove("stringList")).get(0);
    
    ...
    ds.xml:
    Code:
    <field multiple="true" name="stringList" type="text" />
    ...not sure if multiple should be set for in the ds file.

    I tried changing it to a string array then calling ValuesManager.setAttributeAsStringArray but I didn't have much luck there.

    Thanks for your help in advance!

    #2
    Seeing this in the Dev Console:

    Code:
    ...
    values:{
        stringList:"[string A, string B, string 0, string 3, string 6]",
    }
    ...
    .. means you've passed a single String, and not a List or Array of Strings. So, yes, use ValuesManager.setAttributeAsStringArray() to provide the value - once you see it leave the browser as an actual String[], your server-side code looks fine.

    Comment


      #3
      I changed the client-side code to use setAttributeAsArray. I also had to change the type of what I was passing from List<String> to String[] because it was causing JavaScriptObject conversion exceptions.

      Now I get this in the output:
      Code:
      stringList:"[Ljava.lang.String;@3d342e"
      and this exception:
      Code:
      java.lang.ClassCastException: java.lang.String cannot be cast to java.util.List
      I then try to change my server code to:
      Code:
      String[] stringList = ((List<String[]>) map.remove("stringList")).get(0);
      then I get this exception:
      Code:
      java.lang.ClassCastException: java.lang.String cannot be cast to [Ljava.lang.String;

      Comment


        #4
        I also tried changing the server code to
        Code:
        String[] stringList= (String[]) map.remove("stringList");
        But then I got:
        Code:
        java.lang.ClassCastException: java.util.ArrayList cannot be cast to [Ljava.lang.String;

        Comment


          #5
          Never mind the various server consequences until you see an actual String Array being transmitted, which will look like this:

          Code:
          ...
          values:{
              stringList:["string A","string B","string 0","string 3","string 6"],
          }
          ...
          The question is how your string array is getting mangled before getting to the server. Can you show complete code for applying a String[] as a value on a ValuesManager such that it ends up somehow not as a String[] in the RPC tab? Also please indicate exact version, browser, etc.

          Comment


            #6
            Thanks for the tip. I just noticed we call the setValue method (I know it's not recommended but it's for MVP purposes) that takes a String and an Object then it calls the specific setValue method with the specific type.

            Here's the code for that:
            Code:
            /**
             * Takes a general Object and calls a specialized setValue method
             * 
             * @param key   key of value to set
             * @param value value to set
             */
            @SuppressWarnings("rawtypes")
            @Override
            public void setValue(String key, Object value) {
                if (key == null) {
                    throw new IllegalArgumentException("Attempting to set null key with value: " + value);
                }
                
                if (value == null) {
                    throw new IllegalArgumentException("Attempting to set null value for key: " + key);
                }
                
                if (value instanceof Boolean) {
                    super.setValue(key, (Boolean) value); 
                } else if (value instanceof DataClass) {
                    super.setValue(key, (DataClass) value); 
                } else if (value instanceof DataClass[]) {
                    super.setValue(key, (DataClass[]) value); 
                } else if (value instanceof Date) {
                    this.setValue(key, (Date) value); 
                } else if (value instanceof Double) {
                    super.setValue(key, (Double) value); 
                } else if (value instanceof JavaScriptObject) {
                    super.setValue(key, (JavaScriptObject) value);
                } else if (value instanceof Map) {
                    super.setValue(key, (Map) value); 
                } else if (value instanceof Record) {
                    super.setValue(key, (Record) value); 
                } else if (value instanceof Record[]) {
                    super.setValue(key, (Record[]) value);
                } else if (value instanceof String){
                    // Do not call toString() on a String. GWT contains a bug when casting a String to a String
                    super.setValue(key, (String) value);
                } else {
                    super.setValue(key, value.toString());
                }
            }
            This would explain the result from the debug output as a toString() of a String[] would output something like that.

            I looked at the javadoc for ValuesManager and didn't see a setValues(String,String[]) so I was wondering how we should call setValues with the String array.

            We're using a nightly build from 9/28/10 of 2.3 (waiting for schedule to allow to upgrade to 2.4) in IE7.

            Comment


              #7
              Not sure which setValue() this is, but this should be corrected in 2.4. If you need a workaround for 2.3 (seems like upgrading now is the best workaround) you can create a JavaScriptObject representing a JavaScript Array of String and use that with the setValue() method.

              Comment


                #8
                I'm sorry--I meant to say that was a setValue method we wrote on our end to facilitate MVP pattern.

                I added a new case to the method and was able to convert the String[] argument to a JavaScriptObject:
                Code:
                ...
                } else if (value instanceof Object[]) {
                    // Convert to JavaScriptObject
                    super.setValue(key, JSOHelper.arrayConvert((Object[]) value));
                }
                ...
                It then showed up on the server side as a List<String>. Thanks for all your help!

                Comment

                Working...
                X