Grails enlazan colección enum

In my grails app, I have this enum:

public enum RelationshipStatus{

  Single_Never_Married, 
  Separated,
  Divorced, 
  Widowed;  
}

I've defined this command object:

class MyCommand {
  List<RelationshipStatus> relationshipStatuses
}

which I use in one of my controller actions

def myAction = {MyCommand myCommand ->
}

when I submit a request to this action with parameters

user.relationshipStatuses=Separated&user.relationshipStatuses=Divorced

Eso espero myCommand.relationshipStatuses contendrá RelationshipStatus.Separated y RelationshipStatus.Divorced, but in fact it is null.

My understanding is that Grails automatically performs request param -> enum conversion based on the enum's name. Just it case it doesn't, I tried defining a property editor that does this conversion:

class RelationshipStatusEnumEditor extends PropertyEditorSupport {    

    public String getAsText() {
        value.name()
    }

    public void setAsText(String text) {
        RelationshipStatus.valueOf(text)
    }
}

I registered this editor with Grails/Spring and tried again, but the result was the same. Is it possible to bind request parameters to a Colección of Enum?

preguntado el 27 de agosto de 11 a las 17:08

I believe, that Grails do not know how to fill your list, as it discards the information on the List type (List<RelationshipStatus>). I am not sure, if it's possible. -

2 Respuestas

Using the databinder introduced in Grails 2.3, I came up with the following solution for converting request params to collection of enums. For example, given these enums

enum Gender {
    MALE, FEMALE
}

enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

and this command object

class MyCommand {
    Collection<Gender> genders
    Collection<Season> seasons
}

and assume we want to convert strings like "MALE,FEMALE" y "SPRING,SUMMER,WINTER" to the corresponding enum collections. Firstly, provide an implementation of FormattedValueConverter that does the conversion

class EnumCollectionConverter implements FormattedValueConverter {

   /**
    * To make other enums bindable, just add them to this list
    */
    private static final List<Class<Enum>> convertableEnums = [Gender, Season]

    @Override
    Object convert(value, String format) {

        Class<Enum> targetEnumClass = convertableEnums.find { it.simpleName == format }

        if (targetEnumClass) {
            List<String> enumConstantNames = value.toString().tokenize(',')
            return enumConstantNames.collect { targetEnumClass.valueOf(it) }
        }
        value
    }

    @Override
    Class<?> getTargetType() {

        // this class converts to a Collection<T extends Enum<T>> but the return value 
        // of this method can't be any more specific than Collection due to type erasure
        Collection
    }
}

Then register EnumCollectionConverter as a Spring bean in resources.groovy - it doesn't matter what name you choose for the bean. Then to use the class above to convert a comma-separated string to an num collection, annotate the relevant properties with

class MyCommand {
    @BindingFormat('Gender')
    Collection<Gender> genders

    @BindingFormat('Season')
    Collection<Season> seasons
}

El valor pasado al @BindingFormat should be the simple name of the enum type that will be stored in the bound collection.

Respondido el 24 de enero de 14 a las 15:01

As I know grails isn't filling List properties by default, if it's empty. Only if it's already exists, and indexes of items are passed.

Try to define this property as:

import org.apache.commons.collections.ListUtils
import org.apache.commons.collections.Factory

class MyCommand {
    List<RelationshipStatus> relationshipStatuses = ListUtils.lazyList([],{new RelationshipStatus()} as Factory)
}

and submit parameters as:

user.relationshipStatuses[0]=Separated&user.relationshipStatuses[1]=Divorced

Respondido 27 ago 11, 23:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.