Проблема PropertyEditor с типом Set

Использование: Портлет Spring 3.2 MVC с Liferay 5.2.3 и Tomcat 6.0.18

Я пытаюсь создать PropertyEditor для преобразования между Set<Type> и String и обратно. Я успешно получил Set<Type> до String для работы без проблем. Но я не могу заставить редактор свойств распознаваться в обратном направлении. Я сделал это успешно с Type -> String -> Type, но преобразование для Set ускользает от меня.

Я определил, что метод SetAsText никогда не вызывается, и я получаю ошибку времени выполнения, которая показывает, что преобразование не было выполнено. Информация о свойствах Editors очень скудна, и, за одним или двумя исключениями, единственные неясно связанные проблемы, которые я смог найти, имеют возраст 4 или более лет.

Либо я упускаю что-то настолько фундаментальное, что не вижу этого, либо это что-то более глубокое в структуре, но я был бы признателен за любую помощь или предложения.

Вот фрагмент @InitBinder из моего контроллера:

@InitBinder("formBacking")
public void initBinder(WebDataBinder binder){
    binder.registerCustomEditor(Set.class, "field", new SetEditor(listService, Set.class));
    logger.info("FormBacking Binder initialization");
}

Вот мой редактор свойств:

public class SetEditor extends PropertyEditorSupport {
   protected static Logger logger = Logger.getLogger("PropertyEditor");

   private ListService listService;

   public SetEditor(ListService listService, Class clazz) {
    super(clazz);
    this.listService = listService;
   }

   @Override
   public String getAsText() {
    Stack<String> returnString = new Stack<String>();
    Set<Type> types = new HashSet<Type>();
    try {
        types = (Set<Type>)this.getValue();
        for (Type type:types) {
            returnString.push(type.getTypeId().toString());
        }
    } catch (NullPointerException e) {
        logger.info("getAsText is \"\"");
        return "";
    } catch (Exception e) {
        logger.info("getAsText Other Exception: " + e.getMessage());
        return "";
    }
    return "[" + StringUtils.collectionToDelimitedString(returnString,",") + "]";  // a very useful Spring Util
   }

   @Override
   public void setAsText(String text) throws IllegalArgumentException {
    Type type = new Type();
    Set<Type> result = new HashSet<Type>();
    try {
        String[] typeArray = text.split("[,]");  //this may not be correct, but I can't get here to debug it!!
        for(String type:typeArray) {
            if(!type.isEmpty()) {
                type = listService.getType(Long.valueOf(text));
                result.add(type);
            }
        }
    }catch(NullPointerException e) {
            logger.info("SetAsText is \"\" ");
        setValue(null);
    }
    catch(Exception e) {
        logger.info("setAsText Other Exception: " + e.getMessage());
    }
    setValue(result);
   }

}

Фрагмент класса Type:

@Entity(name="Type")

@Table(name="type")
public class Type {

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "playListImages",
    joinColumns={@JoinColumn(name="superTypeId")},
    inverseJoinColumns={@JoinColumn(name="typeId")})
private Set<Type> types = new HashSet<Type>();

getters and setters...

person pjl55    schedule 10.09.2013    source источник


Ответы (1)


Надеюсь, это поможет любому, кто пытался решить эту проблему.

После небольшого дальнейшего расследования (т.е. включения ведения журнала трассировки) выяснилось, что Spring Annotations не полностью регистрирует PropertyEditors, связанные с Set (возможно, Collections в целом, хотя я этого не проверял). Трассировка показала, что встроенный CustomCollectionEditor вызывается (но только при преобразованиях String -> Type), хотя я зарегистрировал свой собственный редактор.

Это, имхо, ошибка Spring Annotations. Обходной путь, который полностью работает, как я и ожидал, заключается в создании собственного регистратора редактора свойств и регистрации редактора свойств в файле конфигурации xxx-portlet.xml.

Например: project-portlet.xml должен содержать что-то вроде этих строк:

    <bean class="org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter">
       <property name="webBindingInitializer">
          <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
             <property name="propertyEditorRegistrars">
                <list>
                   <ref bean="myPropertyEditorRegistrar" />
                </list>
             </property>
         </bean>
      </property>
   </bean>

<bean id="myPropertyEditorRegistrar"
class="com.sbeko.slider.util.MyPropertyEditorRegistrar" />

Класс регистрации:

public class MyPropertyEditorRegistrar implements PropertyEditorRegistrar {

   public void registerCustomEditors(PropertyEditorRegistry registry) 
             {registry.registerCustomEditor(Set.class, new TypeEditor(Set.class));
}
person pjl55    schedule 11.09.2013