참조 : 자바빈 Property Editors

Petclinic의 petForm.jsp 파일을 보면 다음과 같은 코드가 있습니다.

    <tr>
      <th>
        Type: <form:errors path="type" cssClass="errors"/>
        <br/>
        <form:select path="type" items="${types}"/>
      </th>
    </tr>

여기서 굵은 글씨에 주목해야 합니다. type은 문자열 타입이 아닙니다. 스프링이 기본으로 제공해주는 PropertyEditor들이 primitive 타입들과 그것의 배열들은 알아서 바인딩 해주지만, 저 타입은 스프링이 알지 못합니다. 따라서 자동으로 바인딩이 되지 않을 겁니다. 따라서 저 것은 그냥 객체입니다.

그런데, 문자열이 올 자리에 객체가 와서 그런건지, toString()이 호출 됩니다. 그리고 PetType 클래스에는 toString을 다음과 같이 구현해 뒀습니다.

    public String toString() {
        return this.getName();
    }

오호.. 그럼 저 자리에 문자열이 채워지고 따라서 getAsString() 메소드를 구현할 필요가 없어졌습니다. 그래서 그런지 PetTypeEditor 클래스에는 정말 getAsString()이 없습니다.

public class PetTypeEditor extends PropertyEditorSupport {

    private final Clinic clinic;

    public PetTypeEditor(Clinic clinic) {
        this.clinic = clinic;
    }

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        for (PetType type : this.clinic.getPetTypes()) {
            if (type.getName().equals(text)) {
                setValue(type);
            }
        }
    }

}

하지만 어디까지나 저런 경우는 특수한 경우일테니까요.(PetType에 속성이 name밖에 없더군요.) 대부분의 경우에는 getAsText()를 구현해서 써야겠죠.

public String getAsText() {
  Calendar value = (Calendar) getValue();
  return (value != null ?
    this.dateFormat.format(value.getTime()) :
    “”
  );
}

위 코드는 여기서 참조했습니다. getValue()를 사용해서 value 객체를 가져온 다음 이 객체가 가지고 있는 속성을 사용해서 문자열(String)을 만들어서 반환하고 있습니다.

이렇게 만들어 둔 Propery Editor를 스프링이 사용하도록 등록하는 방법이 있습니다. 여러 군대에서 사용되는 Property Editor라면

    <bean name="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
        <property name="customEditors">
            <map>
                <entry key="java.util.regex.Pattern">
                    <bean class="PatternPropertyEditor"/>
                </entry>
            </map>
        </property>
    </bean>

이렇게 스프링 설정 파일에 있는 <property>의 value 값에 적용됩니다.

컨트롤러에서 사용할 거라면... 폼 컨트롤러 안에 다음과 같은 코드를 추가합니다.

protected void initBinder(HttpServletRequest request,
    ServletRequestDataBinder binder)
    throws Exception {
    binder.registerCustomEditor(
      Calendar.class,
      new CustomCalendarEditor(
        new SimpleDateFormat(“dd/MM/yyyy”), true));
  }

Spring 2.5에서는 다음과 같이 추가합니다.

@InitBinder
    public void initBinder(WebDataBinder binder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        dateFormat.setLenient(false);
        binder.registerCustomEditor(Date.class, new CustomDateEditor(
                dateFormat, false));
    }

음... 이제 JSP의 EL에서 member.department.departmentid 이렇게 길게 쓰지 않아도 되겠습니다. 그냥 member.department 라고 써도 커스텀 에디터가 ember.department.departmentid 이렇게 쓴거나 동일하게 처리해 줄 것 입니다.