Whiteship's Note

'@InitBinder'에 해당되는 글 1건

  1. 2008.11.27 PropertyEditor 활용 예제 (8)

PropertyEditor 활용 예제

Spring/Chapter 5 : 2008. 11. 27. 15:46


어제 올린 글에 이어지는 내용으로 스프링이 제공하는 form 태그와 PropertyEditor를 조합하는 방법입니다. PropertyEditor로 할 수 있는 일 중 하나를 스프링 form 태그가 해줍니다. 그게 뭐냐면.. getAsText죠.

<form:checkboxes items="${allRoles}" path="roles" delimiter="<br/>" itemLabel="note"  itemValue="id" /><br/>

여기서 보시면, itemValue에 설정한 id 값을 보고 자바빈 스펙에 따라 getId를 호출하여 해당 값을 각각의 체크박스 아이템의 value로 사용합니다. 편하죠, 대신 다른 반쪽이 없기 때문에 바인딩에러가 발생할 겁니다.

form 태그를 사용하여 값을 바인딩할 속성 roles는 Set<Role> 타입이거든요. id가 실제로는 int 값이지만, 화면에서는 String 값 형태로 전달되겠죠. 그 String 값을 Role 타입으로 캐스팅하려니까 에러가 발생하는 겁니다. 이 에러는 <form:errors path="roles" /> 이런 코드를 화면에 붙여두면 확인할 수 있습니다.

자.. 그럼 어떻게 해야되나요? HttpServletRequest 타입 객체를 메소드 매개변수로 추가해주고 거기서 roles라는 파라미터의 값 빼와서 파싱하고 어쩌구 저쩌구.. @.@ 그렇게 하실건가요? 스프링 2.5 이전 이라면 뭐.. 그럴수도 있겠다 싶지만, 서블릿 API에 의존하지 않은 아주 깔끔한 스프링 2.5 애노테이션 기반 컨트롤러에 저 것 때문에 서블릿 API를 사용할 건가요?? 아니죠. 그러고 싶지 않습니다.

네 그러지 않아도 됩니다. setAsText를 구현한 PropertyEditor를 등록해주면 깔끔하게 해결할 수 있습니다.

public class RolePropertyEditor extends PropertyEditorSupport {

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        if(!text.isEmpty())
            setValue(new Role(Integer.parseInt(text)));
    }

}

하이버를 사용하고 있으니 불 필요한 쿼리를 날리지 않도록 Fake Association Object를 활용하여 PropertyEditor를 구현합니다. 꼭 실제 객체가 필요하다면 DAO를 이용해서 가져올 수도 있겠죠. OSAF에는 두 종류의 GenericPropertyEditor로 그 두 가지 경우를 모두 지원합니다.

자 그리고 이 프로퍼티에디터를 바인더에 등록해주면 끝납니다.,

   @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Role.class, new RolePropertyEditor());
    }

끝~.. 이제 스프링이 Role이라는 도메인 객체를 알아보고 잘 파싱해서 Member의 Set<Role> 타입의 roles라는 속성에다가 잘 설정해 줄 겁니다.


'Spring > Chapter 5' 카테고리의 다른 글

PropertyEditor 활용 예제  (8) 2008.11.27
5. Validation, Data-binding, the BeanWrapper, and PropertyEditors  (0) 2007.03.21
top

  1. Favicon of http://kingori.egloos.com BlogIcon kingori 2008.11.27 16:52 PERM. MOD/DEL REPLY

    date 값 받아와서 처리하기 와 같은 단순한 propery 의 경우 헷갈리지 않는데, collection 형태의 경우 항상 헷갈리더라고요. 제시하신 예제와 같이 list 상의 하나의 item 에 대한 propertyEditor 인지, collection 에 대한 CustomCollectionEditor 의 형태인지. reference 의 property editor 부분을 읽어봐도 뭔가 개운치가 않고요.
    위의 예제의 경우에도 여러개의 role 이므로 받는 측의 role 속성도 collection 형태일텐데, 전에 작업할 때는 저런 형태가 잘 안먹히더군요. 제가 짠 코드를 다시 보니 하다하다 안되서 걍 req.getParameterValues 를 썼었네요. collection 을 다룰때 언제 CustomCollectionEditor 를 쓰고, 언제 그냥 collection 내의 하나의 항목에 대한 PropertyEditor 를 등록해야하는지 애매~하더군요.
    @조금 검색해보니 나오는 이 내용도 흥미롭네요. (쓰레드 마지막 부분)
    http://forum.springframework.org/showthread.php?t=40960

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2008.11.27 17:53 신고 PERM MOD/DEL

    컬렉션은(List, Set, Map까지) 스프링이 알아서 처리해줍니다. 대신 그 안에 들어있는 요소들의 타입들이 기본 타입이 아닐 경우에는 그런 처리를 하다가(첫번째 요소 처리 하다가) 캐스팅 에러가 발생합니다.

    즉 CollectionEditor가 필요한지는 모르겠구요. 위와 같이 컬렉션에 들어가는 엘리먼트에 대한 PropertyEditor만 만드시면 됩니다.

    링크 부분의 마지막 부분이 흥미롭다고 하셔서 그 부분만 봤더니, 마지막 분과 그 전 분 모두 위와 다중 선택이 필요하니 해결할 방법 있으면 알려달라는 거네요.ㅋㅋㅋ

    내용을 대충 보니까 위처럼 단순하게 속성의 값이 아니라 좀 더 조합해서 값을 보여줄 필요가 있나본데요 그럴 땐 PropertyEditor의 getAsText를 재정의해서 화면에 보여줄 형태를 만들어서 반환해주면 되는데요. 뭐가 문젠지 모르겠네요. @.@

  2. Favicon of http://kingori.egloos.com BlogIcon kingori 2008.11.27 19:23 PERM. MOD/DEL REPLY

    그런데 복잡한 editing 의 경우는 어렵더라고요. 링크의 department 내용이 그런 예 인데요, 복수개 dept. 의 이름,체크여부,그룹까지 모두 수정할 경우 PropertyEditor 를 어떤 식으로 접근해야 할 지 감이 잡히질 않더군요. (요런것도 되나요? 흠.. 전에 어떻게 한 것 같긴 한데 당췌 내부에서 어떻게 돌아가는지 감이 잡히질 않아서...) 그냥 화면단에서는 jstl, controller 단에서는 req.getParameterValues 로 후다닥 해치워버렸습니다.

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2008.11.27 21:13 신고 PERM MOD/DEL

    링크의 내용과 왕오리님께서 하시는 이야기가 대응이 안되는 것 같아서 잘 이해가 안 되는데요;;

    링크 내용은 Member 수정/추가 화면에서 Department를 선택할 때 Department 목록에서 하나의 Dep을 선택해서 Mem에 설정해 줄 때 PropertyEditor를 어떻게 사용할지 얘기같은데.. 아마 왕오리님께서 말씀하시는 내용이.. 아래 댓글 같습니다.

    In the JSP, I loop through each department name using JSTL and want to display data in the HTML table model shown above. When the user selects multiple check-boxes I want the list departments to be filled with the selected data and made available in the employee object request. i.e. I want a department object to be filled with the name, group(from the drop-down) for every check-box selection and add it to the employee object's department list.

    이 내용을 보면 Dep 선택 리스트 박스에 group이랑 name이름 조합으로 dep 객체를 채우고 싶다는 거 아닌가요? 그럼 PropertyEditor(PE)의 getAsText에서 그 이름 조합해서 반환하도록 하던가 아님 toString()에 그렇게 구현해놓고 PE의 getAsText에서는 그것만 호출해주면 끝입니다.

    킹고리님께서 말씀하시는 "복잡한 editing 의 경우"라는 게 무엇인지 모르겠습니다. 뭘 "수정" 한다는 거죠?;; @.@

  3. Favicon of http://kingori.egloos.com BlogIcon kingori 2008.11.28 16:20 PERM. MOD/DEL REPLY

    제가 이해한 내용은, employee는 dept. 의 name 만을 가지고 있었는데, 수정화면에서 가지고 있는 dept name 목록 중 checkbox 로 선택한 dept에 대해서만 drop down에서 선택된 dept group을 설정하고, 이것을 저장하고자 하는 것 입니다. (저와 같이 이해하셨나요?)
    요걸 저는 복잡한 editing 이라고 생각했습니다. employee 가 가진 dept 중 check 된 dept. 를 가려내고, check된 dept에 대해선 선택된 group 을 매칭시켜주는 작업이지요.

    일단 기선님이 말씀하신 PE.getAsText / PE.setAsText 의 활용에 대해 아직 제가 정확하게 파악하지 못하고 있는 게 문제인 것 같아서 먼저 테스트를 좀 해 봐야 할 것 같네요. 예를 들면
    setValue(new Role(Integer.parseInt(text)));과 같이 단순히 text 를 interger 로 변한하는 것이 아닌, 좀 더 복잡한 parsing 을 해 보는 것이죠. setValue(new Dept( parseName(text), parseGroup(text) )); 형태가 제대로 동작하는지요. 테스트 해 보고 trackback 이나 커멘트를 남기도록 하겠습니다. :)

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2008.11.28 17:15 신고 PERM MOD/DEL

    kingori님께서 뭔가 조금 잘못 이해하신 것 같은데요. 왜 employee가 dep의 name을 가지고 있어야 하죠? emp는 그냥 dep을 물고 있는게 정상적이고 dep에 있는 name으니까 그냥 . 타고 가서 참조하면 되자나요.

    그리고 댓글에 올라온 코드를 봐도..dep을 여러개 물고 있죠.

    public class Employee{
    private String id;
    private String name;
    private List<Department> departments;

    getter/setter stuff....

    }

    depName 같은 필드는 없습니다. 그냥 emp의 dep을 설정해야 하는데 dep의 name과 group 이름을 조합해서 각각의 emp를 드랍-다운 메뉴에 보여주겠다는 거죠.

    그런 경우에 제가 위에 쓴 글이 딱 제격입니다.

    setValue(new Dept( parseName(text), parseGroup(text) ));

    이런 코드 보다는

    setValue(new Dept(text)); 를 사용하고 text에서 name과 group을 파싱하는 작업은 Dept 도메인 객체에 맡기는게 더 좋치 않을까요?

    그리고 위의 코드는 하이버네이트가 아닐 경우 상당히 부적절합니다.

    실제로는

    setValue(deptDao.getDeptBy(text)); 이런식으로 실제 데이터를 가져와서 세팅해야 할 겁니다. 그렇게 해야 실제 Dept 객체를 가져다가 설정할 수 있을테니까요. JDBC를 사용할 경우이거나 하이버네이트를 사용하더라도 설정한 데이터의 id값 이외에 dep에 대한 다른 정보 조작이나 참조가 필요할 땐 위 코드처럼 작성해야 할 것입니다.

  4. Favicon of http://kingori.egloos.com BlogIcon kingori 2008.11.28 17:35 PERM. MOD/DEL REPLY

    자꾸 의견이 꼬이는 것 같은데, 서로 다른 requirement 에 대해서 이야기하는 것 같습니다.
    setValue(new Dept(text));
    이 부분은 실제 구현한다면 기선님 의견이 맞습니다. setValue(deptDao.getDeptBy(text)); 도 그렇고요. 단순 text를 parsing 해서 name과 dept를 알아내야 하지 않는가 정도의 의견으로 이해하시면 될 것 같습니다.
    employee와 deptName 의 관계는 원문에서의 "I'm putting an employee object in request, that has a list of empty departments, except for the dept name." 에서 나온 이야기입니다. 현재 dept에 설정된 것은 name밖에 없기 때문에 deptName 정도로 표현한 것이지, emp. 가 deptName field를 가지고 있다는 의견은 아닙니다. 사실 상세구현은 별로 중요한 것은 아니고, 전 spring framework이 넘나드는 parameter를 propertyEditor를 통해서 어떻게 처리하는 지가 궁금할 따름입니다.

    제가 생각이 좀 정리가 되고, 샘플 작업을 좀 더 해본 후에 이야기하는 것이 좋을 것 같습니다. 아무래도 서로 다른 이야기를 하는 것 같습니다. :)

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2008.11.28 18:07 신고 PERM MOD/DEL

    넹.. 흠~ 제가 링크에 걸린 포럼 글을 자세하게 읽지않고 대강 읽어서 이런 의견 차이가 생긴 것 같네요.

    말씀하신대로 서로 다른 요구사항을 얘기하고 있는 것 같습니다. 링크에서 말하고 있는게 제가 생각한 것처럼 단순한 경우가 아닌것 같습니다. 흠~ 다음에 좀 더 자세히 읽어보고 글을 올리겠습니다.

Write a comment.