Clean Code that Works.

일단 새로운 스터디 메인 화면을 일단 아래와 같이 해봤습니다.

메인 메뉴 밑에 들어갈 컨텐츠를 더 생각해 봐야겠어요.
아틀라시안 처럼 배너가 들어갈 지 아니면 서브 메뉴가 들어갈 것인지.
봄싹은 커뮤니티 사이트라서 아틀라시안 처럼 꾸미기가 애매하더라구요.

기본 컨셉은 가장 인기있는 스터디를 보여주고, 최근 스터디, 모임, 발표 목록을 보여주는 것 입니다.
최근 목록 하단에 무언가 더 표시하고 싶은데, 뭘 표시하면 좋을 까요?
개인화 컨텐츠나 기타 다른 컨텐츠 있으시면 의견 좀 주세요.
의견 반영 하면서 개선해 나가겠습니다.



스터디 등록 화면을 좀 바꾸었습니다.
로고를 잘 쓰지 않는데 .. 로고는 디폴트, 플리커, 직접 업로드로 구분해서 할 수 있도록 하구요.
디폴트 로고도 좀 더 의미가 있는 로고으로 변경할 생각입니다.

Validation도 jquery.validation 과 JSR 303 같이 쓰면서 하도록 할려구요.
스터디 설명 부분도 jquery.wiswyg 에디터로 해서, 간단한 마크업을 할 수 있도록 하였습니다.

최대한 간결하게 할려고 노력중이에요 ㅋ


기타 스터디에 관련한 의견 있으시면 언제든지 말씀해 주세요.

기선님 의견 대로 http://www.meetup.com/
초필살 급조 스터디 화면,

봄싹 개발 모임 가는 길에.

길을 잘못들어서 한 40분을 헤메였다.
날씨도 너무 덥고 후텁지근 해서 땀을 한바가지 흘렸네 ㅠㅠ

가서 기선이형한테 책한권 빌려오고, '자바 병렬 프로그래밍' 늦어서 별 이야기 없이 진행상황만 듣고 와서 마무리.
가서 다음주 월요일에 출간예정인 토비님의 스프링책을 봤는데, 크기가...... 상당했다.
집ㅇ와서 보니. 소설같은 C# 만 하다 ㄷㄷㄷ

표지도 양장이라서 들고다니긴 무리 .. 들고다니면 살빠진다.
ipad 나와서 pdf 로 들고 다니면서 보면 좋겠다 ㅋ

1. 모임 부분 탭 형식으로 변경.
2. comment 부분 발표 comment와 같이 쓸 수 있는지 확인.
3. 메뉴 선택시 click이벤트 적용 안되는 것 수정(fg-menu 수정할 것인지 아니면 지원 되는지)

이정도??
모임까진 개선이라 뭐 별거 없으니깐

더해서, js 스크립트들 정리 해 볼것.


ValidJsonView라고 'application/json'타입의 view를 리턴해주는 Custom view 클래스를 만들었다.

스프링이 BindException이 발생 하면, Error 정보를 json형태로 리턴해 주는 것이었는데, 직접 Controller Url을 치고 들어가면 view를 찾는데, 폼인 상태에서 url로 액션을 날리면 view를 못 찾는 것이었다.

하여, 디버깅해본 결과, ContentNegotiatingViewResolver에서 view를 못 찾는 것이었다.
해서 ContentNegotiatingViewResolver 소스를 살펴 보니.

private View getBestView(List<View> candidateViews, List<MediaType> requestedMediaTypes) {
        MediaType bestRequestedMediaType = null;
        View bestView = null;
        for (MediaType requestedMediaType : requestedMediaTypes) {
            for (View candidateView : candidateViews) {
                if (StringUtils.hasText(candidateView.getContentType())) {
                    MediaType candidateContentType = MediaType.parseMediaType(candidateView.getContentType());
                    if (requestedMediaType.includes(candidateContentType)) {
                        bestRequestedMediaType = requestedMediaType;
                        bestView = candidateView;
                        break;
                    }
                }
            }
            if (bestView != null) {
                if (logger.isDebugEnabled()) {
                    logger.debug(
                            "Returning [" + bestView + "] based on requested media type '" + bestRequestedMediaType +
                                    "'");
                }
                break;
            }
        }
        return bestView;

    }
view에서 설정한 컨텐츠 타입을 찾아서 그에 맞는 뷰를 리턴하는 것을 볼 수 있었다.

ValidJsonView에는 따로 컨텐츠 타입을 설정 하지 않아서, ContentNegotiatingViewResolver에서 DefaultView로 설정해 둔
mappingJacksonView를 사용하고 있었다.

해서
public ValidationJsonView() {
        setContentType("application/json");
    };
부모 클래스(AbstractView)에 setContentType을 설정해서 해결 하였다.

DB Validation

Spring2010. 7. 28. 11:52
데이터 베이스에서 오류가 발생 했을 경우 어떻게 처리 하면 좋을까?

기존 Server Validation 처럼 DB 익셉션을 처리하는 Exception mapping을 처리해서 만드는게 가장 편할것 같다.

하여 HibernateExceptionJsonView 라는 것을 만들어 보았다.
validation 체크를 하면서 Hibernate를 사용하였는데, Hibernate에서 발생하는 오류(HibernateException)을 잡아서 처리한다.

근데 잡아서 처리한 후, 어떻게 보여 주어야 할 까?

아무래도 Client 나 Server Validation 처럼 필드 별로 구체화된 메시지는 보여주기 어려울 것 같다.

예로 ID가 중복일 경우
"ids for this class must be manually assigned before calling save(): net.study.spring.model.SimpleBbs"
위 같은 오류를 찍어 주는데..

이 것을 사용자에게 보여 줄 수는 없지 않은가.
하여 그냥 DB 오류가 발생 했다고, 팝업 메세지로 보여 주는 것이 가장 좋을 듯 하다.

서버쪽에서는 로그 찍어 주니깐, 개발자들은 그거 보고 해결 하며 되겠지 머.

Server Validation

Spring2010. 7. 26. 19:31
Server Validation을 좀 더 효율적으로 하기 위해서,
ValidationJsonView라는 클래스를 만들었다, BindingResult 가 hasError를 가지고 있을 경우에
ValidationJsonView를 리턴 하도록 하였다.

이 경우에 에러가 발생 했을 경우를 @AfterThrowing aspect 로 처리 하도록 했는데, 에러(BindingResultException)가 발생했어도 잡지를 못하는 것이었다. 이 오류는 이 AnnotationMethodHandlerExceptionResolver 가 잡아서 처리하고 있다.

하여 전에 생각으로는

//@ExceptionHandler(BindException.class)
    public ModelAndView handleValidationException( BindException ex, HttpServletResponse response) {
        logger.info(ex.getMessage());
        return new ValidationJsonView(ex, response).renderError();
    }

이 같은 형식으로 valid 오류가 발생 했을 경우 처리할 view(ValidationJsonView)를 만들어서 처리를 했었다..(2틀 -_-?)

좀 더 생각 해보니 custom resolver를 만들어서 처리 하는게 더 좋은 방법 이었다.
HanderExceptionResolver를 Implements 하여 ValidExceptionResolver를 만들어 보았다.

public class ValidExceptionResolver implements HandlerExceptionResolver {
   
    private Logger logger = LoggerFactory.getLogger(this.getClass());
   
    public ModelAndView resolveException(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex) {
        BindException bindEx = (BindException) ex;
        setScBadRequest( response);
        logger.info( bindEx.getFieldErrors().get(0).toString());
        logger.info("Error Fields : {}", bindEx.getFieldErrors());
       
        return new ModelAndView( new MappingJacksonJsonView(), getErrorInfo( bindEx));
    }
   
    private ModelMap getErrorInfo( BindException bindEx) {
        ModelMap model = new ModelMap();
        model.addAttribute("errorType", "validError");
        model.addAttribute("errorCount", bindEx.getErrorCount());
        model.addAttribute("errors", bindEx.getFieldErrors());
        return model;
    }
   
    private void setScBadRequest( HttpServletResponse response) {
        response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
    }

}


그럼 또 생각해 볼께.... -_-;;
저걸 설정 파일에다가 등록하면 모든 exception을 잡아서 저놈이 처리 하게된다.
이러면 안되!!! 나는 BindException 만 처리 하면 된다고!!!

하여 org.springframework.web.servlet.handler.SimpleMappingExceptionResolver 에서 특정 에러에 대한 resolver를 설정 할 수 있을까? 생각이 들어.. 한번 찾아 보았으나..

못 찾았다. -_-;;

그래서 예전에 만들어 놓았던 view 클래스를 사용 하기로 하였다.

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
               <props>
                       <prop key="org.springframework.validation.BindException">
                            validExceptionJsonView
                       </prop>
               </props>
        </property>
    </bean>


validExceptionJsonView 는 MappingJacksonJsonView를 상속하여 만들었는데, 그냥 AbstractView 상속해도 되겠다.

이정도면 정리 된거야???


스프링 MVC ShowCase!!!

Spring2010. 7. 23. 18:45
스프링 팀 블로그에서 spring mvc 3 showcase라는 멋진 포스팅을 해줬다.
http://blog.springsource.com/2010/07/22/spring-mvc-3-showcase/

블로그에있는 샘플 svn 주로를 체크 아웃 받으면 샘플 프로젝트를 다운 받을 수 있다.
screencast 도 제공하고 다운 받아 보면 pdf로 문서도 있다.

어디 강의용으로 써도 될만한 퀄리티 @_@

좋구만.

Spring Validation.

Spring2010. 7. 22. 09:05

JSR 303을 사용한 Validation 체크(bean-validation-integrating-jsr-303-with-spring)
다른 URL http://blog.frankel.ch/bean-validation-and-jsr-303

기선님 블로그 글
1. 이론(http://whiteship.me/2423)
2. 실습(http://whiteship.me/2424)

에러가 발생 하면 BindingResult result의 result에 에러 정보를 가지고 있다.
여기에 해당 필드 명 과 에러 메세지를 가져 올 수 있는데,
HttpServletResponse에다가 에러로 세팅한 다음 이것들을 json으로 구성해서 리턴 해 주고,
jquery Ajax 요청에서 error로 받아서 이 error Json을 가지고 jQuery Validation 처럼 구성 할 수 있을 것 같다.

에러를 처리 할 때 에러 메시지들 담은 폼 페이지를 리턴해 주는 것이 아니라.
에러 정보를 담고 있는 Json을 리턴해서 기존 폼에다가 붙여서 보여주겠다는 생각!!

http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/validation/BindingResult.html
API를 확인해 보면 에러에 관련된 정보를 가져오는 메서드가 있는 것을 볼 수 있다.


컨트롤러에서 에러와 관련된 정보를 Json으로 담아서 넘겨 주면,
이를 클라이언트에서 처리 해야 한다.


결과가 xhr 형태이기 때문에, 이를 JSON으로 파싱 해서 값을 처리 하면 된다.
submitHandler는 jQuery valdation 에서 처리하는 것으로 submit 처리는 저기서 하면 된다.
validation에서 error가 아닐 경우 validation element(여기서는 em)에 css class가 error success 로 설정 되어 있을 것이다.
(그래야 클라이언트 validation 통과 한 후 전송 하니깐)
이것들 jqeury selector로 찾아서 removeClass해주고, 에러 메시지를 적어주면 땡~~~

음. dataType json으로 하면 파싱할 필요 없나? -,.-;;
success 했을 때만 지정한dataType으로 받을려나??

api를 보자.




화이팅 ㅋㅋ

afterInvocationManager

Spring2010. 5. 31. 10:17
In our application, only principals with permissions to read the given customer should be allowed to obtain it. To make this check, the Customer instance is retrieved and passed to the AclEntryAfterInvocationProvider. If the authenticated object does not have the permission to read it, then the provider will throw AccessDeniesException.

http://www.denksoft.com/wordpress/web-development/acl-spring-security-tutorial/

참고 하고 있는 블로그에 있는 내용인데.. 뭔말이야 @_@;;
일단 오브젝트를 겟 한 다음에 권한을 체크 한다는 내용 같다.

그게 무슨말이야.!!!

그전 메소드 시큐리티에서는 오브젝트를 get 하기 전에, 즉 쿼리를 날리기 전에 보안 검사를 하고 있는데,
이것은 쿼리를 실행 한 후 오브젝트를 get 한 후에 이 오브젝트들을 하나 하나 보안 검사를 해서, 보안검사에 통과할 경우 오브젝트들을 보여준다.

오우 좋은데 @_@

그러니까 검색 한 다음에 검색 결과에서 필터링을 할 수 있다는 말!!
그럼 요곳들을 어떻게 쓰느냐.. 일단 아래 설정 처럼 설정 파일을 정의 해 주고.
<sec:global-method-security secured-annotations="enabled" access-decision-manager-ref="businessAccessDecisionManager">
  <sec:after-invocation-provider ref="afterAclCollectionRead"/>
  <sec:after-invocation-provider ref="afterAclRead"/>
 </sec:global-method-security>

그런 다음에 보안 설정을 할 메서드에 @Secured를 설정 해 주면 된다.
@Secured( {"AFTER_ACL_COLLECTION_READ"})
 public ArrayList<AclBbs> getList( PagingUtil pagingUtil) {
  HashMap<String, Integer> params = new HashMap<String, Integer>();
  params.put( PagingUtil.START, pagingUtil.getStart());
  params.put( PagingUtil.LIMIT, pagingUtil.getLimit());
  params.put( PagingUtil.TOTALCOUNT, pagingUtil.getTotalCount());
  return aclBbsDAO.getList( params);
 }

이렇게 해서
스프링 시큐리티는 대충 내맘대로 정리 완료??