Question

UPDATED: This may turn out to be a Grails bug. Please see:

I'm up against a curious problem where data binding is failing if the incoming XML request body contains a collection of 1 element. For 2 or more elements all is well.

I have the following command object:

class MyCommand { 
    Set<Something> somethings 
} 

And I have the following POGO (not a domain class):

class Something { 
    String name 
} 

I'm using the command like so:

def save(MyCommand command) { 
    respond command 
} 

All is well for the following input:

    <myCommand>
            <somethings>
                    <something>
                            <name>Something 1</name>
                    </something>
                    <something>
                            <name>Something 2</name>
                    </something>
            </somethings>
    </myCommand>

But not for this input:

    <myCommand>
            <somethings>
                    <something>
                            <name>Something 1</name>
                    </something>
            </somethings>
    </myCommand>

I see the following server error (Grails tried to effectively call "new Set()"):

java.lang.NoSuchMethodException: java.util.Set.<init>() 

Here's the interesting part: If I make Something a domain object by moving it under the "domain" Grails dir, the above error does not occur. Meaning, even though the request body contains a single element XML collection, Grails will create a Set with a single element and there are no exceptions thrown.

Additionally, if the request body contains JSON instead of XML, all is well even without use of domain objects: the request can contain a single element collection and Grails still instantiates my command object correctly. I presume this works because JSON explicitly defines the collection type.

Question: How can I use command objects and still consume requests that contain single-element XML collections?

Technically I could write my own binding for this property with @BindUsing and check if the source map is a non-collection, if so then make it a single-element collection. But this won't work for me because I've oversimplified the problem, and Something has many nested properties of its own, so trying to create an instance of it would require lots of manual work.

Thanks in advance for your help. :-)

Was it helpful?

Solution

This turned out to be a Grails bug which will be resolved for 2.3.7: http://jira.grails.org/browse/GRAILS-11175

OTHER TIPS

I ve got the same issue in my project (on rails). When for example rails converts xml to hash, it converts single-element-collection to hash (not array) but if there are more than 1 element, ROR converts it to array of hashes (correct). Its a problem of xml collections.

My sollution was to add a dummy element to collections, so I was shure that one-element-collections (that are now 1+dummy = 2 element collections) are converted to arrays.

<myCommand>
        <somethings>
                <something>
                        <name>Something 1</name>
                </something>
                <something>
                        <name>dummy</name>
                </something>
        </somethings>
</myCommand> 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow