[Spring Security] http 네임스페이스 쓰려면 필터 이름은 항상 고정(?)

http://static.springsource.org/spring-security/site/docs/3.0.x/reference/appendix-namespace.html#nsa-http-attributes

<filter>
<filter-name>securityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
   <filter-mapping>
       <filter-name>securityFilterChain</filter-name>
       <url-pattern>/*</url-pattern>
   </filter-mapping>
    
자 이렇게 필터를 설정하고 
<http>
        <intercept-url pattern=”/base/color/mgt” access=”ROLE_USER” />
        <intercept-url pattern=”/**” access=”IS_AUTHENTICATED_ANONYMOUSLY” />
<form-login login-page=”/login” />
<logout logout-success-url=”/index” />
<remember-me />
</http>
    <beans:bean id=”smdisUserDetailsService” class=”smdis.common.security.SmdisUserDetailsService”/>
<authentication-manager alias=”authenticationManager”>
<authentication-provider user-service-ref=”smdisUserDetailsService”/>
</authentication-manager>
<global-method-security secured-annotations=”enabled”
jsr250-annotations=”enabled” pre-post-annotations=”enabled” />
이렇게 시큐리티 설정을 했다.
잘 돌아갈까?? 안 돌아간다.. 시큐리티 네임스페이스를 사용해서 <http>를 등록하면 FileChainProxy 빈 이름은 항상 springSecurityFilterChain이 된다. 그래서 필터 이름을 springSecurityFilterChain으로 설정해줘야 한다.
뭐.. DelegatingFilterProxy 필터 자체에 targetBeanName 속성을 사용해서 연결할 빈 이름을 설정할 수도 있지만 기본적으로 이 이름은 필터 이름을 따르게 된다. 필터 이름을 바꾸고 targetBeanName을 또 설정해 주느니 그냥 필터 이름을 springSecurityFileterChain으로 하는게 좋겠다.

<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

전자정부 프레임워크 공통 컴포넌트 실행 성공(?)

이 화면 보기가 너무 힘들다;
OSAF 예제 애플리케이션 띄우는거 보다 100배는 올래거리는것 같다. 
그나마 이 화면에서 다음으로 전개도 안된다. 왜냐면 DB가 세팅되지 않았기 떄문에;;
전자 정부 사이트에서 받은 mysql용 sql 파일들을 돌리다 보면 계속 에러가 난다. 자주 보이는 건 주키가 너무 길다는 에러인데 이건 주키 컬럼 사이즈(보통 메서드 이름이 200으로 잡혀 있었다.)를 줄여가면서 지나갔다. 그런데 두번째 sql 파일의 에러는 도무지 모르겠다; MySQL을 설치한지 오래되서 새 버전으로 올린 담에 해봐야 하는건지.. 그냥 오라클로 해야하는건지… 아흑..
맞다. DB만 만들다고 돌아가는것도 아니다. globals.properties 파일을 C:\Documents and Settings\MyHome\egovProps 이 위치에 넣어줘야 하고 이걸 제대로 쓰려면 그 파일에 있는 각종 설정 내용을 다 손봐줘야 한다.
이거.. 아무래도 내가 너무 무모만 것에 손을 댄것 같다. 덕분에 전자 정부 프레임워크 구조가 어떤지 파악할 수 있었다.
개발 환경쪽에서 ‘구현도구’라고 되어있는 이클립스를 받아서 전자정부 웹 프로젝트를 만들어야지 필요한 pom.xml이 나오지만 사실상 이건 제대로 된 pom.xml파일이 아닌것 같다. 그래도 일단 이렇게 받는다.
여기에서 공통여부 Y로 체크되어 있는 것은 무엇을 클릭하던 똑같이 egovframework-common-1.0.0를 받게 된다. 저 안에 수많은 공통 기능이 들어가 있다. 즉 저것을 넣어서 앱을 실행하면 전자정부 프레임워크 도입을 완수한거나 마찬가지다. 거기에 부가적으로 게시판이나 통계등을 넣고 싶다면 해당 메뉴를 클릭해서 소스를 받은 다음 프로젝트에 추가해줘야 한다. 
이 “공통 컴포넌트”라고 하는 서비스들은 “실행 환경”을 기반으로 하고 있다. 실행 환경 코드는 다시 네가지로 나뉜다. 공통기반, 데이터처리, 연계통합, 화면처리.. 이 중에서 웹 관련 기능이 궁금하다면 “화면 처리” 코드를 받아서 보면 된다.
하지만 안타깝게도 이 “실행 환경”에서 받는 코드들은 pom.xml이 없다. 빌드가 되지 않는다. 아참;; 위에서 설명하려다 까먹었는데.. “개발 환경”에서 자동으로 만들어준 pom.xml은 버리고 “공통 컴포넌트” 중에서도 “공통”에 해당하는 egov~~-common-1.0.0을 받으면 들어있는 pom.xml이 있다. 그걸 쓰면 “공통 컴포넌트”에 필요한 의존성까지 설정되어 있으니 무난히 빌드할 수 있다. 어쨋거나 이 코드들은 그냥 쌩으로 봐야한다. 빌드가 안되니.. 별도의 jar 파일을 만들수도 없다. (원래 안만들어도 된다. jar 파일만 따로 다운 받을 수도 있고, 공통 컴포넌트의 pom.xml에서 의존성으로 알아서 가져오게 되어 있다.) 정… 하고 싶으면 pom.xml 만들고 필요한 의존성 다 붙여주면 되는데.. 글쎄;; 별로..
소스 중에 유일하게 살펴본 코드로는 “화면처리(ptl)”에 들어있는 SimpleUrlAnnotationHandlerMapping이 있는데 이름에서는 추측하기 어려운 일을 해준다. 핸들러 매핑 마다 일괄적용되는 인터셉터가 부담스러워서 그걸 url 리스트를 사용해서 걸러주는 작업이다. 그런데 토비님 책을 보면 스프링 3.0의 <mvc:inteceptor>로 해결이 가능하다. 글로벌한 인터셉터 설정이기 때문에 핸들러 매핑을 기준으로 생각할 필요가 없어졌다. 아마도 저 클래스는 주석에도 적혀있듯이 3.0 가면서 deprecated 될 것 같다.

OSAF 2.0 준비중

최근에 계속 포스팅 했던 [회사일]을 하면서 다른 프로젝트에서도 사용할 수 있는 코드들을 별도 패키지에 모아뒀습니다. 

Generic 사용 극대화
이전과 마찬가지로 Generic 사용을 극대화해서 DAO, Service, Controller를 만들고 PersistentEnum을 활용하는 GenericPEFormatter도 만들어 뒀고, GenericExcelView까지 있습니다.
REST 스타일 URL 지원
스프링 3.0 최신 버전과 하이버네이트를 사용했으며 URL은 REST 스타일로 만들어 놨습니다. 따라서 GenericController만 상속받으면 기본적인 CRUD 기능을 RESTful URL로 제공해줍니다.
계층 구조
기본적인 계층 구조(DAO, Service, Controller) 형태기 때문에 적응하기 쉬울 겁니다. 스프링 Roo 스타일로 만들까 했지만. AsepctJ를 공부헀었는데도 잘 적응이 안되더라구요.ㅋ
no-iframe
참.. 화면이 이전처럼 iframe으로 나눠진게 아니라 통짜 구조입니다. 화면을 나누는건 JQuery layout 플러그인을 사용했구요.  iframe보다 편합니다.
그리드
그리드도 jqGrid를 사용해서 이전에 쓰던 그리드(뭔지도 기억안남)보다 기능도 많고 더 좋습니다.
상속
단점은.. Spring Roo 처럼 완전히 비침습적인 프레임워크가 아닌지라.. 상속을 사용해야 합니다. DAO, Service, Controller, Enum 들이 OSAF 코드를 상속 받아야 합니다.
코드 생성
코드 생성 기능은 없습니다. 만들라면 만들겠지만 귀찮기도 하고 손으로 직접 만들면서 사용법을 익히는게 좋을 것 같아서 만들지 않았습니다.
바로 시작
프로젝트를 다운받아서 라이브러리 형태로 넣을 필요없이 프로젝트를 받아서 바로 자신의 웹 프로젝트로 사용할 수 있게끔 배포할 계획입니다. 
기본 모델 제공
바로 실행할 수 있는 프로젝트에 Member, Right, Code, CodeCat 같은 기본 도메인을 제공합니다. 자주 쓰는 도메인 코드를 가진 상태에서 시작하세요. Generic류 코드를 어떻게 쓰는지, OSAF 태그파일을 사용해서 화면 코드를 작성하는 방법을 쉽게 볼 수 있습니다.

[스프링 3.0 이해와 선택] 2차 교육 공지

http://www.hanbitedu.co.kr/incumbent/shortContent.do?index=1097

벌써 공지가 떴네요. 캬..
1차 교육 끝나자 마자 바로 시작합니다.
2차 강의 할 땐 토비님 책을 가지고 시작할 수 있겠군요.
한결 든든하겠네요.
– 1일차 (7월 24일) 
 1장 오브젝트와 의존관계 
 2장 테스트 
 3장 템플릿 
 4장 예외 

– 2일차 (8월 07일) 
 5장 서비스 추상화 
 6장 AOP 
 7장 스프링 핵심기술 응용 
 8장 스프링이란? 

– 3일차 (8월 14일) 
 9장 스프링 프로젝트 시작하기 
 10장 IoC 컨테이너와 DI 
 11장 데이터 엑세스 기술 

– 4일차 (8월 21일) 
 12장 스프링 웹 기술과 스프링 MVC 
 13장 스프링 @MVC 
 14장 AOP와 LTW 
 15장 콘텍스트 테스트 프레임워크 
 16장 스프링의 기타 기술과 효과적인 학습방법 


1일차와 2일차는 “이해”하는 단계입니다. 이 부분에서 스프링 IoC 컨테이너, 테스트, 템플릿, 트랜잭션 추상화, 이메일 추상화, 스프링 AOP 기능들이 어떻게 만들어졌는지 실습을 통해서 학습하게 됩니다.

3일차와 4일차는 “선택”하는 단계로 실제 웹 애플리케이션을 만들어 가면서 IoC 컨테이너 설정 방법, 연관 관계 설정 방법, 빈 등록 방법 등을 선택하고, DAO 기술을 선택하고 그에 따른 스프링 지원 기술을 사용하며, 트랜잭션 선언 방법도 선택하고 적용합니다. 4일차에서는 @MVC를 사용해서 웹 애플리케이션을 마무리하고 3.0에 추가된 기능들을 학습합니다.


[회사일] GenericExcelView 만들기

현재 업무를 엑셀 파일로 처리하고 있기 때문에 엑셀 파일과의 연동을 필수적입니다. 따라서 시스템에 들어있는 정보를 엑셀로 받아볼 수 있게 하거나 엑셀 정보를 시스템에 올려서 DB에 저장되게 하는 것도 필요합니다.

엑셀 업로드야 엑셀 파일 형식이 도메인 클래스 마다 다를 테고 비즈니스 로직마다 다를테니 일반화하기 힘들지만(뭐 어떤 규칙을 정하면 일반화를 못할 것도 없겠지만..) 엑셀 다운로드 경우에는 일반화하기 좋습니다. 리포트 형식의 엑셀을 원하는게 아니라면 말이죠;; 그런건 여기서 받은 엑셀 파일을 기초데이터로 삼아서 다른 직원보고 편집해서 리포트 만들라고 시키면 될테니 이런 간단한 재고관리 시스템에 무리한 기능을 넣고 싶진 않군요.
어쨋든.. 일반화 시켜봅시다.
<page:mgtpage label=”재고 관리”>
    <page:search label=”재고 검색”>
        <s:input label=”제품명” path=”name” />
        <s:input label=”제품번호” path=”number” />
        <s:input label=”색상” path=”colorName” />
        <s:select label=”성별” path=”sexValue” items=”${ref.sexList}” />
        <s:input label=”공급업체” path=”suppName” />
        <s:input label=”창고” path=”locationName” />
        <s:date label=”날짜” fromPath=”dateRange.from” toPath=”dateRange.to”/>
    </page:search>
    <script type=”text/javascript”>
        $(function() {
            $(“#smdis-grid”).jqGrid({
                colNames:[‘id’, ‘제품명’, ‘제품번호’, ‘색상’, ‘사이즈’, ‘공급업체’, ‘창고’, ‘수량’, ‘날짜’],
                colModel :[
                    {name:’id’, index:’id’, width:55, hidden:true},
                    {name:’item.name’, index:’item.name’, width:90},
                    {name:’item.number’, index:’item.number’, width:90},
                    {name:’item.colorName’, index:’item.color’, width:90},
                    {name:’item.size’, index:’item.size’, width:90},
                    {name:’item.supp.name’, index:’item.supp’, width:80},
                    {name:’location.name’, index:’location.name’, width:80},
                    {name:’qty’, index:’qty’, width:80},
                    {name:’date’, index:’date’, width:80}
                ]
            });
        });
    </script>
</page:mgtpage>
화면에 보여줄 그리드 정보가 들어있는 mgt.jsp 페이지 소스입니다. 태그 파일을 사용해서 중복 코드를 제거하고 여기서 꼭 다뤄야하는 정보만 남겨뒀습니다. 이 상태에서 엑셀을 일반화 시켜서 만들때 서버쪽으로 넘겨줘야 하는 정보가 들어있습니다. 컬럼명과 각 컬럼 값이 들어있는 path 정보입니다.
화면에 등록된 그리드 정보를 그대로 엑셀로 옮기고 싶다면 그 두 정보를 가져와야 합니다. 구현 과정을 전부다 설명하기는 다소 귀찮군요.. 흠.. 할일도 많으니까 대충 생략하겠습니다.
저기서 버튼을 누르면 컬럼 정보, Path 정보, 검색 매개변수들을 서버쪽으로 넘겨줍니다.
그럼 서버가 받아서 SpEL과 JExcel API와 스프링이 제공해주는 AbstractJExcelView 엑셀뷰를 사용해서 엑셀을 만들어 줍니다.
public class GenericExcelView extends AbstractJExcelView {
    protected void buildExcelDocument(Map<String, Object> model, WritableWorkbook wb, HttpServletRequest req, HttpServletResponse res) throws Exception {
        List<?> list = (List<?>) model.get(“list”);
        String modelName = (String) model.get(“modelName”);
        List<String> colNameList = (List<String>) model.get(“colNameList”);
        List<String> colPathList = (List<String>) model.get(“colPathList”);
        res.setHeader(“Content-Disposition”, “attachment; filename=” + modelName + “.xls”);
        WritableSheet sheet = wb.createSheet(modelName, 0);
        for(int column = 0 ; column < colNameList.size() ; column++){
            sheet.addCell(new Label(column, 0, colNameList.get(column)));
        }
        ExpressionParser parser = new SpelExpressionParser();
        int row = 1;
        for(Object object : list){
            StandardEvaluationContext context = new StandardEvaluationContext(object);
            for(int column = 0 ; column < colPathList.size() ; column++){
                String path = colPathList.get(column).replace(“.”, “?.”);
                String value = parser.parseExpression(path).getValue(context, String.class);
                sheet.addCell(new Label(column, row, value));
            }
            row++;
        }
    }
}
이걸 사용하도록 GenericController 쪽에도 기능을 추가해줬는데 그거야 뭐 간단하니깐. 생략하겠습니다. 이제 재고관리와 상품관리쪽에 엑셀 업로드를 만들어야겠습니다. 내일할까나;; 흠.