Version 1.1.0
저작권 © 2007-2009 삼성SDS
Anyframe Gen은 Anyframe 기반의 어플리케이션 개발 시 기존 개발 방식보다 훨씬 쉽고 빠르게 개발을 시작할 수 있도록 Scaffolding, 코드 생성 기능 등을 제공하는 개발 툴이다.
개요에서는 툴을 통해 제공되는 기능, 특징, 자동 생성된 코드를 통해 재사용될 수 있는 공통 기능 등에 대해 설명하고 있다. 이밖에 기술 지원 방법 및 유지 보수 그리고 시스템 사양 등에 대한 사항도 제시하고 있다. 또한 Anyframe Gen의 주요 특징, 구조, 프로젝트 중심 개발에 대해 소개하고 있다.
Anyframe Gen은 최신 오픈소스(Anyframe)를 바탕으로 기존 방식보다 훨씬 쉽고 빠르게 웹 어플리케이션 개발을 시작할 수 있도록 Scaffolding, 코드 생성 기능 등을 제공한다.

Anyframe Gen 설치를 통해 기존의 복잡한 설치 및 설정 작업을 최소화한다. Anyfame Gen의 설치로 Anyframe 설치, 프로젝트 구조 생성, 단위 모듈 생성, 소스코드 생성, 빌드/테스트/패키지 스크립트 생성 등이 가능하다.
Single Project Structure, Multi Project Structure 로 프로젝트 구조를 선택할 수 있다. Multi Project Structure 의 경우 공통(Common), 서비스(Service), 웹(Web) 타입 별 프로젝트를 생성할 수 있는 프로젝트 중심의 개발이 가능하다.
엔티티 클래스(JPA)와 기본 템플릿(FreeMarker)을 이용한 도메인 객체 중심의 CRUD 기본 코드가 생성되고, 자동으로 단위/통합 테스트 케이스가 작성된다. 템플릿은 프로젝트의 개발표준에 따라 변경이 가능하다.
템플릿을 이용해 생성된 CRUD 소스는 default 템플릿의 경우 Anyframe Generic Service 를 기반으로 작성된 코드이며(상속 혹은 참조), miplatform 템플릿의 경우 Anyframe MiPlatform 쿼리서비스(MiPQueryService)를 기반으로 작성된 코드이다.
코드 생성 시, 다음과 같은 공통기능이 제공된다.
표 1.1. generated common functions
| function |
|---|
| Generic Service/DAO |
| Search (Primary Keys, Required Fields) |
| Paging (Paging Navigation Bar) |
| Exception / Message Handling |
| Dynamic Reloading (optional) |
| Reporting / Sorting (Display Tag 사용) |
| User Defined Template |
DB 테이블에 해당하는 도메인 클래스를 생성하고, 해당 도메인 클래스를 기반으로 CRUD 소스 코드를 생성하는 데 이때 DB 테이블에 맞는 테스트 데이터까지 함께 생성해주고 있다. DB는 기본적으로 HSQL DB를 샘플 DB로 제공하고 있으나 Oracle, MySQL, Sybase DB 등 DB 정보를 변경하여, 프로젝트에서 사용하는 DB 기반 코드 생성 기능을 사용할 수 있게 하고 있다. 이때, 각 DB 별 제공되는 테이블 컬럼 타입이 다양하므로 도메인 클래스 생성 시 혹은 CRUD를 위한 테스트 데이터 생성 시 지원되지 않는 타입 정보로 인한 오류가 생길 수 있다. 이 때에는 DB 컬럼 타입 별 매핑되는 자바 타입 정보를 설정해주는 파일 내용을 변경하여 지원해주도록 한다.
Anyframe Gen에 대한 기술 지원은 Anyframe 오픈소스 커뮤니티 사이트( http://www.anyframejava.org/ )의 포럼 메뉴를 통해 이루어지며, 단순 질의 응답에서부터 소스 코드에 대한 구체적인 가이드 및 해결책을 제시한다. 특정 프로젝트를 위한 기술 컨설팅 지원이 필요한 경우 Anyframe 오픈소스 커뮤니티 사이트의 연락처 를 통해 요청할 수 있다. 또한, 이슈관리시스템인 JIRA( http://dev.anyframejava.org/jira/ )를 통해, Bug Fix, Improvements, New Features 에 대한 이슈들을 요청할 수 있다. 자세한 사용방법은 이곳 을 참조하도록 한다.
Anyframe 오픈소스 커뮤니티 사이트( http://www.anyframejava.org/ )를 통해 릴리즈된 최신버전 및 이전 버전에 해당하는 라이브러리, 매뉴얼 등을 제공받을 수 있으며 패치 및 업그레이드되는 실시간 파일의 경우 Reuse Repository 를 통해 제공된다. 자세한 사용방법은 이곳 을 참조하도록 한다.
하드웨어와 소프트웨어 요구 사항은 다음 테이블에 작성되어 있다. 아래 작성된 하드웨어 사양 이하의 시스템에서도 Anyframe Gen을 사용할 수 있으나, 빠른 성능을 위해서는 아래 사양을 권고한다. 또한 아래 작성된 Storage의 경우, Anyframe Gen 전체 설치 파일에서부터 Eclipse, Tomcat, MiPlatform 등 모든 관련 파일 설치를 합하여 작성된 것으로 Anyframe Gen 만으로는 1GB 이하의 용량을 차지하고 있다. 소프트웨어 요구 사항은 반드시 충족시켜줘야 한다.
표 1.2. System Requirements(HW)
| Hardware Requirements | Description |
|---|---|
| Memory | 1024MB RAM 이상 |
| Storage | 1GB 하드 디스크 공간 |
표 1.3. System Requirements(SW)
| Software Requirements | Description |
|---|---|
| JDK | 1.5.x Version |
| Eclipse IDE | Eclipse 3.3.x Version 이상 지원(Europa/Ganymede/Galileo) |
Anyframe Gen은 어플리케이션 프레임워크인 Anyframe 기반으로 어플리케이션을 개발할 때 Anyframe 설치, 어플리케이션과 프로젝트 생성 및 코드 생성 기능을 통해 개발 편의성을 제공해주는 개발 툴로 CLI(Command Line Interface) 혹은 Eclipse Plugin 툴을 통해 Scaffolding과 코드 생성 기능을 제공한다. 아래 그림에서와 같이 Anyframe 설치에서부터 프로젝트 구조, 코드 생성, 빌드 수행에 이르기까지 개발 프로세스 전반에 걸쳐 어플리케이션 개발에 도움을 준다.

Anyframe Gen은 다음과 같은 주요 특징을 가지고 있다.
개발 대상 어플리케이션에 대한 프로젝트 구조 및 단위 모듈, 빌드 스크립트 생성한다.
도메인 클래스를 중심으로 CRUD 기본 코드 생성하고 자동으로 테스트 코드와 테스트 데이터를 생성한다.
어플리케이션 개발 시 어플리케이션 전체 구조 및 모듈, 소스 코드 생성 기능 및 어플리케이션과 프로젝트 단위 별 빌드 기능을 제공함으로써 신속한 개발 환경 구성을 가능하게 한다.
Anyframe을 사용하여 개발 시 직면하게 되는 복잡한 설정 파일로 인한 잦은 오류 발생 상황을 줄일 수 있다.
개발 초기 공통 개발 템플릿을 따로 구성하여 배포하고 각 개발자들은 배포된 개발 템플릿 소스를 참조하여 수정해서 사용해야 하는 이러한 반복적인 작업을, Anyframe Gen에서 제공하는 코드 생성 기능을 이용하면 하지 않게 된다.
Best Practice에 해당하는 샘플 소스 코드를 자동 생성시켜줌으로써 Anyframe을 활용한 개발 시 참조하기 용이하다.
단위 테스트 케이스 및 통합 테스트 케이스를 자동 생성시켜줌으로써 개발 진행 시 테스트를 통한 코드 품질을 향상시킬 수 있다.
Anyframe Gen은 자바의 Generic Type 및 JPA Annotation 설정 등의 기능을 이용하므로 JDK 5 이상의 환경에서 사용할 수 있다.
Anyframe Gen 설치를 통해 Anyframe, 템플릿, 빌드 도구, 사용되는 모든 라이브러리 설치가 완료된다. 개발 대상 어플리케이션의 생성 위치는 꼭 applications 하위로 지정하지 않아도 무방하다.

프로젝트별 Eclipse 연계 및 샘플 코드 생성이 가능하며 단위 빌드 기능이 제공된다. 어플리케이션 빌드의 경우 클래스 혹은 war 파일로 패키징 처리된다.

Anyframe Gen을 개발 환경에 맞게 설치하도록 한다. 설치 프로그램을 이용하여 손쉽게 설치할 수 있다.
Anyframe Gen은 압축파일로 배포되며, 다음과 같은 순서에 의하여 설치한다. Anyframe Gen 설치 시 Anyframe 도 함께 설치가 된다. 따라서, Anyframe Gen을 설치하면 Anyframe 을 따로 설치할 필요가 없다.
Anyframe Gen을 설치하기 위한 [시스템 사양]을 확인한다.
Anyframe Gen의 최신 배포판을 http://www.anyframejava.org/project/gen#downloads 에서 확인한다.
Anyframe Gen의 최신 배포판("Anyframe-gen-x.x.x.x-bin.zip")을 사용자의 컴퓨터에 내려받는다.
내려받은 최신 배포판의 압축을 원하는 폴더에 푼다.
압축을 풀면 다음과 같은 파일들이 보인다.

licenses : Anyframe Gen을 통해 배포되는 3rd party 라이브러리들에 대한 라이센스 본문과 정리된 목록
plugins : Eclipse 플러그인 패키지 (Anyframe Common, Anyframe Gen)
Anyframe-gen-x.x.x.x-setup.jar : Anyframe Gen 설치 파일(JAR 파일을 실행시킨다)
changelog.txt : 버전 별 변경 사항 로그
license.txt : Anyframe Gen 라이센스(Apache License)
readme.txt : Anyframe Gen 소개 및 기본 사항
Anyframe Gen 설치를 위해 Anyframe-gen-x.x.x.x-setup.jar 파일을 실행시킨다.
다음 순서대로 설치를 진행한다.
Apache License에 동의하고 Next 버튼 클릭하면 Anyframe Gen 을 설치할 경로를 지정할 수 있는 창이 조회된다. Anyframe Gen을 설치하고자 하는 폴더를 선택한 후 Next 선택하여 설치를 완료한다. 이때 이 installation path 항목으로 입력된 정보가 Anyframe Gen이 설치된 root 경로 가 되며 이후 매뉴얼 내용에서 [Gen Home] 이라 통칭하도록 한다.
Anyframe Gen이 정해진 경로에 제대로 설치되어 있는지 확인해본다. 아래 그림과 같은 구조로 설치되어 있으면 정상이다. 설치 과정이 모두 완료되면 Anyframe에서 제공하는 모든 라이브러리들과 빌드 도구인 Ant, 프로젝트 및 코드 생성 템플릿, 공통 빌드 스크립트, 샘플 HSQL DB등이 모두 함께 설치 완료된다.

Command Line Interface를 사용하여 어플리케이션과 프로젝트 생성, Domain 클래스 및 CRUD 소스 코드 생성, 빌드 및 실행 등의 작업을 할 수 있다. 이때 [빌드]와 [빌드 및 실행]에서 수행하는 빌드가 중복되는 작업이므로 [빌드 및 실행]을 수행시키는 경우 [빌드] 단계는 수행시키지 않는다. CLI(Command Line Interface) 기반의 command를 실행하여 작업하는 경우, 아래 매뉴얼에서 정의한 command arguments 이외의 값 설정 혹은 반드시 필요한 arguments 생략 시 올바르게 동작하지 않을 수 있으므로 유의하도록 한다.
Command Line Interface을 사용하기 위한 환경 설정 및 도움말에 대해 알아보자.
Anyframe Gen 설치 폴더 하위의 bin 폴더에서 command 창을 실행 시킨 다음 env 명령어를 입력하여 env.bat 파일을 실행시킨다.(Windows 환경에서는 env.bat 파일을, Unix 환경에서는 env.sh 파일을 실행시킨다.) GEN_HOME, ANT_HOME, PATH, CLASSPATH, MAINCLASS 등의 환경 변수 설정이 수행된다.

Windows 환경에서는 env.bat 파일을 CLI 상에서 실행시키고, Unix 환경(ex. Mac OS 등)에서는 우선 bin 폴더 하위의 파일들에 대해서 실행 권한을 부여(chmod 755 *)한 후, env.sh 파일을 실행(source env.sh)시킨다. 수행시켜야 할 command는 각 내용의 괄호안을 참고하도록 한다.
Command를 통한 작업 시, 사용 가능한 command가 아래 그림과 같으며 이는 gen -help 라는 명령어를 통해 확인 가능하다. gen -help를 통해 확인할 수 있는 명령어는 Anyframe과 Anyframe Gen에서 제공하는 command가 함께 보이는 것이며, Anyframe Gen에서 제공하는 command를 중심으로 확인해본다. Anyframe에서 제공하는 command는 추후 제공되는 Anyframe의 매뉴얼을 참고하도록 한다.

현재 Anyframe Gen은 샘플 DB로 HSQL DB를 제공하고 있다. [Gen Home]\db\hsqldb\ 하위의 start.cmd 파일을 실행시켜서 DB를 구동한다. 탐색기로 해당 경로 이동 후, start.cmd 파일을 더블 클릭하면 hsqldb가 구동된다. 만약 Oracle과 같은 다른 DB를 사용한다면 DB를 구동시키고, 어플리케이션 생성 후에 DB 정보를 application-build.properties 파일에 입력해주도록 한다.
Windows 환경에서는 start.cmd 파일을 CLI 상에서 실행시키고, Unix 환경(ex. Mac OS 등)에서는 우선 hsqldb 폴더 하위의 파일들에 대해서 실행 권한을 부여(chmod 755 *)한 후, start.sh 파일을 실행(source start.sh)시킨다.
Single 프로젝트 구조에서 사용 가능한 command를 활용하여 어플리케이션 및 프로젝트 생성, Domain Class 및 CRUD 소스 코드 생성, 그리고 DB 정보 변경 등의 작업을 할 수 있다.
Command Line Interface를 이용해 어플리케이션을 생성해본다.
env를 통해 환경 변수 정보가 설정된 command 창에서 어플리케이션 생성을 위해 다음 command를 입력한다. 어플리케이션이 생성되는 위치는 command의 옵션에 의해 변경될 수 있다. 여기서는 default인 Gen Home 하위의 applications 폴더에 어플리케이션을 생성한다.
다음의 어플리케이션 생성 command를 입력한다.
gen create-app [-options]
ex) gen create-app -name emarketplace -package com.sds.emp
위 예제는 emarketplace라는 어플리케이션명을 가진 com.sds.emp 패키지의 어플리케이션을 생성하는 command로 아래와 같은 option 정보를 추가하여 어플리케이션 정보를 변경할 수 있다.
표 5.1. create-app options
| option | description | default value |
|---|---|---|
| -name | 어플리케이션 이름을 지정할 수 있는 옵션으로 이름을 지정하지 않는 경우 default value에 해당하는 어플리케이션이 생성된다. | myapp |
| -package | 어플리케이션의 대표 패키지명을 입력한다. 차후 소스 코드 생성 시 기준이 되는 소스 패키지명이 된다. | 어플리케이션명으로 -name에 지정한 값 |
| -structure |
single or multi 프로젝트 구조를 지정한다. 지정하지 않는 경우 single
프로젝트 구조로
생성된다.
*single: 1개의 웹 프로젝트 구조 *multi : 공통(common)/서비스(service)/웹(web) 타입 별 프로젝트 구조(즉, 여러 개의 프로젝트 구조 채택) | single |
| -dynamic | dynamic reloading 기능 사용 여부를 결정한다. 단, single 프로젝트 구조에서는 dynamic reloading 기능이 제공되지 않는다. | false |
| -app.home | 어플리케이션 생성위치를 설정한다. 옵션값을 설정하지 않으면 기본적으로 [Gen Home] 디렉토리 하위의 applications 폴더 아래에 생성된다. | [Gen Home]\applications\ |
어플리케이션 생성이 정상적으로 되었는지 확인한다.
생성된 어플리케이션에는 배포 파일이 위치하게 될 repo 폴더와 1개의 어플리케이션 설정 파일(application-build.properties)이 생성된다.
생성된 어플리케이션 설정 파일(Properties)을 수정하면, 이후 생성되는 프로젝트들이 수정된 설정 값을 통해 생성되도록 할 수 있다. 아래 표에 설명된 항목별 내용을 보고 DAO Framework, Template type 설정을 비롯하여 다양한 공통 속성 값을 변경시킬 수 있다. DB 관련한 설정 파일 설명에 대해서는 [DB 정보 변경]에 상세하게 설명되어 있다.
표 5.2. application-build.properties(어플리케이션 정보)
| Property Name | Description | Required | Default Value |
|---|---|---|---|
| gen.home | Anyframe Gen을 설치한 루트 폴더 | Y | N/A |
| app.name | 어플리케이션 명 | Y | N/A |
| app.home | 어플리케이션 루트 폴더 경로 | Y | N/A |
| app.package.name | 어플리케이션 대표 패키지 명 | Y | N/A |
| dynamic | Dynamic Reloading 기능 사용 여부 | Y | false |
| project.list | 어플리케이션 내에 생성되는 프로젝트 이름 목록 | Y | N/A |
| common.project.name | Common 타입 프로젝트 명 | Y | N/A |
| domain.project.name | Domain 타입 프로젝트 명 | Y | N/A |
| service.project.name | Service 타입 프로젝트 명 | Y | N/A |
| web.project.name | Web 타입 프로젝트 명 | N | N/A |
| dao.framework | DAO Framework 선택(query, hibernate 중 택일) | Y | query |
| emma.enabled | 프로젝트 빌드 시 emma를 이용하여 코드 커버리지 리포트 결과 생성 여부 | Y | true |
| template_type | 프로젝트 및 CRUD 소스 코드 생성 시 기반이 되는 Template 형태(ex. default, miplatform 등) | Y | default |
| project.structure | 프로젝트 구조 | Y | single |
| web.context.path | jetty run 으로 실행시킬때 사용되는 WebContext Path명 | Y | 어플리케이션 명 |
Command Line Interface를 이용해 프로젝트를 생성해본다. Single 프로젝트 구조에서는 프로젝트가 하나의 웹 프로젝트로 구성된다.
어플리케이션이 생성된 폴더 하위로 이동한다. (예를 들어, emarketplace 라는 어플리케이션을 생성시켰다면 emarketplace 폴더 하위에서 command를 실행시키도록 한다.)
Single 타입 프로젝트 생성 command를 입력한다.
gen create-project [-options]
ex) gen create-project -pjtname sample
위 예제는 sample이라는 이름을 가진 single 타입의 프로젝트를 생성하는 command로 아래와 같은 option 정보를 추가하여 프로젝트 정보를 변경할 수 있다.
표 5.3. create-project options
| option | description | default value |
|---|---|---|
| -pjtname | 프로젝트 명을 입력한다.프로젝트 명을 입력하지 않을 경우 default value에 해당하는 프로젝트가 생성된다. | myproject |
| -pjttype | 프로젝트 타입을 지정한다. single, common, service, web 타입이 있으며, single 타입은 single 프로젝트 구조에서 적용되며, common, service, web 타입은 multi 프로젝트 구조에서 사용된다. 이때 common과 web 타입 프로젝트는 1개씩 생성시킬 수 있고 service 타입 프로젝트는 복수개 생성시킬 수 있다. service 타입 프로젝트 중 최초로 생성되는 프로젝트가 application-build.properties 파일의 service.project.name 속성 값으로 저장된다. | single |
| -domain | 해당 프로젝트를 domain 프로젝트(Domain Class 생성 및 관리하는 프로젝트)로 사용할지 여부를 결정하는 옵션이다. single 프로젝트 구조에서는 하나의 프로젝트로 사용되므로 해당 프로젝트가 항상 domain 프로젝트로 사용된다. multi 프로젝트 구조에서는 common 혹은 service 타입 프로젝트를 domain 프로젝트로 지정할 수 있으며 default로 common 타입 프로젝트를 domain 프로젝트로 사용하지 않은 경우 첫번째로 생성시킨 service 타입 프로젝트가 domain 프로젝트로 사용됨에 유의하도록 한다. | false |
| -package | [Anyframe에서만 사용되는 옵션] 프로젝트의 소스 코드 패키지를 지정하는 옵션으로 Anyframe Gen에서는 어플리케이션 생성 시 어플리케이션 대표 패키지명을 설정하였으므로 따로 프로젝트 생성 시 이 옵션을 사용할 필요가 없다. | myapp |
| -repo | [Anyframe에서만 사용되는 옵션] 프로젝트에서 참조하는 라이브러리 파일들을 프로젝트 내로 가져오기 위해 바라보는 Repository 정보를 지정하는 옵션으로 Anyframe Gen을 사용할 경우 모든 참조 라이브러리 파일들이 [Gen Home] 폴더 하위의 repo 폴더에 존재하므로 해당 옵션은 따로 사용하지 않는다. | N/A |
single 타입의 프로젝트가 정상적으로 생성되었는지 확인한다.
프로젝트가 생성되면 eclipse 프로젝트 관련 파일들(.project, .classpath)과 Anyframe Foundation 샘플 및 테스트 코드, 빌드 파일(build.xml, build.properties), 설치된 Anyframe 플러그인 관련 폴더(.metadata) 등이 생성된다.
어플리케이션과 프로젝트를 생성한 후, Anyframe 에서 제공하는 다음 command 들을 통해 Anyframe 플러그인을 설치 또는 제거할 수 있다. 이 command 는 Single Project Structure 에서만 사용가능하다.
Anyframe Gen CLI를 통해서 생성할 소스코드의 DAO Framework 또는 Template Type을 디폴트로 지정된 값 이외의 값으로 설정하고 싶은 경우, 이와 관련한 Anyframe 플러그인이 설치되어 있어야 생성된 어플리케이션이 정상적으로 동작할 수 있다. 예를 들어, DAO Framework의 디폴트 설정은 Query Service로 되어 있지만 Hibernate/JPA 를 사용하고 싶은 경우, 어플리케이션 설정 파일((applicaation-build.properties) 의 dao.framework 의 값을 hibernate으로 변경하는 것 이외에, Anyframe 의 hibernate 플러그인을 설치하여야 한다. 어플리케이션 설정 파일과 관련한 설명은 [어플리케이션 생성]을 참조하도록 한다.
Anyframe 플러그인 설치
프로젝트가 생성된 폴더 하위로 이동한다. (예를 들어, sample 이라는 프로젝트를 생성시켰다면 sample 폴더 하위에서 command를 실행시키도록 한다.)
Anyframe 플러그인 설치 command를 입력한다.
gen install PLUGIN_NAME [-options]
ex) gen install hibernate -package com.sds.emp
위 예제는 hibernate 플러그인에 대한 샘플과 라이브러리를 설치하는 command로 설치되는 샘플의 패키지는 com.sds.emp로 설정된다.
표 5.4. install options
| option | description | default value |
|---|---|---|
| -package | 플러그인 설치 시 함께 설치되는 샘플 소스 코드의 패키지를 지정하는 옵션으로 지정하지 않았을 경우 src/main/java 밑에 상위패키지 없이 설치된다. | N/A |
| -repo | 프로젝트에서 참조하는 라이브러리 파일들을 프로젝트 내로 가져오기 위해 바라보는 Repository 정보를 지정하는 옵션으로 Anyframe Gen을 사용할 경우 모든 참조 라이브러리 파일들이 [Gen Home] 폴더 하위의 repo 폴더에 존재하므로 해당 옵션은 따로 사용하지 않는다. | N/A |
Anyframe 플러그인이 정상적으로 설치되었는지 확인한다.
Anyframe 플러그인이 정상적으로 설치되었다면, 지정한 패키지 경로에 설치한 플러그인 샘플 소스 코드가 생성되어 있고, src/main/webapp/WEB-INF/lib에 플러그인 관련 라이브러리가 설치되어 있다.
Anyframe 플러그인 제거
프로젝트가 생성된 폴더 하위로 이동한다. (예를 들어, sample 이라는 프로젝트를 생성시켰다면 sample 폴더 하위에서 command를 실행시키도록 한다.)
Anyframe 플러그인 제거 command를 입력한다.
gen uninstall PLUGIN_NAME [-options]
ex) gen uninstall hibernate
위 예제는 hibernate 플러그인에 대한 샘플과 라이브러리를 제거하는 command이다.
표 5.5. install options
| option | description | default value |
|---|---|---|
| -excludes | 플러그인 제거시 제외하고 싶은 파일명을 입력한다. 예를 들어, context-hibernate-services.xml 을 hibernate 플러그인 삭제 시 삭제되지 않게 하기 위해서는 -excludes context-hibernate-services.xml 로 옵션을 설정해준다. | N/A |
| -repo | 프로젝트에서 참조하는 라이브러리 파일들을 프로젝트 내로 가져오기 위해 바라보는 Repository 정보를 지정하는 옵션으로 Anyframe Gen을 사용할 경우 모든 참조 라이브러리 파일들이 [Gen Home] 폴더 하위의 repo 폴더에 존재하므로 해당 옵션은 따로 사용하지 않는다. | N/A |
Anyframe 플러그인이 정상적으로 제거되었는지 확인한다.
Anyframe 플러그인이 정상적으로 제거되었다면, 플러그인 샘플 소스 코드 및 관련 라이브러리가 제거된다.
Command Line Interface를 이용해 Domain Class를 생성해본다. 이때, 반드시 DB를 구동하여 다음 command를 수행한다. DB가 구동되지 않은 상태에서 Domain Class를 생성하는 경우 socket creation error가 발생한다. 기본적으로 DB 정보는 HSQL로 설정되나 이를 변경하고 싶은 경우 다음 [DB정보 변경] 을 참조한다.
Domain Class 생성 command를 입력한다.
gen create-model [-options]
ex) gen create-model -table "*" -basepackage com.sds.emp.domain
위 예제는 모든 테이블에 대해 Domain Class를 어플리케이션 생성 시 지정한 대표 패키지(ex. com.sds.emp) 하위의 domain 패키지 내에 생성하는 command로 아래와 같은 option 정보를 이용하여 Domain Class 생성 대상 및 패키지 정보를 변경할 수 있다.
표 5.6. create-model options
| option | description | default value |
|---|---|---|
| -table |
Domain Class를 생성하려는 대상 DB 테이블을 선정한다. 테이블에 대한 option
을 따로 설정하지
않는 경우 default로 모든 DB 테이블로부터 Domain Class를 생성하고 있다.
명시적으로 모든
DB
Table에 대해서 Domain Class를 생성하기 위해서는 "*" 로 옵션 값을
설정한다.
특정
테이블만
대상으로 Domain Class를 생성하고 싶은 경우 대상 DB 테이블명을 지정하면
된다. 여러
개의
테이블을
대상으로 할 때에는 "," 기호를 이용하여 작성하도록 한다.
* 이때 테이블명에 대해 대소문자를 구분하므로 유의하여 테이블명을 입력하도록 한다. ex) gen create-model -table BOARD,BOARD_MASTER -basepackage com.sds.emp.domain | "*" (모든 테이블 대상) |
| -basepackage | DB 테이블로부터 Domain Class를 생성 시 어느 소스 코드 패키지 하위에 생성시킬 지 결정하는 옵션으로, default로 어플리케이션 생성 시 설정한 대표패키지 + ".domain" 패키지 경로가 Domain Class 패키지 경로가 된다. | 어플리케이션 생성 시 지정한 대표 패키지.domain |
Domain Class 가 정상적으로 생성되었는지 확인한다.
Domain Class 생성 시 지정한 -basepackage 값에 해당하는 패키지에 -table 값에 해당하는 Domain Class가 있으면 정상이다. 아래는 생성된 Board.java 코드의 일부분이다.
@Entity
@Table(name = "BOARD", schema = "PUBLIC")
public class Board implements Serializable {
private BoardId id;
private BoardMaster boardMaster;
private String boardName;
중략...
public BoardId getId() {
return this.id;
}
public void setId(BoardId id) {
this.id = id;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "BOARD_MASTER_ID", nullable = false,
insertable = false, updatable = false)
public BoardMaster getBoardMaster() {
return this.boardMaster;
}
public void setBoardMaster(BoardMaster boardMaster) {
this.boardMaster = boardMaster;
}
@Column(name = "BOARD_NAME", nullable = false, length = 150)
public String getBoardName() {
return this.boardName;
}
public void setBoardName(String boardName) {
this.boardName = boardName;
}
}위에서 생성한 Domain Class를 기반으로 CRUD 소스 코드를 생성할 수 있다. 이때 Business Layer와 Presentation Layer 별로 구분하여 소스 코드를 생성할 수도 있고 함께 생성해낼 수도 있다. 각각의 경우로 나누어서 아래에 설명하고 있다. 아래 예제는 default 템플릿 타입으로 설정되어 있는 경우에 해당하며, 이 때 생성된 CRUD 소스코드는 annotation 기반으로 되어 있다.
Business Layer 코드 생성 command를 입력한다.
gen create-crud ENTITY [-options]
ex) gen create-crud Board -project sample -package board -scope service
위 예제는 Board Domain class를 기반으로 CRUD 소스 코드 생성 시 어플리케이션 대표 패키지(ex. com.sds.emp) + ".board" 패키지 하위에 business layer 코드를 생성시키는 command로 아래와 같은 option 정보를 이용하여 CRUD 소스 코드 생성 시 필요한 타켓 프로젝트와 패키지 경로 위치 그리고 생성 범위 등을 변경할 수 있다.
표 5.7. create-crud options
| option | description | default value |
|---|---|---|
| -project | CRUD 소스 코드 생성 후, 생성된 결과 코드를 위치시킬 프로젝트 명을 입력한다. single 프로젝트 구조에서는 하나의 프로젝트를 사용하므로 타켓 프로젝트 위치가 자동 지정되어 이 옵션을 사용할 필요가 없다. multi 프로젝트 구조에서는 생성된 business layer 코드를 위치시킬 service 타입 프로젝트 명을 설정한다. 지정하지 않은 경우 최초로 생성된 service 타입 프로젝트 명이 자동으로 설정된다. presentation layer 코드 생성 시에는 결과 코드를 위치시킬 web 타입 프로젝트가 하나만 존재하여 자동 지정되므로 사용할 필요가 없다. | application-build.properties 파일의 service.project.name 속성에 정의된 프로젝트 명 |
| -package | CRUD 소스 코드가 생성될 패키지명을 정하는 옵션으로, 어플리케이션 생성 시 지정한 대표 패키지 뒤에 붙게 된다. | Domain Class명(소문자)형태 |
| -scope | 생성할 코드가 business layer일 경우 service로 설정하고, presentation layer일 경우 web으로 설정한다. 두 layer에 대한 소스 코드 모두를 함께 생성할 경우 all로 설정한다. | all |
Business Layer 코드가 정상적으로 생성되었는지 확인한다.
서비스인터페이스, 서비스구현클래스, DAO인터페이스, DAO구현클래스와 매핑쿼리문등이 생성된다.
아래는 생성된 자바코드와 속성파일, 매핑쿼리문의 일부분이다. 서비스인터페이스, 서비스구현클래스, DAO인터페이스, DAO구현클래스는 Generic Service를 상속받아 구현되었으므로, 자세한 내용은 Generic Service를 참조한다.
서비스인터페이스 (src/main/java/[대표패키지]/[-package 값]/service/[Entity 클래스명]Service.java)
public interface BoardService extends GenericService<Board, BoardId> {
Page getPagingList(SearchVO searchVO) throws Exception;
}서비스구현클래스 (src/main/java/[대표패키지]/[-package 값]/service/impl/[Entity 클래스명]ServiceImpl.java)
@Service("boardService")
@Transactional(rollbackFor = {Exception.class}, propagation = Propagation.REQUIRED)
public class BoardServiceImpl extends GenericServiceImpl<Board, BoardId>
implements BoardService {
@Resource
private BoardDao boardDao;
@PostConstruct
public void initialize(){
super.setGenericDao(boardDao);
}
/** {@inheritDoc} */
public Page getPagingList(SearchVO searchVO) throws Exception {
return super.getGenericDao().getPagingList(searchVO);
}
}DAO인터페이스 (src/main/java/[대표패키지]/[-package 값]/dao/[Entity 클래스명]Dao.java)
public interface BoardDao extends GenericDao<Board, BoardId> {
Page getPagingList(SearchVO searchVO) throws Exception;
}DAO구현클래스 (src/main/java/[대표패키지]/[-package 값]/dao/impl/[Entity 클래스명]Dao[DAO Framework 명]Impl.java)
@Repository("boardDao")
public class BoardDaoQueryImpl extends GenericDaoQuery<Board, BoardId>
implements BoardDao {
@Resource
IQueryService queryService;
@Resource
IPropertiesService propertiesService;
public BoardDaoQueryImpl() {
super(Board.class);
}
@PostConstruct
public void initialize(){
super.setQueryService(queryService);
super.setPropertiesService(propertiesService);
}
/** {@inheritDoc} */
public Page getPagingList(SearchVO searchVO) throws Exception {
int pageIndex = searchVO.getPageIndex();
int pageSize = super.getPropertiesService().getInt("PAGE_SIZE");
int pageUnit = super.getPropertiesService().getInt("PAGE_UNIT");
중략...
return super.findListWithPaging(ClassUtils.getShortName(getPersistentClass()),
args, pageIndex, pageSize, pageUnit);
}
}매핑쿼리문 (src/main/resources/query/mapping-query-[Entity 클래스명].xml)
<queryservice>
<queries>
<query id="createBoard">
<statement>
INSERT INTO BOARD (BOARD_ID, BOARD_DESC, BOARD_MASTER_ID, BOARD_NAME,
BOARD_ORDER, BOARD_TOPICS, REG_DATE)
VALUES (:vo.id.boardId, :vo.boardDesc, :vo.id.boardMasterId, :vo.boardName,
:vo.boardOrder, :vo.boardTopics, :vo.regDate)
</statement>
</query>
중략...
</queries>
</queryservice>MessageSoruce (src/main/resources/message/message-generation.properties)
# -- Board-START board.id.boardId=Board Id board.id.boardMasterId=Board Master Id board.boardDesc=Board Desc board.boardName=Board Name board.boardOrder=Board Order board.boardTopics=Board Topics board.regDate=Reg Date # -- success messages -- success.board.create=Board has been added successfully. success.board.update=Board has been updated successfully. success.board.delete=Board has been deleted successfully. # -- error messages -- error.boardserviceimpl.create=Board data not created error.boardserviceimpl.create.solution=Enter correct data for mandatory field or enter data according to formats means date format as yyyy-mm-dd error.boardserviceimpl.create.reason=Entered incorrect data for Board 중략...
통합테스트케이스 (src/test/java/[대표패키지]/[-package 값]/dao/[Entity 클래스명]DaoTest.java)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:/spring/context-*.xml" })
public class BoardDaoTest{
@Resource(name="boardDao")
private BoardDao boardDao;
@Test
public void testAddAndRemoveBoard() throws Exception {
Board board = new Board();
BoardId id = new BoardId();
id.setBoardId(new Integer(1732013925));
id.setBoardMasterId(new Integer(1681092908));
board.setId(id);
중략...
}
}단위테스트 케이스 (src/test/java/[대표패키지]/[-package 값]/service/impl/[Entity 클래스명]ServiceImplTest.java)
@RunWith(JMock.class)
public class BoardServiceImplTest{
private BoardServiceImpl service = null;
private BoardDao dao = null;
private Mockery context = new JUnit4Mockery();
@Before
public void setUp() {
System.setProperty("log4j.configuration", "log4j-test.xml");
this.dao = context.mock(BoardDao.class);
this.service = new BoardServiceImpl();
ObjectUtil.setField(this.service, "boardDao", this.dao);
this.service.initialize();
}
@After
public void tearDown() {
service = null;
}
@Test
public void testGetBoard() throws Exception {
log.debug("testing get...");
final BoardId id = new BoardId();
id.setBoardId(257077485);
id.setBoardMasterId(555604496);
final Board board = new Board();
// set expected behavior on dao
context.checking(new Expectations() {{
one(dao).get(with(equal(id)));
will(returnValue(board));
}});
Board result = service.get(id);
assertSame(board, result);
}
중략...application-build.properties 에서 dao.framework 값을 변경하지 않았을 경우 기본 DAO Framework 은 Query Service 로 설정되어 있다. 위의 경우는 Query Service로 설정되어 있는 경우에 해당한다.
application-build.properties 에서 dao.framework 값을 hibernate 으로 설정하여 DAO Framework 으로 Hibernate 을 사용하는 경우, CRUD 소스코드 생성시 DAO구현 클래스는 BoardDaoHibernateImpl.java 로, 매핑쿼리문은 hibernate/dynamic/dynamic-hibernate-board.xml 형태로 생성된다.
Presentation Layer 코드 생성 command를 입력한다.
gen create-crud ENTITY [-options]
ex) gen create-crud Board -project sample -package board -scope web
위 예제는 Board Domain class를 기반으로 CRUD 소스 코드 생성 시 어플리케이션 대표 패키지(ex. com.sds.emp) + ".board" 패키지 하위에 presentation layer 코드를 생성시키는 command이다.
표 5.8. create-crud options
| option | description | default value |
|---|---|---|
| -project | CRUD 소스 코드 생성 후, 생성된 결과 코드를 위치시킬 프로젝트 명을 입력한다. presentation layer 코드 생성 시에는 결과 코드를 위치시킬 web 타입 프로젝트가 하나만 존재하여 자동 지정되므로 사용할 필요가 없다. | application-build.properties 파일의 service.project.name 속성에 정의된 프로젝트 명 |
| -package | CRUD 소스 코드가 생성될 패키지명을 정하는 옵션으로, 어플리케이션 생성 시 지정한 대표 패키지 뒤에 붙게 된다. | Domain Class명(소문자)형태 |
| -scope | 생성할 코드가 business layer일 경우 service로 설정하고, presentation layer일 경우 web으로 설정한다. 두 layer에 대한 소스 코드 모두를 함께 생성할 경우 all로 설정한다. | all |
Presentation Layer 코드가 정상적으로 생성되었는지 확인한다.
서비스와 통신을 하기 위한 컨트롤러 파일, UI파일(JSP 또는 MiPlatform 용 XML파일) 등이 생성된다.
컨트롤러 (src/main/java/[대표패키지]/[-package 값]/web/[Entity 클래스명]Controller.java)
@Controller
@RequestMapping("/board.do")
public class BoardController {
/**
* Resource Injection on BoardService
*/
@Resource(name="boardService")
private BoardService boardService;
중략...
/**
* Display Board list.
* @param request current HTTP request
* @param searchVO form object with request parameters bound onto it
* @param model model containing control data
* @return the prepared Board list view
* @throws Exception in case of getting Board paging list
*/
@RequestMapping(params = "method=list")
public String list(HttpServletRequest request,
@ModelAttribute("search") SearchVO searchVO, Model model) throws Exception
{
String pageParam = (new ParamEncoder("boardList").
encodeParameterName(TableTagParameters.PARAMETER_PAGE));
String pageParamValue = request.getParameter(pageParam);
int pageIndex = StringUtil.isNotEmpty(pageParamValue) ?
(Integer.parseInt(pageParamValue)) : 1;
searchVO.setPageIndex(pageIndex);
Page resultPage = boardService.getPagingList(searchVO);
model.addAttribute("boardList", resultPage.getList());
model.addAttribute("size", resultPage.getTotalCount());
model.addAttribute("pagesize", resultPage.getPagesize());
model.addAttribute("pageunit", resultPage.getPageunit());
return "generation/board/listBoard";
}
}UI JSP 파일 (src/main/webapp/WEB-INF/jsp/[프로젝트명]/*.jsp)
<%@ include file="/sample/common/taglibs.jsp"%>
<html>
<head>
<%@ include file="/sample/common/meta.jsp" %>
<title><fmt:message key="boardList.title"/></title>
<meta name="heading" content="<fmt:message key='boardList.heading'/>"/>
<link rel="stylesheet" type="text/css" media="all"
href="<c:url value='/sample/css/displaytag.css'/>" />
<link rel="stylesheet" href="<c:url value='/sample/css/admin.css'/>"
type="text/css">
<script type="text/javascript"
src="<c:url value='/sample/javascript/prototype.js'/>"></script>
<script type="text/javascript"
src="<c:url value='/sample/javascript/global.js'/>"></script>
<script type="text/javascript"
src="<c:url value='/sample/javascript/CommonScript.js'/>"></script>
<script language="JavaScript">
function fncAddBoardView() {
document.location.href="<c:url value='/board.do?method=addView'/>";
}
function fncSearchBoard(arg) {
var conditions = ["boardId","boardMasterId","boardTopics"]
중략...단위테스트케이스 (src/test/java/[대표패키지]/[-package 값]/web/[Entity 클래스명]ControllerTest.java)
@RunWith(JMock.class)
public class BoardControllerTest {
private BoardController controller;
private String SUCCESS_ADDVIEW = "generation/board/viewBoard";
private String SUCCESS_ADD = "redirect:/board.do?method=list";
private String SUCCESS_GET = "generation/board/viewBoard";
private String SUCCESS_UPDATE = "forward:/board.do?method=list";
private String SUCCESS_LIST = "generation/board/listBoard";
private String SUCCESS_DELETE = "redirect:/board.do?method=list";
private Mockery context = new JUnit4Mockery();
private BoardService mockService = null;
@Before
public void setUp() throws Exception {
System.setProperty("log4j.configuration", "log4j-test.xml");
this.mockService = context.mock(BoardService.class);
this.controller = new BoardController();
this.controller.setBoardService(this.mockService);
}
public void setBoardController(BoardController controller) {
this.controller = controller;
}
@Test
public void testAddView() throws Exception{
String viewName = this.controller.addView(new ExtendedModelMap());
assertEquals("returned correct view name", SUCCESS_ADDVIEW, viewName);
}
중략...현재 Presentation Layer 코드를 생성하면 Spring MVC + JSP UI Page(default template 선택 시) 혹은 Spring MVC + MiPlatform UI(miplatform template 선택 시)에 해당하는 소스 코드가 생성된다.
이중 default template의 경우 목록 조회 화면과 상세 조회 화면을 일반 JSP 페이지로 생성해내지만, 목록 조회 화면의 경우 Display Tag Library를 이용하여 페이징 처리, Sorting 등의 공통 기능을 제공해주고 있다. Display Tag Library에 대한 자세한 사용법은 Display Tag Library 사이트 를 참고하도록 한다.
아래는 Display Tag를 사용한 JSP 페이지 예제이다.
<display:table name="usersList" class="table" requestURI="users.do"
id="usersList" export="true" partialList="true" size="size"
pagesize="${pagesize}" style="margin-top:10px;">
<display:column property="userId" sortable="true"
href="users.do?method=get"
media="html" paramId="userId" paramProperty="userId"
titleKey="users.userId"/>
<display:column property="password" sortable="true"
titleKey="users.password" maxLength="20" />
<display:column property="userName" sortable="true"
titleKey="users.userName" maxLength="20" />
<display:setProperty name="export.excel.filename">
<fmt:message key="usersList.title"/>.xls
</display:setProperty>
<display:setProperty name="export.pdf.filename">
<fmt:message key="usersList.title"/>.pdf
</display:setProperty>
</display:table>Business Layer 와 Presentation Layer 코드 생성 command를 입력한다.
gen create-crud ENTITY [-options]
ex) gen create-crud Board -project sample -package board -scope all
위 예제는 Board Domain class를 기반으로 CRUD 소스 코드 생성 시 어플리케이션 대표 패키지(ex. com.sds.emp) + ".board" 패키지 하위에 business layer 코드와 presentation layer 코드를 함께 생성시키는 command이다.
표 5.9. create-crud options
| option | description | default value |
|---|---|---|
| -project | CRUD 소스 코드 생성 후, 생성된 결과 코드를 위치시킬 프로젝트 명을 입력한다. single 프로젝트 구조에서는 하나의 프로젝트를 사용하므로 타켓 프로젝트 위치가 자동 지정되어 이 옵션을 사용할 필요가 없다. multi 프로젝트 구조에서는 생성된 business layer 코드를 위치시킬 service 타입 프로젝트 명을 설정한다. 지정하지 않은 경우 최초로 생성된 service 타입 프로젝트 명이 자동으로 설정된다. presentation layer 코드 생성 시에는 결과 코드를 위치시킬 web 타입 프로젝트가 하나만 존재하여 자동 지정되므로 사용할 필요가 없다. | application-build.properties 파일의 service.project.name 속성에 정의된 프로젝트 명 |
| -package | CRUD 소스 코드가 생성될 패키지명을 정하는 옵션으로, 어플리케이션 생성 시 지정한 대표 패키지 뒤에 붙게 된다. | Domain Class명(소문자)형태 |
| -scope | 생성할 코드가 business layer일 경우 service로 설정하고, presentation layer일 경우 web으로 설정한다. 두 layer에 대한 소스 코드 모두를 함께 생성할 경우 all로 설정한다. | all |
Business Layer, Presentation Layer 코드가 정상적으로 생성되었는지 확인한다. dao,service,web 폴더가 존재하여야 하며, 각각 business layer, presentation layer 생성 시 결과 화면을 참조하여 확인해보도록 한다.
Command Line Interface를 이용하여 application-build.properties 파일에 변경한 DB 설정 정보를 프로젝트 내 관련 파일들에 모두 반영되도록 한다. default로 HSQL DB를 사용하는 sampledb를 제공하고 있다. 해당 프로젝트에서 HSQL DB가 아닌 다른 DB를 사용하는 경우 application-build.properties 파일을 수정해준 뒤, DB 정보 변경 command를 실행시켜준다.
application-build.properties파일(생성한 어플리케이션 폴더 하위에 위치)을 열어 DB 설정 정보를 수정한다.
표 5.10. application-build.properties I (DB 정보)
| property name | description | required | default value |
|---|---|---|---|
| db_type | DB 정보(HSQL, Oracle, MySQL, Sybase 등) | Y | HSQL |
| db_name | Database 명 | Y | sampledb |
| schema | schema 명 | N | PUBLIC |
| username | DB 사용자 명 | Y | sa |
| password | DB 사용자 패스워드 | N | |
| server | DB에 접근하기 위한 server 정보 (ex.70.7.105.123) | Y | localhost |
| port | DB에 접근하기 위한 port 번호 | Y | -1 |
| driver_class |
DB의 드라이버 클래스를 설정한다. Default Value로는 HSQL의 드라이버 클래스 값이며, DB에 맞는
값을 찾아 설정하면
된다.
ex. Oracle: oracle.jdbc.driver.OracleDriver ex. MySQL: com.mysql.jdbc.Driver ex. Sybase: com.sybase.jdbc3.jdbc.SybDataSource | Y | org.hsqldb. jdbcDriver |
| driver_jar _path |
DB에 접근하기 위한 driver jar 파일 경로를 설정한다. Default Value로는 HSQL의
driver jar파일 경로 값이며, DB에 맞는 driver
jar 파일을 찾아 경로를 설정하면 된다.
ex. Oracle: ojdbc-XX.jar ex. MySQL: mysql-connector-java-X.X.XX-bin.jar ex. Sybase: jconnX.jar | Y | [Gen Home]/repo/ hsqldb/hsqldb/ 1.8.0.10/ hsqldb- 1.8.0.10.jar |
| url | DB에 접근하기 위한 Access URL | Y | jdbc: hsqldb:hsql: //localhost /sampledb |
표 5.11. application-build.properties II (DB 관련 정보)
| property name | description | required | default value |
|---|---|---|---|
| dialect |
DB별 Hibernate Dialect 클래스를 설정한다. Default Value로는 HSQL의
dialect값이며, DB에 맞는 값을 찾아 설정하면 된다.
ex. Oracle: org.hibernate.dialect. OracleDialect(10g의 경우 org.hibernatedialect. Oracle10gDialect) ex. MySQL: org.hibernate.dialect. MySQLDialect ex. Sybase: org.hibernate.dialect. SybaseDialect | Y | org.hibernate.dialect. HSQLDialect |
| paging _generator |
[Query Service에서 사용] 목록 조회 시 페이징 처리를 지원하기 위한 SQL 생성 클래스명을 설정한다.
Default Value로는 HSQL의 paging generator 값이며, DB에 맞는 값을
설정하면 된다.
MySQL과 Sybase는 현재 지원되지 않는다.
ex. Oracle: anyframe.core.query.impl. jdbc.generator.OraclePagingSQLGenerator | N | anyframe.core.query. impl.jdbc.generator. HSQLPaging SQLGenerator |
| lobhandler |
[Query Service에서 사용] BLOB,CLOB과 같은 Large Data Type을 핸들링하는
클래스명을
설정한다. Default Value로는 HSQL의lobhandler 값이며, HSQL은 lob type을
지원하지
않으므로
공란으로 비워둔다. 각 DB에 맞는lobhandler 값을 찾아 설정한다.
ex. Oracle: org.springframework.jdbc.support. lob.OracleLobHandler ex. MySQL: org.springframework.jdbc.support. lob.DefaultLobHandler ex. Sybase: org.springframework.jdbc.support. lob.DefaultLobHandler | N | N/A |
DB 변경 command를 입력한다. application-build.properties 파일의 DB 정보를 참조로 하여 DB 설정 내용을 반영한다.
gen change-db
DB 정보가 정상적으로 변경되었는지 확인한다.
프로젝트 코드 내 DataSource Service 설정 정보 및 Hibernate, Query Service 관련 정보들이 변경되었는지 확인한다. (ex. src/main/resources/spring/context-datasource.xml)
현재 Anyframe Gen에서는 5개의 DB를 지원하고 있다.(HSQL, Oracle, MySQL, Sybase, DB2) 프로젝트에서 작업하려는 DB가 이 5가지 중 하나라면 [Gen Home]/db/jdbc.config 파일을 열어서 사용하려는 DB 정보가 등록되었는지 확인한다.
<list>
<jdbcType>
<type>Oracle</type>
<driver>oracle.jdbc.driver.OracleDriver</driver>
<dialect>
<string>org.hibernate.dialect.OracleDialect</string>
<string>org.hibernate.dialect.Oracle10gDialect</string>
</dialect>
<port>1521</port>
<pagingGenerator>anyframe.core.query.impl.jdbc.generator.
OraclePagingSQLGenerator</pagingGenerator>
<lobHandler>org.springframework.jdbc.support.lob.OracleLobHandler
</lobHandler>
</jdbcType>
중략...만약 이외의 다른 DB를 사용하려면 Anyframe 이슈 관리 시스템 에 등록해주시기 바랍니다.
Multi 프로젝트 구조에서 사용 가능한 command를 활용하여 어플리케이션 및 프로젝트 생성, Domain Class 및 CRUD 소스 코드 생성, 그리고 DB 정보 변경 등의 작업을 할 수 있다.
Command Line Interface를 이용해 어플리케이션을 생성해본다.
env를 통해 환경 변수 정보가 설정된 command 창에서 어플리케이션 생성을 위해 다음 command를 입력한다. 어플리케이션이 생성되는 위치는 command의 옵션에 의해 변경될 수 있다. 여기서는 default인 Gen Home 하위의 applications 폴더에 어플리케이션을 생성한다.
다음의 어플리케이션 생성 command를 입력한다.
gen create-app -structure multi [-options]
ex) gen create-app -name emarketplace -package com.sds.emp -structure multi
위 예제는 emarketplace라는 어플리케이션명을 가진 com.sds.emp 패키지의 multi 프로젝트 구조의 어플리케이션을 생성하는 command이다. 즉, 하나의 어플리케이션이 여러 개의 프로젝트로 구성될 것이다.
표 6.1. create-app options
| option | description | default value |
|---|---|---|
| -name | 어플리케이션 이름을 지정할 수 있는 옵션으로 이름을 지정하지 않는 경우 default value에 해당하는 어플리케이션이 생성된다. | myapp |
| -package | 어플리케이션의 대표 패키지명을 입력한다. 차후 소스 코드 생성 시 기준이 되는 소스 패키지명이 된다. | 어플리케이션명으로 -name에 지정한 값 |
| -structure |
single or multi 프로젝트 구조를 지정한다. 지정하지 않는 경우 single
프로젝트 구조로
생성된다.
*single: 1개의 웹 프로젝트 구조 *multi : 공통(common)/서비스(service)/웹(web) 타입 별 프로젝트 구조(즉, 여러 개의 프로젝트 구조 채택) | single |
| -dynamic | dynamic reloading 기능 사용 여부를 결정한다. 단, single 프로젝트 구조에서는 dynamic reloading 기능이 제공되지 않는다. | false |
| -app.home | 어플리케이션 생성위치를 설정한다. 옵션값을 설정하지 않으면 기본적으로 [Gen Home] 디렉토리 하위의 applications 폴더 아래에 생성된다. | [Gen Home]\applications\ |
어플리케이션 생성이 정상적으로 되었는지 확인한다. 생성된 어플리케이션에는 다음과 같이, 배포 파일이 위치하게 될 repo 폴더와 1개의 Properties 파일(application-build.properties)이 생성된다.
생성된 어플리케이션 설정 파일(Properties)을 수정하면, 이후 생성되는 프로젝트들이 수정된 설정 값을 통해 생성되도록 할 수 있다. 아래 표에 설명된 항목별 내용을 보고 DAO Framework, Template type 설정을 비롯하여 다양한 공통 속성 값을 변경시킬 수 있다. DB 관련한 설정 파일 설명에 대해서는 [DB 정보 변경]에 상세하게 설명되어 있다.
표 6.2. application-build.properties(어플리케이션 정보)
| Property Name | Description | Required | Default Value |
|---|---|---|---|
| gen.home | Anyframe Gen을 설치한 루트 폴더 | Y | N/A |
| app.name | 어플리케이션 명 | Y | N/A |
| app.home | 어플리케이션 루트 폴더 경로 | Y | N/A |
| app.package.name | 어플리케이션 대표 패키지 명 | Y | N/A |
| dynamic | Dynamic Reloading 기능 사용 여부 | Y | false |
| project.list | 어플리케이션 내에 생성되는 프로젝트 이름 목록 | Y | N/A |
| common.project.name | Common 타입 프로젝트 명 | Y | N/A |
| domain.project.name | Domain 타입 프로젝트 명 | Y | N/A |
| service.project.name | Service 타입 프로젝트 명 | Y | N/A |
| web.project.name | Web 타입 프로젝트 명 | N | N/A |
| dao.framework | DAO Framework 선택(query, hibernate 중 택일) | Y | query |
| emma.enabled | 프로젝트 빌드 시 emma를 이용하여 코드 커버리지 리포트 결과 생성 여부 | Y | true |
| template_type | 프로젝트 및 CRUD 소스 코드 생성 시 기반이 되는 Template 형태(ex. default, miplatform 등) | Y | default |
| project.structure | 프로젝트 구조 | Y | single |
| web.context.path | jetty run 으로 실행시킬때 사용되는 WebContext Path명 | Y | 어플리케이션 명 |
Command Line Interface 를 이용해 프로젝트를 생성해본다. 공통(common), 서비스(service), 웹(web) 타입 별 프로젝트를 생성할 수 있다.
공통 타입 프로젝트는 해당 어플리케이션 내에서 단 1개의 프로젝트만 생성시킬 수 있으며 반드시 하나의 어플리케이션 내에서 하나의 공통 타입 프로젝트를 필수로 생성시키도록 한다.
어플리케이션이 생성된 폴더 하위로 이동한다. (예를 들어, emarketplace 라는 어플리케이션을 생성시켰다면 emarketplace 폴더 하위에서 command를 실행시키도록 한다.)
common 타입 프로젝트 생성 command를 입력한다.
gen create-project -pjttype common [-options]
multi 프로젝트 구조에서 common 타입 프로젝트를 생성하기 위해서는 반드시 -pjttype common 옵션을 설정해줘야 한다.
ex) gen create-project -pjttype common -pjtname common
위 예제는 common 타입으로 common이라는 이름의 프로젝트를 생성하는 command이다.
표 6.3. create-project options
| option | description | default value |
|---|---|---|
| -pjtname | 프로젝트 명을 입력한다.프로젝트 명을 입력하지 않을 경우 default value에 해당하는 프로젝트가 생성된다. -pjttype 옵션 값을 사용한 경우 pjttype 옵션 값이 디폴트 프로젝트 명으로 설정된다. | -pjttype 옵션 값 |
| -pjttype | 프로젝트 타입을 지정한다. single, common, service, web 타입이 있으며, single 타입은 single 프로젝트 구조에서 적용되며, common, service, web 타입은 multi 프로젝트 구조에서 사용된다. 이때 common과 web 타입 프로젝트는 1개씩 생성시킬 수 있고 service 타입 프로젝트는 복수개 생성시킬 수 있다. service 타입 프로젝트 중 최초로 생성되는 프로젝트가 application-build.properties 파일의 service.project.name 속성 값으로 저장된다. | single |
| -domain | 해당 프로젝트를 domain 프로젝트(Domain Class 생성 및 관리하는 프로젝트)로 사용할지 여부를 결정하는 옵션이다. single 프로젝트 구조에서는 하나의 프로젝트로 사용되므로 해당 프로젝트가 항상 domain 프로젝트로 사용된다. multi 프로젝트 구조에서는 common 혹은 service 타입 프로젝트를 domain 프로젝트로 지정할 수 있으며 default로 common 타입 프로젝트를 domain 프로젝트로 사용하지 않은 경우 첫번째로 생성시킨 service 타입 프로젝트가 domain 프로젝트로 사용됨에 유의하도록 한다. | false |
| -package | [Anyframe에서만 사용되는 옵션] 프로젝트의 소스 코드 패키지를 지정하는 옵션으로 Anyframe Gen에서는 어플리케이션 생성 시 어플리케이션 대표 패키지명을 설정하였으므로 따로 프로젝트 생성 시 이 옵션을 사용할 필요가 없다. | myapp |
| -repo | [Anyframe에서만 사용되는 옵션] 프로젝트에서 참조하는 라이브러리 파일들을 프로젝트 내로 가져오기 위해 바라보는 Repository 정보를 지정하는 옵션으로 Anyframe Gen을 사용할 경우 모든 참조 라이브러리 파일들이 [Gen Home] 폴더 하위의 repo 폴더에 존재하므로 해당 옵션은 따로 사용하지 않는다. | N/A |
common 타입의 프로젝트가 정상적으로 생성되었는지 확인한다.
프로젝트가 생성되면 eclipse 프로젝트 관련 파일들(.project, .classpath)과 logging, Exception Aspect 기능을 구현한 클래스 및 공통설정파일, 빌드 파일(build.xml, build.properties) 등이 생성된다.
공통(common)타입 프로젝트를 생성한 뒤에 서비스(service) 타입 프로젝트를 생성해야 함에 유의한다.
서비스 타입 프로젝트는 해당 어플리케이션 내에서 1개 이상의 복수개 프로젝트로 생성시킬 수 있으나 반드시 하나의 어플리케이션 내에서 하나의 서비스 타입 프로젝트를 필수로 생성시키도록 한다.
어플리케이션이 생성된 폴더 하위로 이동한다. (예를 들어, emarketplace 라는 어플리케이션을 생성시켰다면 emarketplace 폴더 하위에서 command를 실행시키도록 한다.)
service 타입 프로젝트 생성 command를 입력한다.
gen create-project -pjttype service [-options]
multi 프로젝트 구조에서 service 타입 프로젝트를 생성하기 위해서는 반드시 -pjttype service 옵션을 설정해줘야 한다.
ex) gen create-project -pjttype service -pjtname service
위 예제는 service 타입으로 service라는 이름의 프로젝트를 생성하는 command이다.
표 6.4. create-project options
| option | description | default value |
|---|---|---|
| -pjtname | 프로젝트 명을 입력한다.프로젝트 명을 입력하지 않을 경우 default value에 해당하는 프로젝트가 생성된다. -pjttype 옵션 값을 사용한 경우 pjttype 옵션 값이 디폴트 프로젝트 명으로 설정된다. | -pjttype 옵션 값 |
| -pjttype | 프로젝트 타입을 지정한다. single, common, service, web 타입이 있으며, single 타입은 single 프로젝트 구조에서 적용되며, common, service, web 타입은 multi 프로젝트 구조에서 사용된다. 이때 common과 web 타입 프로젝트는 1개씩 생성시킬 수 있고 service 타입 프로젝트는 복수개 생성시킬 수 있다. service 타입 프로젝트 중 최초로 생성되는 프로젝트가 application-build.properties 파일의 service.project.name 속성 값으로 저장된다. | single |
| -domain | 해당 프로젝트를 domain 프로젝트(Domain Class 생성 및 관리하는 프로젝트)로 사용할지 여부를 결정하는 옵션이다. single 프로젝트 구조에서는 하나의 프로젝트로 사용되므로 해당 프로젝트가 항상 domain 프로젝트로 사용된다. multi 프로젝트 구조에서는 common 혹은 service 타입 프로젝트를 domain 프로젝트로 지정할 수 있으며 default로 common 타입 프로젝트를 domain 프로젝트로 사용하지 않은 경우 첫번째로 생성시킨 service 타입 프로젝트가 domain 프로젝트로 사용됨에 유의하도록 한다. | false |
| -package | [Anyframe에서만 사용되는 옵션] 프로젝트의 소스 코드 패키지를 지정하는 옵션으로 Anyframe Gen에서는 어플리케이션 생성 시 어플리케이션 대표 패키지명을 설정하였으므로 따로 프로젝트 생성 시 이 옵션을 사용할 필요가 없다. | myapp |
| -repo | [Anyframe에서만 사용되는 옵션] 프로젝트에서 참조하는 라이브러리 파일들을 프로젝트 내로 가져오기 위해 바라보는 Repository 정보를 지정하는 옵션으로 Anyframe Gen을 사용할 경우 모든 참조 라이브러리 파일들이 [Gen Home] 폴더 하위의 repo 폴더에 존재하므로 해당 옵션은 따로 사용하지 않는다. | N/A |
service 타입의 프로젝트가 정상적으로 생성되었는지 확인한다.
프로젝트가 생성되면 eclipse 프로젝트 관련 파일들(.project, .classpath)과 도메인 클래스, 샘플 소스 및 테스트 코드, 빌드 파일(build.xml, build.properties) 등이 생성된다.
공통(common)타입과 서비스(service) 타입 프로젝트를 생성한 뒤에 웹(web) 타입 프로젝트를 생성해야 함에 유의한다.
웹 타입 프로젝트는 해당 어플리케이션 내에서 단 1개의 프로젝트만 생성시킬 수 있으나 반드시 하나의 어플리케이션 내에서 웹 타입 프로젝트를 필수로 생성시키지 않아도 된다. 웹 어플리케이션으로 개발 시에만 웹 타입 프로젝트를 생성시키도록 한다.
어플리케이션이 생성된 폴더 하위로 이동한다. (예를 들어, emarketplace 라는 어플리케이션을 생성시켰다면 emarketplace 폴더 하위에서 command를 실행시키도록 한다.)
web 타입 프로젝트 생성 command를 입력한다.
gen create-project -pjttype web [-options]
multi 프로젝트 구조에서 web 타입 프로젝트를 생성하기 위해서는 반드시 -pjttype web 옵션을 설정해줘야 한다.
ex) gen create-project -pjttype web -pjtname web
위 예제는 web 타입으로 web이라는 이름의 프로젝트를 생성하는 command이다.
표 6.5. create-project options
| option | description | default value |
|---|---|---|
| -pjtname | 프로젝트 명을 입력한다.프로젝트 명을 입력하지 않을 경우 default value에 해당하는 프로젝트가 생성된다. -pjttype 옵션 값을 사용한 경우 pjttype 옵션 값이 디폴트 프로젝트 명으로 설정된다. | -pjttype 옵션 값 |
| -pjttype | 프로젝트 타입을 지정한다. single, common, service, web 타입이 있으며, single 타입은 single 프로젝트 구조에서 적용되며, common, service, web 타입은 multi 프로젝트 구조에서 사용된다. 이때 common과 web 타입 프로젝트는 1개씩 생성시킬 수 있고 service 타입 프로젝트는 복수개 생성시킬 수 있다. service 타입 프로젝트 중 최초로 생성되는 프로젝트가 application-build.properties 파일의 service.project.name 속성 값으로 저장된다. | single |
| -domain | 해당 프로젝트를 domain 프로젝트(Domain Class 생성 및 관리하는 프로젝트)로 사용할지 여부를 결정하는 옵션이다. single 프로젝트 구조에서는 하나의 프로젝트로 사용되므로 해당 프로젝트가 항상 domain 프로젝트로 사용된다. multi 프로젝트 구조에서는 common 혹은 service 타입 프로젝트를 domain 프로젝트로 지정할 수 있으며 default로 common 타입 프로젝트를 domain 프로젝트로 사용하지 않은 경우 첫번째로 생성시킨 service 타입 프로젝트가 domain 프로젝트로 사용됨에 유의하도록 한다. | false |
| -package | [Anyframe에서만 사용되는 옵션] 프로젝트의 소스 코드 패키지를 지정하는 옵션으로 Anyframe Gen에서는 어플리케이션 생성 시 어플리케이션 대표 패키지명을 설정하였으므로 따로 프로젝트 생성 시 이 옵션을 사용할 필요가 없다. | myapp |
| -repo | [Anyframe에서만 사용되는 옵션] 프로젝트에서 참조하는 라이브러리 파일들을 프로젝트 내로 가져오기 위해 바라보는 Repository 정보를 지정하는 옵션으로 Anyframe Gen을 사용할 경우 모든 참조 라이브러리 파일들이 [Gen Home] 폴더 하위의 repo 폴더에 존재하므로 해당 옵션은 따로 사용하지 않는다. | N/A |
web 타입의 프로젝트가 정상적으로 생성되었는지 확인한다.
프로젝트가 생성되면 eclipse 프로젝트 관련 파일들(.project, .classpath)과 컨트롤러, 샘플 소스 및 테스트 코드, 빌드 파일(build.xml, build.properties) 등이 생성되며 src/main/webapp/WEB-INF/lib 폴더 하위에 필요 라이브러리들이 배포되어 있다.
Anyframe Gen CLI를 통해 Multi 프로젝트 구조로 프로젝트를 생성한 경우, Anyframe에서 제공하는 Anyframe 플러그인 설치 및 제거 command는 사용할 수 없다. Anyframe 플러그인 설치 및 제거 command 는 Single 프로젝트 구조일 경우에만 지원되기 때문이다.
Multi 프로젝트 구조일 때 Anyframe Gen CLI에서는 Anyframe 플러그인 설치 및 제거를 할 수 없지만, Eclipse를 통해 Anyframe Gen 을 사용하는 경우에는 Anyframe 플러그인 설치 및 제거가 가능하다. Anyframe Gen Editor의 Anyframe plugin installation 탭의 기능을 이용하는 것으로 이와 관련한 설명은 Eclipse plugin의 [Anyframe Plugin Installation] 을 참조한다.
Command Line Interface를 이용해 Domain Class를 생성해본다. 이때, 반드시 DB를 구동하여 다음 command를 수행한다. DB가 구동되지 않은 상태에서 Domain Class를 생성하는 경우 socket creation error가 발생한다. 기본적으로 DB 정보는 HSQL로 설정되나 이를 변경하고 싶은 경우 다음 [DB정보 변경] 을 참조한다.
Domain Class 생성 command를 입력한다.
gen create-model [-options]
ex) gen create-model -table "*" -basepackage com.sds.emp.domain
위 예제는 모든 테이블에 대해 Domain Class를 어플리케이션 생성 시 지정한 대표 패키지(ex. com.sds.emp) 하위의 domain 패키지 내에 생성하는 command로 아래와 같은 option 정보를 이용하여 Domain Class 생성 대상 및 패키지 정보를 변경할 수 있다.
표 6.6. create-model options
| option | description | default value |
|---|---|---|
| -table |
Domain Class를 생성하려는 대상 DB 테이블을 선정한다. 테이블에 대한 option
을 따로 설정하지
않는 경우 default로 모든 DB 테이블로부터 Domain Class를 생성하고 있다.
명시적으로 모든
DB Table에 대해서 Domain Class를 생성하기 위해서는 "*" 로 옵션 값을
설정한다.
특정
테이블만 대상으로 Domain Class를 생성하고 싶은 경우 대상 DB 테이블명을 지정하면
된다. 여러
개의
테이블을 대상으로 할 때에는 "," 기호를 이용하여 작성하도록 한다.
* 이때 테이블명에 대해 대소문자를 구분하므로 유의하여 테이블명을 입력하도록 한다. ex) gen create-model -table BOARD,BOARD_MASTER -basepackage com.sds.emp.domain | "*" (모든 테이블 대상) |
| -basepackage | DB 테이블로부터 Domain Class를 생성 시 어느 소스 코드 패키지 하위에 생성시킬 지 결정하는 옵션으로, default로 어플리케이션 생성 시 설정한 대표패키지 + ".domain" 패키지 경로가 Domain Class 패키지 경로가 된다. | 어플리케이션 생성 시 지정한 대표 패키지.domain |
Domain Class 가 정상적으로 생성되었는지 확인한다.
Domain Class 생성 시 지정한 -basepackage 값에 해당하는 패키지에 -table 값에 해당하는 Domain Class가 있으면 정상이다. 아래는 생성된 Board.java 코드의 일부분이다.
@Entity
@Table(name = "BOARD", schema = "PUBLIC")
public class Board implements Serializable {
private BoardId id;
private BoardMaster boardMaster;
private String boardName;
중략...
public BoardId getId() {
return this.id;
}
public void setId(BoardId id) {
this.id = id;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "BOARD_MASTER_ID", nullable = false, insertable = false,
updatable = false)
public BoardMaster getBoardMaster() {
return this.boardMaster;
}
public void setBoardMaster(BoardMaster boardMaster) {
this.boardMaster = boardMaster;
}
@Column(name = "BOARD_NAME", nullable = false, length = 150)
public String getBoardName() {
return this.boardName;
}
public void setBoardName(String boardName) {
this.boardName = boardName;
}
}위에서 생성한 Domain Class를 기반으로 CRUD 소스 코드를 생성할 수 있다. 이때 Business Layer와 Presentation Layer 별로 구분하여 소스 코드를 생성할 수도 있고 함께 생성해낼 수도 있다. 각각의 경우로 나누어서 아래에 설명하고 있다. 아래 예제는 default 템플릿 타입으로 설정되어 있는 경우에 해당하며, 이 때 생성된 CRUD 소스코드는 annotation 기반으로 되어 있다.
Business Layer 코드 생성 command를 입력한다.
gen create-crud ENTITY [-options]
ex) gen create-crud Board -project sample -package board -scope service
위 예제는 Board Domain class를 기반으로 CRUD 소스 코드 생성 시 어플리케이션 대표 패키지(ex. com.sds.emp) + ".board" 패키지 하위에 business layer 코드를 생성시키는 command로 아래와 같은 option 정보를 이용하여 CRUD 소스 코드 생성 시 필요한 타켓 프로젝트와 패키지 경로 위치 그리고 생성 범위 등을 변경할 수 있다.
표 6.7. create-crud options
| option | description | default value |
|---|---|---|
| -project | CRUD 소스 코드 생성 후, 생성된 결과 코드를 위치시킬 프로젝트 명을 입력한다. single 프로젝트 구조에서는 하나의 프로젝트를 사용하므로 타켓 프로젝트 위치가 자동 지정되어 이 옵션을 사용할 필요가 없다. multi 프로젝트 구조에서는 생성된 business layer 코드를 위치시킬 service 타입 프로젝트 명을 설정한다. 지정하지 않은 경우 최초로 생성된 service 타입 프로젝트 명이 자동으로 설정된다. presentation layer 코드 생성 시에는 결과 코드를 위치시킬 web 타입 프로젝트가 하나만 존재하여 자동 지정되므로 사용할 필요가 없다. | application-build.properties 파일의 service.project.name 속성에 정의된 프로젝트 명 |
| -package | CRUD 소스 코드가 생성될 패키지명을 정하는 옵션으로, 어플리케이션 생성 시 지정한 대표 패키지 뒤에 붙게 된다. | Domain Class명(소문자)형태 |
| -scope | 생성할 코드가 business layer일 경우 service로 설정하고, presentation layer일 경우 web으로 설정한다. 두 layer에 대한 소스 코드 모두를 함께 생성할 경우 all로 설정한다. | all |
Business Layer 코드가 정상적으로 생성되었는지 확인한다. Multi Project Structure 에서는 Business Layer코드는 Service 타입 프로젝트에 생성된다.
서비스인터페이스, 서비스구현클래스, DAO인터페이스, DAO구현클래스와 매핑쿼리문등이 생성된다.
아래는 생성된 자바코드와 속성파일, 매핑쿼리문의 일부분이다. 서비스인터페이스, 서비스구현클래스, DAO인터페이스, DAO구현클래스는 Generic Service를 상속받아 구현되었으므로, 자세한 내용은 Generic Service를 참조한다.
서비스인터페이스 (src/main/java/[대표패키지]/[-package 값]/service/[Entity 클래스명]Service.java)
public interface BoardService extends GenericService<Board, BoardId> {
Page getPagingList(SearchVO searchVO) throws Exception;
}서비스구현클래스 (src/main/java/[대표패키지]/[-package 값]/service/impl/[Entity 클래스명]ServiceImpl.java)
@Service("boardService")
@Transactional(rollbackFor = {Exception.class}, propagation = Propagation.REQUIRED)
public class BoardServiceImpl extends GenericServiceImpl<Board, BoardId>
implements BoardService {
@Resource
private BoardDao boardDao;
@PostConstruct
public void initialize(){
super.setGenericDao(boardDao);
}
/** {@inheritDoc} */
public Page getPagingList(SearchVO searchVO) throws Exception {
return super.getGenericDao().getPagingList(searchVO);
}
}DAO인터페이스 (src/main/java/[대표패키지]/[-package 값]/dao/[Entity 클래스명]Dao.java)
public interface BoardDao extends GenericDao<Board, BoardId> {
Page getPagingList(SearchVO searchVO) throws Exception;
}DAO구현클래스 (src/main/java/[대표패키지]/[-package 값]/dao/impl/[Entity 클래스명]Dao[DAO Framework 명]Impl.java)
@Repository("boardDao")
public class BoardDaoQueryImpl extends GenericDaoQuery<Board, BoardId>
implements BoardDao {
@Resource
IQueryService queryService;
@Resource
IPropertiesService propertiesService;
public BoardDaoQueryImpl() {
super(Board.class);
}
@PostConstruct
public void initialize(){
super.setQueryService(queryService);
super.setPropertiesService(propertiesService);
}
/** {@inheritDoc} */
public Page getPagingList(SearchVO searchVO) throws Exception {
int pageIndex = searchVO.getPageIndex();
int pageSize = super.getPropertiesService().getInt("PAGE_SIZE");
int pageUnit = super.getPropertiesService().getInt("PAGE_UNIT");
중략...
return super.findListWithPaging(ClassUtils.getShortName(getPersistentClass()),
args, pageIndex, pageSize, pageUnit);
}
}매핑쿼리문 (src/main/resources/query/mapping-query-[Entity 클래스명].xml)
<queryservice>
<queries>
<query id="createBoard">
<statement>
INSERT INTO BOARD (BOARD_ID, BOARD_DESC, BOARD_MASTER_ID, BOARD_NAME,
BOARD_ORDER, BOARD_TOPICS, REG_DATE)
VALUES (:vo.id.boardId, :vo.boardDesc, :vo.id.boardMasterId, :vo.boardName,
:vo.boardOrder, :vo.boardTopics, :vo.regDate)
</statement>
</query>
중략...
</queries>
</queryservice>MessageSoruce (src/main/resources/message/message-generation.properties)
# -- Board-START board.id.boardId=Board Id board.id.boardMasterId=Board Master Id board.boardDesc=Board Desc board.boardName=Board Name board.boardOrder=Board Order board.boardTopics=Board Topics board.regDate=Reg Date # -- success messages -- success.board.create=Board has been added successfully. success.board.update=Board has been updated successfully. success.board.delete=Board has been deleted successfully. # -- error messages -- error.boardserviceimpl.create=Board data not created error.boardserviceimpl.create.solution=Enter correct data for mandatory field or enter data according to formats means date format as yyyy-mm-dd error.boardserviceimpl.create.reason=Entered incorrect data for Board 중략...
통합테스트케이스 (src/test/java/[대표패키지]/[-package 값]/dao/[Entity 클래스명]DaoTest.java)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:/spring/context-*.xml" })
public class BoardDaoTest{
@Resource(name="boardDao")
private BoardDao boardDao;
@Test
public void testAddAndRemoveBoard() throws Exception {
Board board = new Board();
BoardId id = new BoardId();
id.setBoardId(new Integer(1732013925));
id.setBoardMasterId(new Integer(1681092908));
board.setId(id);
중략...
}
}단위테스트 케이스 (src/test/java/[대표패키지]/[-package 값]/service/impl/[Entity 클래스명]ServiceImplTest.java)
@RunWith(JMock.class)
public class BoardServiceImplTest{
private BoardServiceImpl service = null;
private BoardDao dao = null;
private Mockery context = new JUnit4Mockery();
@Before
public void setUp() {
System.setProperty("log4j.configuration", "log4j-test.xml");
this.dao = context.mock(BoardDao.class);
this.service = new BoardServiceImpl();
ObjectUtil.setField(this.service, "boardDao", this.dao);
this.service.initialize();
}
@After
public void tearDown() {
service = null;
}
@Test
public void testGetBoard() throws Exception {
log.debug("testing get...");
final BoardId id = new BoardId();
id.setBoardId(257077485);
id.setBoardMasterId(555604496);
final Board board = new Board();
// set expected behavior on dao
context.checking(new Expectations() {{
one(dao).get(with(equal(id)));
will(returnValue(board));
}});
Board result = service.get(id);
assertSame(board, result);
}
중략...현재 Multi 프로젝트 구조에서 Query Service와 Hibernate/JPA를 DAO Framework으로 사용하는 경우, HibernateTransactionManager를 공통으로 사용할 수 있다. (Query Service만 사용하는 경우 DataSourceTransactionManager를 사용할 수도 있다.) 단, Multi 프로젝트 중 공통(common) 타입 프로젝트에 설정된 HibernateTransactionManager에서 dataSource property에 대한 설정을 반드시 해줘야 한다. 아래 예시를 참고하도록 한다. Single 프로젝트 구조에서는 HibernateTransactionManager bean에 dataSource property 설정을 해주지 않아도 된다.
<bean id="hibernateTxManager" class="org.springframework.orm.hibernate3.
HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
<property name="dataSource" ref="dataSource" />
</bean>
중략...Presentation Layer 코드 생성 command를 입력한다.
gen create-crud ENTITY [-options]
ex) gen create-crud Board -project sample -package board -scope web
위 예제는 Board Domain class를 기반으로 CRUD 소스 코드 생성 시 어플리케이션 대표 패키지(ex. com.sds.emp) + ".board" 패키지 하위에 presentation layer 코드를 생성시키는 command이다.
표 6.8. create-crud options
| option | description | default value |
|---|---|---|
| -project | CRUD 소스 코드 생성 후, 생성된 결과 코드를 위치시킬 프로젝트 명을 입력한다. presentation layer 코드 생성 시에는 결과 코드를 위치시킬 web 타입 프로젝트가 하나만 존재하여 자동 지정되므로 사용할 필요가 없다. | application-build.properties 파일의 service.project.name 속성에 정의된 프로젝트 명 |
| -package | CRUD 소스 코드가 생성될 패키지명을 정하는 옵션으로, 어플리케이션 생성 시 지정한 대표 패키지 뒤에 붙게 된다. | Domain Class명(소문자)형태 |
| -scope | 생성할 코드가 business layer일 경우 service로 설정하고, presentation layer일 경우 web으로 설정한다. 두 layer에 대한 소스 코드 모두를 함께 생성할 경우 all로 설정한다. | all |
Presentation Layer 코드가 정상적으로 생성되었는지 확인한다. Multi Project Structure 에서는 Web 타입 프로젝트에 Presentation Layer 코드가 생성된다.
서비스와 통신을 하기 위한 컨트롤러 파일, UI파일(JSP 또는 MiPlatform 용 XML파일) 등이 생성된다.
컨트롤러 (src/main/java/[대표패키지]/[-package 값]/web/[Entity 클래스명]Controller.java)
@Controller
@RequestMapping("/board.do")
public class BoardController {
/**
* Resource Injection on BoardService
*/
@Resource(name="boardService")
private BoardService boardService;
중략...
/**
* Display Board list.
* @param request current HTTP request
* @param searchVO form object with request parameters bound onto it
* @param model model containing control data
* @return the prepared Board list view
* @throws Exception in case of getting Board paging list
*/
@RequestMapping(params = "method=list")
public String list(HttpServletRequest request,
@ModelAttribute("search") SearchVO searchVO, Model model) throws Exception
{
String pageParam = (new ParamEncoder("boardList").
encodeParameterName(TableTagParameters.PARAMETER_PAGE));
String pageParamValue = request.getParameter(pageParam);
int pageIndex = StringUtil.isNotEmpty(pageParamValue) ?
(Integer.parseInt(pageParamValue)) : 1;
searchVO.setPageIndex(pageIndex);
Page resultPage = boardService.getPagingList(searchVO);
model.addAttribute("boardList", resultPage.getList());
model.addAttribute("size", resultPage.getTotalCount());
model.addAttribute("pagesize", resultPage.getPagesize());
model.addAttribute("pageunit", resultPage.getPageunit());
return "generation/board/listBoard";
}
}UI JSP 파일 (src/main/webapp/WEB-INF/jsp/[프로젝트명]/*.jsp)
<%@ include file="/sample/common/taglibs.jsp"%>
<html>
<head>
<%@ include file="/sample/common/meta.jsp" %>
<title><fmt:message key="boardList.title"/></title>
<meta name="heading" content="<fmt:message key='boardList.heading'/>"/>
<link rel="stylesheet" type="text/css" media="all"
href="<c:url value='/sample/css/displaytag.css'/>" />
<link rel="stylesheet" href="<c:url value='/sample/css/admin.css'/>"
type="text/css">
<script type="text/javascript"
src="<c:url value='/sample/javascript/prototype.js'/>"></script>
<script type="text/javascript"
src="<c:url value='/sample/javascript/global.js'/>"></script>
<script type="text/javascript"
src="<c:url value='/sample/javascript/CommonScript.js'/>"></script>
<script language="JavaScript">
function fncAddBoardView() {
document.location.href="<c:url value='/board.do?method=addView'/>";
}
function fncSearchBoard(arg) {
var conditions = ["boardId","boardMasterId","boardTopics"]
중략...단위테스트케이스 (src/test/java/[대표패키지]/[-package 값]/web/[Entity 클래스명]ControllerTest.java)
@RunWith(JMock.class)
public class BoardControllerTest {
private BoardController controller;
private String SUCCESS_ADDVIEW = "generation/board/viewBoard";
private String SUCCESS_ADD = "redirect:/board.do?method=list";
private String SUCCESS_GET = "generation/board/viewBoard";
private String SUCCESS_UPDATE = "forward:/board.do?method=list";
private String SUCCESS_LIST = "generation/board/listBoard";
private String SUCCESS_DELETE = "redirect:/board.do?method=list";
private Mockery context = new JUnit4Mockery();
private BoardService mockService = null;
@Before
public void setUp() throws Exception {
System.setProperty("log4j.configuration", "log4j-test.xml");
this.mockService = context.mock(BoardService.class);
this.controller = new BoardController();
this.controller.setBoardService(this.mockService);
}
public void setBoardController(BoardController controller) {
this.controller = controller;
}
@Test
public void testAddView() throws Exception{
String viewName = this.controller.addView(new ExtendedModelMap());
assertEquals("returned correct view name", SUCCESS_ADDVIEW, viewName);
}
중략...현재 Presentation Layer 코드를 생성하면 Spring MVC + JSP UI Page(default template 선택 시) 혹은 Spring MVC + MiPlatform UI(miplatform template 선택 시)에 해당하는 소스 코드가 생성된다.
이중 default template의 경우 목록 조회 화면과 상세 조회 화면을 일반 JSP 페이지로 생성해내지만, 목록 조회 화면의 경우 Display Tag Library를 이용하여 페이징 처리, Sorting 등의 공통 기능을 제공해주고 있다. Display Tag Library에 대한 자세한 사용법은 Display Tag Library 사이트 를 참고하도록 한다.
아래는 Display Tag를 사용한 JSP 페이지 예제이다.
<display:table name="usersList" class="table" requestURI="users.do"
id="usersList" export="true" partialList="true" size="size"
pagesize="${pagesize}" style="margin-top:10px;">
<display:column property="userId" sortable="true"
href="users.do?method=get"
media="html" paramId="userId" paramProperty="userId"
titleKey="users.userId"/>
<display:column property="password" sortable="true"
titleKey="users.password" maxLength="20" />
<display:column property="userName" sortable="true"
titleKey="users.userName" maxLength="20" />
<display:setProperty name="export.excel.filename">
<fmt:message key="usersList.title"/>.xls
</display:setProperty>
<display:setProperty name="export.pdf.filename">
<fmt:message key="usersList.title"/>.pdf
</display:setProperty>
</display:table>Business Layer와 Presentation Layer 코드 생성 command를 입력한다.
gen create-crud ENTITY [-options]
ex) gen create-crud Board -project sample -package board -scope all
위 예제는 Board Domain class를 기반으로 CRUD 소스 코드 생성 시 어플리케이션 대표 패키지(ex. com.sds.emp) + ".board" 패키지 하위에 business layer 코드와 presentation layer 코드를 함께 생성시키는 command이다.
표 6.9. create-crud options
| option | description | default value |
|---|---|---|
| -project | CRUD 소스 코드 생성 후, 생성된 결과 코드를 위치시킬 프로젝트 명을 입력한다. single 프로젝트 구조에서는 하나의 프로젝트를 사용하므로 타켓 프로젝트 위치가 자동 지정되어 이 옵션을 사용할 필요가 없다. multi 프로젝트 구조에서는 생성된 business layer 코드를 위치시킬 service 타입 프로젝트 명을 설정한다. 지정하지 않은 경우 최초로 생성된 service 타입 프로젝트 명이 자동으로 설정된다. presentation layer 코드 생성 시에는 결과 코드를 위치시킬 web 타입 프로젝트가 하나만 존재하여 자동 지정되므로 사용할 필요가 없다. | application-build.properties 파일의 service.project.name 속성에 정의된 프로젝트 명 |
| -package | CRUD 소스 코드가 생성될 패키지명을 정하는 옵션으로, 어플리케이션 생성 시 지정한 대표 패키지 뒤에 붙게 된다. | Domain Class명(소문자)형태 |
| -scope | 생성할 코드가 business layer일 경우 service로 설정하고, presentation layer일 경우 web으로 설정한다. 두 layer에 대한 소스 코드 모두를 함께 생성할 경우 all로 설정한다. | all |
Business Layer, Presentation Layer 코드가 정상적으로 생성되었는지 확인한다. dao,service,web 폴더가 존재하여야 하며, 각각 business layer, presentation layer 생성 시 결과 화면을 참조하여 확인해보도록 한다.
Command Line Interface를 이용하여 application-build.properties 파일에 변경한 DB 설정 정보를 프로젝트 내 관련 파일들에 모두 반영되도록 한다. default로 HSQL DB를 사용하는 sampledb를 제공하고 있다. 해당 프로젝트에서 HSQL DB가 아닌 다른 DB를 사용하는 경우 application-build.properties 파일을 수정해준 뒤, DB 정보 변경 command를 실행시켜준다.
application-build.properties파일(생성한 어플리케이션 폴더 하위에 위치)을 열어 DB 설정 정보를 수정한다.
표 6.10. application-build.properties I (DB 정보)
| property name | description | required | default value |
|---|---|---|---|
| db_type | DB 정보(HSQL, Oracle, MySQL, Sybase 등) | Y | HSQL |
| db_name | Database 명 | Y | sampledb |
| schema | schema 명 | N | PUBLIC |
| username | DB 사용자 명 | Y | sa |
| password | DB 사용자 패스워드 | N | |
| server | DB에 접근하기 위한 server 정보(ex.70.7.105.123) | Y | localhost |
| port | DB에 접근하기 위한 port 번호 | Y | -1 |
| driver_class |
DB의 드라이버 클래스를 설정한다. Default Value로는 HSQL의 드라이버 클래스 값이며, DB에 맞는
값을 찾아 설정하면
된다.
ex. Oracle: oracle.jdbc.driver.OracleDriver ex. MySQL: com.mysql.jdbc.Driver ex. Sybase: com.sybase.jdbc3.jdbc.SybDataSource | Y | org. hsqldb. jdbcDriver |
| driver_jar _path |
DB에 접근하기 위한 driver jar 파일 경로를 설정한다. Default Value로는 HSQL의
driver jar파일 경로 값이며, DB에 맞는 driver
jar 파일을 찾아 경로를 설정하면 된다.
ex. Oracle: ojdbc-XX.jar ex. MySQL: mysql-connector-java-X.X.XX-bin.jar ex. Sybase: jconnX.jar | Y | [Gen Home]/repo/hsqldb/hsqldb/ 1.8.0.10/ hsqldb- 1.8.0.10.jar |
| url | DB에 접근하기 위한 Access URL | Y | jdbc:hsqldb :hsql: //localhost /sampledb |
표 6.11. application-build.properties II (DB 관련 정보)
| property name | description | required | default value |
|---|---|---|---|
| dialect |
DB별 Hibernate Dialect 클래스를 설정한다. Default Value로는 HSQL의
dialect값이며, DB에 맞는 값을 찾아 설정하면 된다.
ex. Oracle: org.hibernate.dialect.OracleDialect (10g의 경우 org.hibernatedialect.Oracle10gDialect) ex. MySQL: org.hibernate.dialect.MySQLDialect ex. Sybase: org.hibernate.dialect.SybaseDialect | Y | org.hibernate.dialect. HSQLDialect |
| paging _generator |
[Query Service에서 사용] 목록 조회 시 페이징 처리를 지원하기 위한 SQL 생성 클래스명을 설정한다.
Default Value로는 HSQL의 paging generator 값이며, DB에 맞는 값을
설정하면 된다.
MySQL과 Sybase는 현재 지원되지 않는다.
ex. Oracle: anyframe.core.query.impl.jdbc. generator.OraclePagingSQLGenerator | N | anyframe.core.query. impl.jdbc.generator. HSQLPaging SQLGenerator |
| lobhandler |
[Query Service에서 사용] BLOB,CLOB과 같은 Large Data Type을 핸들링하는
클래스명을
설정한다. Default Value로는 HSQL의lobhandler 값이며, HSQL은 lob type을
지원하지 않으므로
공란으로 비워둔다. 각 DB에 맞는lobhandler 값을 찾아 설정한다.
ex. Oracle: org.springframework.jdbc.support. lob.OracleLobHandler ex. MySQL: org.springframework.jdbc.support. lob.DefaultLobHandler ex. Sybase: org.springframework.jdbc.support. lob.DefaultLobHandler | N | N/A |
DB 변경 command를 입력한다. application-build.properties 파일의 DB 정보를 참조로 하여 DB 설정 내용을 반영한다.
gen change-db
DB 정보가 정상적으로 변경되었는지 확인한다.
프로젝트 코드 내 DataSource Service 설정 정보 및 Hibernate, Query Service 관련 정보들이 변경되었는지 확인한다. (ex. src/main/resources/spring/context-datasource.xml)
현재 Anyframe Gen에서는 5개의 DB를 지원하고 있다.(HSQL, Oracle, MySQL, Sybase, DB2) 프로젝트에서 작업하려는 DB가 이 5가지 중 하나라면 [Gen Home]/db/jdbc.config 파일을 열어서 사용하려는 DB 정보가 등록되었는지 확인한다.
<list>
<jdbcType>
<type>Oracle</type>
<driver>oracle.jdbc.driver.OracleDriver</driver>
<dialect>
<string>org.hibernate.dialect.OracleDialect</string>
<string>org.hibernate.dialect.Oracle10gDialect</string>
</dialect>
<port>1521</port>
<pagingGenerator>anyframe.core.query.impl.jdbc.generator.
OraclePagingSQLGenerator</pagingGenerator>
<lobHandler>org.springframework.jdbc.support.lob.OracleLobHandler
</lobHandler>
</jdbcType>
중략...만약 이외의 다른 DB를 사용하려면 Anyframe 이슈 관리 시스템 에 등록해주시기 바랍니다.
Command Line Interface를 이용해 생성된 어플리케이션에 대해서는 빌드 및 컴파일을, 생성된 프로젝트에 대해서는 빌드를 할 수 있다. 빌드 단계에서는 소스 코드 컴파일, 테스트 케이스 수행, 패키징, 코드 품질 검사, 배포 파일 생성 등 빌드 프로세스를 수행하는데 어플리케이션 빌드와 프로젝트 빌드 두 가지 형태로 크게 구분할 수 있다. 컴파일은 어플리케이션에 대해서 수행할 수 있으며, 어플리케이션 내 변경된 소스파일들을 컴파일하여 웹 어플리케이션 폴더로 배포하는 역할을 한다.
여러 개의 프로젝트로 구성되어 있을 때 (즉, multi 프로젝트 구조에서) 어플리케이션 빌드를 수행시키면 어플리케이션 내 모든 프로젝트 빌드가 함께 수행되어 어플리케이션 배포 파일을 생성해낸다. 프로젝트 빌드는 각각의 프로젝트 단위로 빌드를 수행하여 프로젝트 배포 파일을 생성해낸다.
Command Line Interface를 이용해 어플리케이션을 빌드해본다.
어플리케이션이 생성된 폴더 하위로 이동한다. (예를 들어, emarketplace 라는 어플리케이션을 생성시켰다면 emarketplace 폴더 하위에서 command를 실행시키도록 한다.)
다음의 어플리케이션 빌드 command를 입력한다.
gen build-app [-options]
어플리케이션이 생성된 폴더 하위의 repo폴더에 어플리케이션 명으로 된 배포폴더가 생성되고, 옵션에 따라 배포형태 및 war 파일 생성유무 등이 결정된다.
ex)gen build-app -deploy jar
위 예제는 jar 파일 형태로 프로젝트를 패키징하여 어플리케이션 배포 파일을 생성하는 command이다.
표 7.1. build-app options
| option | description | default value |
|---|---|---|
| -deploy |
프로젝트 배포 형태를 정의할 수 있다. "class" 혹은 "jar"를 입력한다.
[single 프로젝트 구조] - WEB-INF/classes 폴더 하위에 클래스 형태로 배포할 때 class로 설정 - WEB-INF/lib 폴더 하위에 jar 파일 형태로 배포할 때 jar로 설정 [multi 프로젝트 구조] - dynamic reloading 기능을 사용하고 있지 않은 경우에는 single 프로젝트 구조와 동일하게 배포 - dynamic reloading 기능을 사용하는 경우에는 deploy option 값에 상관없이 WEB-INF/modules 폴더 하위에 jar 파일 형태로 배포됨 | class |
| -war | true일 때 어플리케이션이 생성된 폴더 하위의 repo 폴더에 어플리케이션명.war 파일을 생성 한다. | false |
| -clean | true일 때 어플리케이션이 생성된 폴더 하위의 repo 폴더 전체를 삭제 한 후 빌드를 수행한다. | false |
어플리케이션 전체 빌드 후, WEB-INF/classes 폴더 하위에 프로젝트 소스 코드 컴파일 결과를 class 파일 형태로 배포하는 경우에 사용한다.
gen build-app -deploy class
빌드된 결과를 WEB-INF/classes 에서 확인하며,WEB-INF/classes 아래에 컴파일된 자바코드, 설정파일, 매핑쿼리문 등이 생성된다.
어플리케이션 전체 빌드 후, WEB-INF/lib 폴더 하위에 프로젝트 소스 코드 컴파일 결과를 jar 파일 형태로 배포하는 경우에 사용한다.
gen build-app -deploy jar
빌드된 결과를 WEB-INF/lib 에서 확인하며, single 프로젝트 구조에서는 하나의 프로젝트 이름(예를 들면 sample)으로 jar 파일이 생성되고, multi 프로젝트 구조에서는 생성한 각각의 타입 별 프로젝트 이름(common/service/web 타입 별)으로 jar 파일이 생성된다.
multi 프로젝트 구조의 어플리케이션에 대해서 dynamic reloading 기능을 사용하는 경우 어플리케이션 생성 시 dynamic option 값을 true로 설정하여 생성하였다면, deploy option 값과 무관하게 WEB-INF/modules 폴더 하위에 jar 파일 형태로 배포된다.
gen build-app
빌드된 결과를 WEB-INF/modules/ 폴더 하위에서 확인한다. WEB-INF/modules/ 폴더에는 각각의 타입 별 프로젝트 이름(common/service/web 타입 별)으로 jar 파일이 생성된다.
어플리케이션 전체 빌드 후, war 파일을 생성하는 경우에 사용한다.
gen build-app -war true
빌드된 결과를 어플리케이션이 생성된 폴더/repo/ 폴더 하위에서 확인한다. 어플리케이션이 생성된 폴더/repo 폴더에는 어플리케이션 명으로 된 war 파일이 생성된다.( 예)emarketplace.war)
현재 Anyframe Gen에서는 어플리케이션 빌드 관련된 빌드 스크립트를 [Gen Home]/cli/scripts/application-build.xml 파일에서 관리하고 있다. 이 빌드 파일 내에서 target명이 "build-app"인 경우가 어플리케이션 빌드에 해당된다.
<target name = "build-app" depends = "clean, dist, war"/> 중략...
만약 어플리케이션 빌드 프로세스 내용 중 일부를 변경시키고자 한다면 application-build.xml 파일 내용을 변경하도록 한다.
Command Line Interface를 이용해 어플리케이션 내 프로젝트에 대한 소스 코드를 컴파일해본다. 빌드 프로세스를 모두 수행하지 않고 컴파일 단계만 수행하는데 이때 변경된 클래스만 컴파일하여 어플리케이션 배포 폴더에 반영한다. (incremental build 지원)
어플리케이션 폴더 하위로 이동한다. (예를 들어, emarketplace 라는 어플리케이션 폴더 하위에서 command를 실행시키도록 한다.)
다음의 어플리케이션 컴파일 command를 입력한다.
gen compile-app
incremental build classes들을 웹 어플리케이션 폴더로 배포할 수 있는 명령어로써, 옵션은 없다.
수정한 파일이 있을 경우, 해당 명령을 수행했을 때 변경된 파일에 대해서만 컴파일을 수행하여 클래스 파일을 배포한다.
컴파일 된 결과를 어플리케이션이 생성된 폴더/repo/ 폴더 하위에서 확인한다. 수정한 날짜를 확인하였을 때, 수정된 파일의 컴파일된 클래스 만이 시간이 변경되어 있는 것을 확인할 수 있다.
현재 Anyframe Gen에서는 어플리케이션 컴파일 관련된 빌드 스크립트를 [Gen Home]/cli/scripts/application-build.xml 파일에서 관리하고 있다. 이 빌드 파일 내에서 target명이 "compile-app"인 경우가 어플리케이션 컴파일에 해당된다.
<target name="compile-app"> <antcall target="pjtscompile"/> </target> 중략...
만약 어플리케이션 컴파일 프로세스 내용 중 일부를 변경시키고자 한다면 application-build.xml 파일 내용을 변경하도록 한다.
Command Line Interface를 이용해 어플리케이션 내 프로젝트에 대한 빌드를 수행한다. 어플리케이션 전체에 대한 빌드가 아닌 어플리케이션 내 각각의 프로젝트 별로 빌드가 가능하다.
어플리케이션 내 빌드 대상 프로젝트 폴더 하위로 이동한다. (예를 들어, emarketplace 라는 어플리케이션 내 sample 프로젝트를 생성시켰다면 sample 폴더 하위에서 command를 실행시키도록 한다.)
ant를 실행하기 위한 build.xml, build.properties 파일이 있는지 확인한다.
다음의 프로젝트 빌드 command를 입력한다.
ant [targets]
ex) ant all
위 예제는 프로젝트에 대해서 all이라는 target을 실행시키는 ant command로 아래와 같은 target 중 하나를 선택하여 프로젝트 빌드 프로세스를 수행시킬 수 있다. target을 입력하지 않고 ant만 실행시킨 경우 default target인 "default"가 수행된다.
표 7.2. ant targets
| target | description |
|---|---|
| default | 프로젝트에 대해서 초기화, 컴파일, 패키징 그리고 배포까지의 빌드 프로세스를 수행한다. |
| all | 위에 설명한 "default" target에서 수행하는 빌드 프로세스 작업 외에 테스트 케이스 수행, 소스 코드 커버리지, CheckStyle/JDepend/FindBugs/Code Duplication 등의 코드 품질 검사 리포팅까지의 작업을 추가로 더 수행한다. |
| 그외 | "clean", "init", "resources", "compile", "test-resources", "test-compile", "package", "emma-jars", "test", "report", "deploy" 등 빌드 프로세스 작업 내역 하나 별로 하나의 ant target이 구성되어 있으므로 위에서 설명한 "default"와 "all" target 이외의 작업 별 빌드를 수행해야 할 필요가 있으면 사용하도록 한다. |
현재 Anyframe Gen에서는 프로젝트 빌드 스크립트를 [Gen Home]/cli/scripts/project-build.xml 파일에서 관리하고 있다. (project-build.properties 함께 제공) 이 빌드 파일 내 target명들 앞에 prefix로 "shared:"가 붙어있어서 실제 생성한 프로젝트 내 빌드 파일(build.xml)에서는 이 공통 프로젝트 빌드 파일(project-build.xml)의 target명을 호출하여 실제 프로젝트 빌드를 수행하게 되며, 각 프로젝트 별로 특화된 빌드 프로세스를 추가해넣을 수도 있다.
<target name="compile-app"> <antcall target="pjtscompile"/> </target> 중략...
만약 공통 프로젝트 빌드 파일을 변경하여 나머지 모든 프로젝트 내 빌드 프로세스 내용을 변경시키고자 한다면 project-build.xml 파일 내용을 변경하도록 한다.
Command Line Interface를 이용해 어플리케이션 전체 빌드를 수행하고 웹 어플리케이션까지 실행시킬 수 있다. 즉, command를 통해 프로젝트 빌드와 배포를 수행한 후 Jetty를 이용하여 웹 어플리케이션을 구동시킴으로써 어플리케이션의 기능 확인이 가능하다.
Command Line Interface를 이용해 어플리케이션을 빌드하고 웹 어플리케이션을 실행시켜본다.
어플리케이션이 생성된 폴더 하위로 이동한다. (예를 들어, emarketplace 라는 어플리케이션을 생성시켰다면 emarketplace 폴더 하위에서 command를 실행시키도록 한다.)
다음의 어플리케이션 빌드 및 웹 어플리케이션 실행 command를 입력한다.
gen run [-options]
앞에서 설명된 어플리케이션 빌드 과정을 동일하게 수행한 후 웹 어플리케이션을 구동시켜주는 역할을 담당한다.
ex) gen run
위 예제는 추가 옵션 정보 없이 해당 어플리케이션을 빌드하고 Jetty로 실행시키는 command이다.
표 8.1. build-app options
| option | description | default value |
|---|---|---|
| -deploy |
프로젝트 배포 형태를 정의할 수 있다. "class" 혹은 "jar"를 입력한다.
[single 프로젝트 구조] - WEB-INF/classes 폴더 하위에 클래스 형태로 배포할 때 class로 설정 - WEB-INF/lib 폴더 하위에 jar 파일 형태로 배포할 때 jar로 설정 [multi 프로젝트 구조] - dynamic reloading 기능을 사용하고 있지 않은 경우에는 single 프로젝트 구조와 동일하게 배포 - dynamic reloading 기능을 사용하는 경우에는 deploy option 값에 상관없이 WEB-INF/modules 폴더 하위에 jar 파일 형태로 배포됨 | class |
| -war | true일 때 어플리케이션이 생성된 폴더 하위의 repo 폴더에 어플리케이션명.war 파일을 생성 한다. | false |
| -clean | true일 때 어플리케이션이 생성된 폴더 하위의 repo 폴더 전체를 삭제 한 후 빌드를 수행한다. | false |

웹 어플리케이션 실행 결과를 웹 브라우저를 띄워서 확인하도록 한다. 요청 URL에서 Port 정보가 8090 인 것에 유의하도록 한다. (Jetty의 기본 Port 정보가 8090임)

Jetty 폴더를 확인한다.
어플리케이션의 repo 폴더 하위에 jetty-temp라는 폴더가 생성되어 Jetty가 구동되게 된다. 배포 이후에 클래스나 JAR 파일, JSP 파일 등을 반영하고 Jetty로 재확인하고 싶다면 이 폴더의 해당 위치에 배포하도록 한다.
Anyframe Gen Eclipse Plugin을 사용하여 어플리케이션과 프로젝트 생성, Domain 클래스 및 CRUD 소스 코드 생성, Configuration, JDBC Setting, Anyframe 플러그인 install/uninstall 등의 작업을 할 수 있다. 어플리케이션과 프로젝트는 Wizard를 통해서 생성하며, 그 밖의 작업은 Anyframe Gen Editor를 이용한다.
Anyframe Gen은 압축파일로 배포되며, 설치방법은 [Anyframe Gen 매뉴얼의 설치]를 참고하도록 한다.
Anyframe Gen 플러그인 설치는 Anyframe Plugin Update Site를 통해서 설치할 수 있다. 외부 인터넷 연결이 안되거나 네트웍에 문제가 있는 경우 아래의 노트 [Update Site를 이용하지 않고 Anyframe Gen Eclipse Plugin 설치하기] 내용을 참고하여 설치하도록 한다.
Eclipse의 Help > Install New Software... 메뉴를 선택한다.
[Available Software] 화면: 우측 상단의 Add...버튼을 클릭하여 Anyframe Plugin Update Site를 추가하도록 한다. 이때 Name에는 Anyframe Plugin Update Site를, Location에는 http://dev.anyframejava.org/update를 입력한다.
[Available Software] 화면: 중앙에 Anyframe Plugin Update Site 를 루트로 하는 Plugin Tree가 나타난다. (Anyframe Common, Anyframe Gen, Anyframe Oden, Anyframe Query Manager 목록 조회됨) 여기서 하단 항목 중 "Contact all update sites during install to find required software" 체크 박스를 해제하여 다른 Plugin이 함께 설치되는 것을 방지한다.
[Available Software] 화면: Plugin Tree 중 Anyframe Gen을 선택하고 하단의 Next 버튼을 클릭한다.
[Install Details] 화면: Anyframe Gen하위로 Anyframe Common plugin이 보이게 된다. Anyframe Gen 사용 시 Anyframe Common이 필요하므로 참조관계에 의해 함께 설치된다. 확인 후 Next 버튼을 클릭한다.
[Review Licenses] 화면: 좌측의 Plugin을 선택하면 우측에 License text가 나온다. Anyframe Common과 Anyframe Gen에 대해서 우측 하단의 "I accept the terms of the license agreements" 구문에 동의하고 Finish 버튼을 클릭한다.
[Security Warning] 화면: 팝업창에서 설치 진행 여부 물을 때 OK 버튼을 선택한다.
[Software Updates] 화면: 팝업창이 뜨고, "Would you like to restart now?" 질문에 Yes 버튼을 선택한다.
Anyframe Gen Plugin이 설치하려고 하는 Eclipse의 dropins 혹은 addins 폴더에 이미 설치되어 있다면 Update Site를 통해 설치될 Plugin과 중복되어 문제를 일으킬 수 있으므로 반드시 dropins 혹은 addins 폴더에 Anyframe Gen Plugin이 설치되어 있는지 확인하고 설치되어 있다면 제거한 후, Update Site를 통해 설치하도록 한다. Update Site를 통해 설치한 경우 물리적인 Anyframe Gen Plugin 파일은 plugins 폴더 하위에 위치하게 된다.
"Help > About Eclipse Platform (또는 About Eclipse SDK) > Plug-in Details"를 통해 정상적으로 설치되었는 지 확인한다.
☞ About Eclipse Platform (또는 About Eclipse SDK) 메뉴는 Windows용 Eclipse의 경우 Help 메뉴에서, Mac OS X용 Eclipse의 경우 Eclipse 메뉴에서 확인할 수 있다.
☞ Eclipse 루트 폴더 하위의 plugins 폴더 내로 anyframe.common.eclipse.core_xxx.jar와 anyframe.gen.eclipse.core_xxx.jar 파일이 설치되어있는지 확인해볼 수 있다.

Anyframe Gen 플러그인을 포함한 전체 Anyframe Gen의 설치가 완료되었다. Anyframe Gen의 기능을 사용하여 어플리케이션을 개발하기 이전에 반드시 [Preferences] 내용을 참고하여 환경 설정을 모두 끝마치도록 한다.
Anyframe Gen 플러그인 설치는 plugins 폴더내에 있는 2개의 플러그인 패키지 파일들(anyframe.[제품명].eclipse[.*]_x.x.x.jar)를 "[eclipse 설치 폴더]/dropins/anyframe/eclipse/plugins" 로 복사시키면 된다. plugins 폴더에는 다음 두가지 플러그인 패키지가 존재한다.
anyframe.common.eclipse.core_x.x.x.jar : Anyframe plugins의 공용 라이브러리 및 공통 메뉴 제공
anyframe.gen.eclipse.*_x.x.x.x.jar : Anyframe Gen 플러그인
☞ 현재 Anyframe Common 플러그인의 경우, Anyframe Gen 설치 파일 내에 함께 배포되어 손쉽게 설치할 수 있도록 제공하고 있다. 하지만 Anyframe Common 플러그인은 독립적으로 배포되고 사용될 수 있는 플러그인이므로 추후 Anyframe Common 플러그인 버전이 업데이트되고, 업데이트된 버전을 사용하고자 한다면 Anyframe Gen에서 배포한 구버전 Anyframe Common 플러그인을 제거하고 업데이트된 플러그인 패키지를 설치하도록 한다.
Anyframe Gen 을 이용하여 생성한 어플리케이션/프로젝트 실행을 위해 필요한 환경설정을 한다. Anyframe Gen의 환경설정은 Eclipse Preferences 창을 통해 수행한다.
ClassPath 설정 : Anyframe Library 를 인식하도록 ClassPath를 설정한다.
Window >> Preferences >> Java >> Build Path >> Classpath Variables 에서 New 클릭
Name : GEN_REPO
Path : [Gen Home]\repo [Folder..]
Server 설정 : 어플리케이션이 구동될 WAS로 Tomcat v6.0을 사용한다.
Window >> Preferences >> Server >> Runtime Environments 에서 Add..클릭
Name : Apache Tomcat v6.0
Tomcat Installation directory : [Tomcat 이 설치된 root 경로]
JRE : Workbench default JRE
Ant Home 설정 : 설치된 Ant 를 인식하도록 Ant Home을 변경하거나 Ant Home Entries에 jdepend-X_X.jar파일을 추가한다.
Ant Home 변경 : Window >> Preferences >> Ant >> Runtime >> Classpath Tab >> 우측 하단의 Ant Home.. 버튼 클릭
path : [Gen Home]\ant
Ant Home Entries 파일 추가 : Window >> Preferences >> Ant >> Runtime >> Classpath Tab >> 우측 의 Add External JARs... 버튼 클릭
path : [Gen Home]\ant\lib\jdepend-2.9.jar 파일 선택
환경설정을 통해 Anyframe Gen으로 생성된 어플리케이션 및 프로젝트가 정상적으로 실행이 된다.
샘플 DB를 구동 시킨다.
현재 Anyframe Gen은 샘플 DB로 HSQL DB를 제공하고 있다. [Gen Home]\db\hsqldb 하위의 start.cmd 파일을 실행시켜서 DB를 구동한다.
탐색기로 해당경로 이동 후, start.cmd 파일을 더블클릭하면 hsqldb가 구동된다. 만약 Oracle과 같은 다른 DB를 사용한다면 DB를 구동시킨 후, [Gen Home]\db\scripts\sampledb-[DB명].sql 파일의 스크립트를 실행해준다. 현재는 Oracle(sampledb-oracle.sql), MySQL(sampledb-mysql.sql), Sybase(sampledb-sybase.sql)에 대한 샘플쿼리문이 제공되고 있으며, Anyframe Gen 에서 자동으로 설치되는 샘플이 정상적으로 동작하기 위해 필요한 것이다.
구동된 DB에 대한 JDBC 설정은 어플리케이션을 생성하면서 반영하거나, Anyframe Gen JDBC Setting 탭을 통해서 반영이 가능하다. 자세한 내용은 [New Application Creation]또는 [JDBC Setting]을 참고하도록 한다. JDBC Setting 탭은 Domian Type 프로젝트 생성 후에 사용이 가능하다.
Anyframe Gen 을 이용해 어플리케이션을 생성 할 수 있다. 개발하려고 하는 어플리케이션을 생성하고, 그 내부에 프로젝트들을 생성하여 개발해나가는 구조를 제공하고 있다. 이때 어플리케이션과 프로젝트를 함께 생성할 수도 있고, 어플리케이션 생성 완료 후, 프로젝트들을 하나씩 생성할 수도 있다. 어플리케이션만 생성하고 완료해야 하는 경우는 보통 어플리케이션 설정 파일을 변경해야 하는 경우에 발생한다.
어플리케이션이 생성되면 주어진 어플리케이션 명에 따라 폴더가 하나 생성되고 그 하위에는 1개의 Properties 파일이 제공된다. Properties 파일에는 어플리케이션 내에 위치할 프로젝트들이 공통적으로 사용할 설정 값이 저장되어 있으며, 변경가능하다.
어플리케이션 생성 시 프로젝트 생성 여부 옵션 선택에 따라 아래의 두 가지 경우가 있다.
[Create an application & projects] : 어플리케이션과 프로젝트가 함께 생성된다.
[Create an application Only] : 어플리케이션만 생성된다.
[어플리케이션 및 프로젝트 생성 시 발생할 수 있는 에러 해결 Tip]
[Out of memory] : 어플리케이션 혹은 프로젝트 생성 시 java.lang.OutOfMemoryError 조치방법
[Project Clean & JSP Validation
Error ]: 어플리케이션 혹은 프로젝트 생성 시
표시가 뜰 경우 조치방법
File >> New >> Other.. >> Anyframe >> Application 을 선택
열린 창에서 어플리케이션 생성을 위해 다음과 같은 내용을 입력한다. 아래 항목을 문제없이 기입하는 경우 Next 버튼과 Finish 버튼이 활성화 되며, Next 버튼을 클릭하면 DB정보를 구성할 수 있는 화면으로 연결된다. Generate an Application only 체크박스가 체크되지 않은 채로 Finish 버튼을 클릭하면 어플리케이션과 프로젝트가 함께 생성된다.
Application Name: 어플리케이션 이름으로, 예제의 경우 emarketplace로 설정하였다.
Gen Home: Anyframe Gen을 설치하기 위해 설치 시 선택했던 경로
Base Location: 개발대상 어플리케이션 생성 위치로, default로 지정되는 경로를 꼭 사용할 필요 없이 원하는 경로로 변경 가능하다.
Package Name: 패키지 이름으로, 예제의 경우 com.sds.emp로 지정하였다.
Single Project Structure: 하나의 프로젝트로 구성하고 싶을 경우 선택
Multi Projects Structure: Common, Service, Web 타입 등 여러 타입의 프로젝트로 나누어 구성하고 싶을 경우 선택
Generate an Application only: 어플리케이션 만 생성하고 싶은 경우에 체크하면 어플리케이션 만 생성되고 종료된다. 체크하지 않으면 프로젝트를 생성할 수 있는 화면이 제공된다.

DB정보를 구성하기 위해 위 화면에서 Next 버튼을 클릭하였다면 다음과 같은 JDBC Configuration 화면이 제공된다 Next 버튼은 위의 어플리케이션 생성화면의 Generate an Application only 체크박스를 선택하지 않은 경우에 활성화 되며, Next 버튼을 클릭하여 이동하면 프로젝트 생성화면이 제공된다.
Finish 버튼은 Generate an Application only 체크박스 체크여부에 따라 어플리케이션 또는 어플리케이션과 프로젝트가 생성된다.
Database Type: Database 타입으로, HSQL, Oracle, MySQL, Sybase를 제공하고 있다.
Database Name: Database 의 이름
Schema: 스키마의 이름
User Name: DB 유저 이름
Password: 패스워드
Server: DB가 설치된 서버 ip 정보, 로컬에서 사용하는 경우 localhost
Port: HSQL의 경우 -1, Oracle의 경우 1521, MySQL의 경우 3306, Sybase는 3000
Hibernate Dialect: Hibernate에서 쿼리 수행 시, DBMS에 최적화된 기능을 제공하기 위해 사용되는 것이 SQL Dialect 이며, 이 Dialect 프로퍼티를 사용하여 해당 DB 별 Dialect 정보를 설정할 수 있다. 각 DB 별 Dialect 클래스가 따로 존재하여 HSQL DB를 선택한 경우, 디폴트로 org.hibernate.dialect.HSQLDialect값이 선택된다.(Oracle, MySQL, Sybase Dialect 도 제공함)
Driver Class Name: DB의 드라이버 클래스를 설정해 주기 위한 값으로, HSQL의 경우 org.hsqldb.jdbcDriver 값으로 설정된다. Database Type 선택 시 해당 DB에 맞는 값이 셋팅된다.
Driver Jar Path : Anyframe Gen 설치 시 샘플 DB를 위한 HSQL DB Driver Jar 파일이 제공되므로 디폴트로 설정된다. 만약 다른 DB를 사용한다면 해당 DB의 Driver jar 파일로 연결시켜준다.

어플리케이션 생성시 프로젝트를 함께 생성하기 위해 Next 버튼을 클릭하여 이동하였다면 다음과 같은 Create Projects 화면이 제공된다. Project Structure 에 따라 활성화되는 항목이 다르며, Single Project를 선택한 경우 Single Project 그룹이, Multi Projects를 선택한 경우 Multi Projects 그룹의 항목이 활성화된다. 아래 사항 입력 후 활성화 된 Finish 버튼을 클릭하는 경우, 어플리케이션과 프로젝트가 함께 생성이 된다.
표 11.1. Single project
| Property Name | Description |
|---|---|
| Project Name | Single Project Structure 로 한 개의 프로젝트로 구성될 프로젝트 명을 입력한다. |
표 11.2. Multi Projects
| Property Name | Description |
|---|---|
| Common Project Name | Exception, Logging, Message Properties, 기술 공통 서비스들의 설정 XML 파일 등이 생성되는 프로젝트 명을 입력한다. |
| Service Project Name | Domain 클래스 및 비즈니스 서비스 클래스들이 생성되는 프로젝트 명을 입력한다. |
| Web Project Name | 웹 클래스 및 페이지 등이 생성되는 프로젝트 명을 입력한다. |
| Template Type | default, default-xml, map, miplatform, miplatform-xml 중 하나를 선택한다.
default, map, miplatform 템플릿은 annotation 기반으로,
"-xml" 이 붙은 default-xml, miplatform-xml은 xml 기반으로 프로젝트 및 소스코드가 생성되도록 한다.
- default, default-xml : spring/spring mvc 기반으로 Business Layer와 Presentation Layer 간의 데이터 통신을 DTO(Data Transfer Object) 객체를 이용하여 구현하며, 화면은 JSP 페이지로 구성되어 있다. - map : spring 기반으로 Business Layer와 Presentation Layer 간의 데이터 통신을 Map(java.util.Map) 객체를 이용하도록 코드를 생성해주고, DAO Framework은 QueryService만 지원가능하다. - miplatform, miplatform-xml : spring/spring mvc 기반으로 Business Layer와 Presentation Layer 간의 데이터 통신을 MiPlatform의 객체(DatasetList,VariableList)를 이용하여 구현하며, 화면은 MiPlatform을 이용한 UI로 구성되어 있다. MiPlatform은 상용프로그램으로 Anyframe Gen 에서 배포하지 않으므로, 개발 및 생성된 샘플 어플리케이션을 정상적으로 구동하기 위해서는 MiPlatform 개발 Tool인 PID(Presentation Interface Developer)가 설치되어 있어야 한다. |
| Use Dynamic Reloading | Dynamic Reloading 기능 사용여부 |

어플리케이션 및 프로젝트 생성이 완료되면 Eclipse 내에 프로젝트들이 정상적으로 생성되어 Import 되었는지 확인해본다. Single project Structure 일 경우 단일프로젝트가, Multi Project Structure 일때는 Common, Service, Web 타입 프로젝트가 Import된다.
서버를 실행하여 어플리케이션을 실행해본다.
Single Project Structure: 프로젝트를 선택한 후 마우스 우측 버튼 클릭 >> Run As >> Run On Server 메뉴를 선택하고 이때 기존에 설정되어있던 Tomcat Server(6.0 Version 사용)가 없는 경우 등록해주고 실행하도록 한다.
Single Project의 경우 서버를 start 했을 때 열리는 웹 페이지는 설치된 플러그인 목록이 보이는 화면이다. 어플리케이션 생성 이후에 Anyframe Gen Editor의 CRUD Generation 기능을 통해 생성되는 화면은 /src/main/webapp/index.jsp를 선택한 후 마우스 우측 버튼 클릭하여 Run As 함으로써 확인할 수 있다.
Multi Projects Structure: web 타입 프로젝트 명을 선택 후 마우스 우측 버튼 클릭 >> Run As >> Run On Server 메뉴를 선택하고 이때 기존에 설정되어있던 Tomcat Server(6.0 Version 사용)가 없는 경우 등록해주고 실행하도록 한다.
※ dynamic reloading 옵션을 선택하였을 경우, Tomcat 서버를 처음 실행 하였을 때 404 에러가 발생한다. dynamic reloading 옵션을 선택하지 않은 경우에는 에러가 발생하지 않는다. 이는 dynamic reloading 단위가 각각의 프로젝트 단위로 working directory 기준으로 reloading 대상 프로젝트들을 인식하기 때문이다. 그러므로 현재 디폴트로 설정되어 있는 working directory를 web 타입 프로젝트로 변경해 주도록 한다. Tomcat 서버를 두 번째 실행하기 전에 아래 변경 사항을 설정하고, 실행시키도록 한다.
☞ 변경방법 : Run >> Run Configurations.. >> Apache Tomcat >> New_configuration >> Arguments Tab >> Working directory Other 항목에서 workspace 버튼 클릭 >> web 타입 프로젝트 선택
File >> New >> Other.. >> Anyframe >> Application 을 선택
열린 창에서 어플리케이션 생성을 위해 다음과 같은 내용을 입력한다. 아래 항목을 문제없이 기입하는 경우 Next 버튼과 Finish 버튼이 활성화 되며, Next 버튼을 클릭하면 DB정보를 구성할 수 있는 화면으로 연결된다.
Generate an Application only 체크박스가 체크되지 않은 채로 Finish 버튼을 클릭하면 어플리케이션과 프로젝트가 함께 생성된다. 어플리케이션만 생성하고 종료하고 싶은 경우 체크박스를 선택한다.
Application Name: 어플리케이션 이름으로, 예제의 경우 emarketplace로 설정하였다.
Gen Home: Anyframe Gen을 설치하기 위해 설치 시 선택했던 경로
Base Location: 개발대상 어플리케이션 생성 위치로, default로 지정되는 경로를 꼭 사용할 필요 없이 원하는 경로로 변경가능하다.
Package Name: 어플리케이션의 대표 패키지 이름으로, 예제의 경우 com.sds.emp로 지정하였다.
Single Project Structure: 하나의 프로젝트로 구성하고 싶을 경우 선택
Multi Projects Structure: Common, Service, Web 타입 등 여러 타입의 프로젝트로 나누어 구성하고 싶을 경우 선택
Generate an Application only: 어플리케이션 만 생성하고 싶은 경우에 체크하면 어플리케이션 만 생성되고 종료된다. 체크하지 않으면 프로젝트를 생성할 수 있는 화면이 제공된다.

DB정보를 구성하기 위해 위 화면에서 Next 버튼을 클릭하였다면 다음과 같은 JDBC Configuration 화면이 제공된다 Next 버튼은 위의 어플리케이션 생성화면의 Generate an Application only 체크박스를 선택하지 않은 경우에 활성화 되며, Next 버튼을 클릭하여 이동하면 프로젝트 생성화면이 제공된다.
Finish 버튼은 Generate an Application only 체크박스 체크여부에 따라 어플리케이션 또는 어플리케이션과 프로젝트가 생성된다.
Database Type: Database 타입으로, HSQL, Oracle, MySQL, Sybase를 제공하고 있다.
Database Name: Database 의 이름
Schema: DB 스키마의 이름
User Name: DB 유저 이름
Password: 패스워드
Server: DB가 설치된 서버 ip 정보, 로컬에서 사용하는 경우 localhost
Port: HSQL의 경우 -1, Oracle의 경우 1521, MySQL의 경우 3306, Sybase는 3000
Hibernate Dialect: Hibernate에서 쿼리 수행 시, DBMS에 최적화된 기능을 제공하기 위해 사용되는 것이 SQL Dialect 이며, 이 Dialect 프로퍼티를 사용하여 해당 DB 별 Dialect 정보를 설정할 수 있다. 각 DB 별 Dialect 클래스가 따로 존재하여 HSQL DB를 선택한 경우, 디폴트로 org.hibernate.dialect.HSQLDialect값이 선택된다.(Oracle, MySQL, Sybase Dialect 도 제공함)
Driver Class Name: DB의 드라이버 클래스를 설정해 주기 위한 값으로, HSQL의 경우 org.hsqldb.jdbcDriver 값으로 설정된다. Database Type 선택 시 해당 DB에 맞는 값이 셋팅된다.
Driver Jar Path : Anyframe Gen 설치 시 샘플 DB를 위한 HSQL DB Driver Jar 파일이 제공되므로 디폴트로 설정된다. 만약 다른 DB를 사용한다면 해당 DB의 Driver jar 파일로 연결시켜준다.

Finish 버튼을 클릭하여 생성된 어플리케이션이 정상적으로 생성되었는지 확인해본다. 어플리케이션만 생성하였을 경우, Eclipse의 Project Explorer 혹은 Package Explorer에는 표시되는 것이 없으며, 탐색기를 통해 확인한다. 어플리케이션 생성 시 지정한 [Base Location]/[Application name] 위치의 폴더 를 탐색기로 연다. repo 폴더와 1개의 Properties 파일이 생성되어 있으면 정상이다. repo 폴더에는 프로젝트 생성 이후에 빌드를 수행했을 때 최종 패키징된 파일들이 존재하게 되는 폴더이다.(jar, war 파일들이 위치하게 되는 폴더)
어플리케이션을 생성한 후 어플리케이션 설정 파일(Properties)을 수정하여, 이후 생성되는 프로젝트들이 수정된 설정 값을 통해 생성되도록 할 수 있다. 어플리케이션을 생성하면 다음과 같이 1개의 Properties 파일이 생성된다. 아래 표에 설명된 항목별 내용을 보고 DB 설정을 비롯하여 다양한 공통 속성 값을 변경시킬 수 있다. 현재 DB 속성 정보들의 디폴트 값은 HSQL 샘플 DB에 대한 속성 값으로 설정되어 있다.
표 11.3. application-build.properties I (어플리케이션 정보)
| Property Name | Description | Required | Default Value |
|---|---|---|---|
| gen.home | Anyframe Gen을 설치한 루트 폴더 | Y | N/A |
| app.name | 어플리케이션 명 | Y | N/A |
| app.home | 어플리케이션 루트 폴더 경로 | Y | N/A |
| app.package.name | 어플리케이션 대표 패키지 명 | Y | N/A |
| dynamic | Dynamic Reloading 기능 사용 여부 | Y | false |
| project.list | 어플리케이션 내에 생성되는 프로젝트 이름 목록 | Y | N/A |
| common.project.name | Common 타입 프로젝트 명 | Y | N/A |
| domain.project.name | Domain 타입 프로젝트 명 | Y | N/A |
| service.project.name | Service 타입 프로젝트 명 | Y | N/A |
| web.project.name | Web 타입 프로젝트 명 | N | N/A |
| dao.framework | DAO Framework 선택(query, hibernate 중 택일) | Y | query |
| emma.enabled | 프로젝트 빌드 시 emma를 이용하여 코드 커버리지 리포트 결과 생성 여부 | Y | true |
| template_type | 프로젝트 및 CRUD 소스 코드 생성 시 기반이 되는 Template 형태(ex. default, miplatform 등) | Y | default |
| project.structure | 프로젝트 구조 | Y | single |
| web.context.path | jetty run 으로 실행시킬때 사용되는 WebContext Path명 | Y | 어플리케이션 명 |
표 11.4. application-build.properties Ⅱ(DB 정보)
| Property Name | Description | Required | Default Value |
|---|---|---|---|
| db_name | [DB] Database 명 | Y | sampledb |
| dialect | [DB] DB별 Hibernate Dialect 클래스 설정 | Y | org.hibernate. dialect. HSQLDialect |
| driver_class | [DB] DB의 드라이버 클래스 설정 | Y | org.hsqldb. jdbcDriver |
| schema | [DB] schema 명 | Y | PUBLIC |
| username | [DB] DB 사용자 명 | Y | sa |
| password | [DB] DB 사용자 패스워드 | N | N/A |
| url | [DB] DB에 접근하기 위한 Access URL | Y | jdbc:hsqldb:hsql://localhost/sampledb |
| lobhandler | [DB]BLOB,CLOB과 같은 Large Data 타입에 대한 핸들링 | N | N/A |
| port | [DB] DB에 접근하기 위한 port | Y | -1 |
| driver_jar_path | [DB] DB에 접근하기 위한 driver jar파일의 경로 | Y | C\:\\Gen-1.0.0\\repo\\hsqldb\\hsqldb\\1.8.0.10\\hsqldb-1.8.0.10.jar |
| server | [DB] DB에 접근하기 위한 server정보 | Y | localhost |
| db_type | [DB] DB 정보(HSQL, Oracle, MySQL, Sybase) | Y | HSQL |
| paging_generator | [DB] DB에 따른 페이징 처리 SQL Generator | N | anyframe.core. query.impl. jdbc.generator. HSQLPaging SQLGenerator |
어플리케이션 혹은 프로젝트 생성 시 다음과 같은 out of memory 에러가 발생할 경우 다음과 같이 조치한다.

실행하고 있는 eclipse가 설치되어 있는 폴더로 이동한다.
root 폴더 하위의 eclipse.ini 파일의 내용에서 launcher.XXMaxPermSize값(ex. 256M)을 높여서 재설정해준다. 필요 시 메모리 사용 최소값(-Xms)과 최대값(-Xmx)을 증가시켜서 사용하도록 한다. 다음은 Eclipse 3.5.0(Galileo) 버전의 eclipse.ini 파일 예이다.
-clean -startup plugins/org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar --launcher.library plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.0.200.v20090519 -product org.eclipse.epp.package.jee.product --launcher.XXMaxPermSize 256M -showsplash org.eclipse.platform --launcher.XXMaxPermSize 128m -vmargs -Dosgi.requiredJavaVersion=1.5 -Xms400m -Xmx512m
어플리케이션 혹은 프로젝트 생성 시 다음과 같이 생성된 프로젝트에
표시가 뜨는 경우, 프로젝트를 clean을 하거나 해당 프로젝트를 close 한 후
다시 open하면 표시가 사라진다.
☞ Project >> Clean... 수행
☞ 프로젝트 선택 후 오른쪽 마우스 클릭 >> Close Project 후 프로젝트 선택 후 오른쪽 마우스 클릭 >> Open Project
Problems 에 JSP Validation 에러가 나오는 경우, 실제로 error는 아니지만 eclipse에서 인식을 에러로 하는 것으로 다음과 같이 validation 설정을 변경해주면 된다. Eclipse 내 프로젝트에서 Validation 기능을 사용하게 되면 시간이 많이 소요될 수 있다. 반드시 필요한 경우가 아니고, 속도 향상을 위해서라면 Validation 설정을 모두 Disable All 버튼을 선택하여 사용하지 않는 것으로 설정할 수도 있다.

☞ Window >> Preferences... >> Validation >> JPA Validator, JSP Syntax Validator 의 Build 항목 체크 해제 후 Apply
Anyframe Gen을 이용해 프로젝트를 생성 할 수 있다.
프로젝트는 반드시 어플리케이션 생성 후에 생성하도록 함에 유의하도록 한다.
프로젝트를 생성하게 되면 프로젝트 구조, 샘플 소스 및 테스트 코드, 빌드 스크립트 등이 생성되어 개발 프로젝트 구성 시 매우 편리하다. 어플리케이션 생성시 선택한 프로젝트 Structure 정보에 따라, New Project Wizard 화면에서 활성화 되는 메뉴가 다르다. 프로젝트 생성은 어플리케이션의 프로젝트 구성 상태에 따라 다음 두 가지 경우로 나눠진다. Multi Projects structure로 설정되어 있을 때 하나의 어플리케이션은 Common 타입과 Web 타입의 프로젝트는 하나씩만 생성하여 사용할 수 있음에 유의하도록 한다. Service 타입 프로젝트는 여러 개를 사용할 수 있다.
[Create a single project:] 어플리케이션만 생성되어 있고 프로젝트는 아직 생성하지 않은 경우로, Single Project Structure일 경우 하나의 프로젝트를 생성할 수 있다.
[Create Multi[Common, Service, Web] projects:] 어플리케이션만 생성되어 있고 프로젝트는 아직 생성하지 않은 경우로, Multi Projects Structure 일 때는 Common, Service, Web 타입의 프로젝트를 생성할 수 있다. Common, Service, Web 타입의 프로젝트가 이미 생성된 경우에는, Service 타입의 프로젝트만 추가로 생성이 가능하다.
[Contents 포함한 프로젝트 삭제 후 프로젝트 재 생성시 조치사항 :] Contents를 포함하여 생성한 프로젝트를 삭제 한 후, 동일한 어플리케이션에서 프로젝트를 다시 생성하고 싶은 경우, application-build.properties 파일 수정이 필요하다.
File >> New >> Other.. >> Anyframe >> Project 선택 한다.
New Project Wizard 화면은 프로젝트 생성유무, 프로젝트 구조에 따라 활성화 되는 메뉴가 상이하다.(Application Location 은 항상 활성화되어 있음)
어플리케이션이 단 한번도 생성되지 않은 경우 Application Location 메뉴만 활성화된다.
어플리케이션이 생성되고 프로젝트가 생성되지 않은 경우 Project Structure 모두 활성화 되고, Single Project 일 경우, Single Project 그룹만 활성화된다.
Single Project 구조이면서 프로젝트가 생성된 경우 Application Location 메뉴만 활성화
아래 그림과 같이 Single 타입의 프로젝트를 선택하고,해당 프로젝트의 이름을 입력한다. Single Project의 경우 하나의 프로젝트로 구성되므로 프로젝트 이름만 입력하면 된다.
Project Structure: Single/Multi가 있고, 어플리케이션 생성시 정의된 정보로 조회가 된다. 단, 프로젝트가 하나도 생성되지 않았을 경우에는 Single/Multi 값을 변경할 수 있고, 프로젝트가 하나라도 생겼으면 그 후로는 조회만 가능하다.
Project Name: Single Project 일 경우 활성화 되며, 생성할 프로젝트의 이름을 입력
Application Location: 어플리케이션 생성 시 선택했던 어플리케이션 폴더 경로가 자동으로 나타나게 되므로 변경 불필요하나, 어플리케이션을 변경하여 해당 어플리케이션에 대한 프로젝트 생성은 가능하다. 어플리케이션 경로를 변경하게 되면 해당 어플리케이션 속성에 맞게 화면의 변경된다.

프로젝트가 정상적으로 생성되었는지 확인해본다.
Single Project
프로젝트가 하나로 생성되고, 싱글 프로젝트는 Anyframe Foundation 샘플 및 테스트 코드, 빌드파일 등으로 구성되어 있다. 싱글 프로젝트를 실행하면, 설치된 플러그인 목록이 보이는 웹 페이지가 조회된다.
File >> New >> Other.. >> Anyframe >> Project 선택 한다.
New Project Wizard 화면은 프로젝트 생성유무, 프로젝트 구조에 따라 활성화 되는 메뉴가 상이하다.(Application Location 은 항상 활성화되어 있음)
어플리케이션이 단 한번도 생성되지 않은 경우 Application Location 메뉴만 활성화된다.
어플리케이션이 생성되고 프로젝트가 생성되지 않은 경우 Project Structure 모두 활성화 되고, Mult Project 일 경우, Multi Project 그룹이 활성화된다. 이때, Multi Projects 의 경우 Common Project Name, Template Type, Use Dynamic Reloading 만 활성화된다. Template Type, Use Dynamic Reloading 설정은 Common Project 를 생성할때에만 설정 가능하다.
Multi Project 구조이면서 Common 프로젝트가 생성되고, Service 프로젝트가 생성되지 않은 경우 Service Project Name 만 활성화된다.
Multi Project 구조이면서 Common 프로젝트, Service 프로젝트가 생성된 경우 Service Project Name과 Web Project Name이 활성화된다.
Multi Project 구조이면서 Common 프로젝트, Service 프로젝트, Web 프로젝트가 생성된 경우 Service Project Name 만 활성화되고, Service 프로젝트는 여러개 생성이 가능하다.
아래 그림과 같이 원하는 타입의 프로젝트를 선택하고,해당 프로젝트의 이름을 입력한다. Multi Projects의 경우 Common, Service, Web 타입의 프로젝트가 생성 가능하다. Multi Projects이고, Common 타입의 프로젝트를 아직 생성하지 않았다면 Common 타입의 프로젝트를 제일 먼저 생성하도록 한다.
Project Structure: Single/Multi가 있고, 어플리케이션 생성시 정의된 정보로 조회가 된다. 단, 프로젝트가 하나도 생성되지 않았을 경우에는 Single/Multi 값을 변경할 수 있고, 프로젝트가 하나라도 생겼으면 그 후로는 조회만 가능하다.
Common Project Name: Exception, Logging, Message Properties, 기술 공통 서비스들의 설정 XML 파일 등이 생성되는 프로젝트로 하나의 어플리케이션에 하나만 생성가능
Service Project Name: Domain 클래스 및 비즈니스 서비스 클래스들이 생성되는 프로젝트로 여러 개 생성 가능
Web Project Name: 웹 클래스 및 페이지 등이 생성되는 프로젝트로 하나의 어플리케이션에 하나만 생성 가능
Template Type: default, default-xml, map, miplatform, miplatform-xml 중 하나를 선택한다. default, map, miplatform 템플릿은 annotation 기반으로, "-xml" 이 붙은 default-xml, miplatform-xml은 xml 기반으로 프로젝트 및 소스코드가 생성되도록 한다.
표 12.1. Template Type
| Template Type | Description |
|---|---|
| default, default-xml | spring/spring mvc 기반으로 Business Layer와 Presentation Layer 간의 데이터 통신을 DTO(Data Transfer Object) 객체를 이용하여 구현하며, 화면은 JSP 페이지로 구성되어 있다. |
| map | spring 기반으로 Business Layer와 Presentation Layer 간의 데이터 통신을 Map(java.util.Map) 객체를 이용하도록 코드를 생성해주고, DAO Framework은 QueryService만 지원가능하다. |
| miplatform, miplatform-xml | spring/spring mvc 기반으로 Business Layer와 Presentation Layer 간의 데이터 통신을 MiPlatform의 객체(DatasetList,VariableList)를 이용하여 구현하며, 화면은 MiPlatform을 이용한 UI로 구성되어 있다. MiPlatform은 상용프로그램으로 Anyframe Gen 에서 배포하지 않으므로, 개발 및 생성된 샘플 어플리케이션을 정상적으로 구동하기 위해서는 MiPlatform 개발 Tool인 PID(Presentation Interface Developer)가 설치되어 있어야 한다. |
Use Dynamic Reloading: Dynamic Reloading 기능 사용여부
Application Location: 어플리케이션 생성 시 선택했던 어플리케이션 폴더 경로가 자동으로 나타나게 되므로 변경 불필요하나, 어플리케이션을 변경하여 해당 어플리케이션에 대한 프로젝트 생성은 가능하다. 어플리케이션 경로를 변경하게 되면 해당 어플리케이션 속성에 맞게 화면의 변경된다.

아래와 같은 경우는 Multi Projects Structure 인 경우에만 해당하며, 아래 그림과 같이 원하는 service 프로젝트 명을 입력하고 Finish 하면 Service 타입의 프로젝트 가 생성된다. Common과 Web 프로젝트가 이미 생성된 경우 Service 프로젝트 만 선택이 가능하며, Service 프로젝트는 여러 개 추가가 가능하다.

프로젝트가 정상적으로 생성되었는지 확인해본다.
Common Project
Common 타입의 프로젝트가 생성되고, Common 타입의 프로젝트는 Logging, Exception Aspect이 적용된 소스코드 및 공통 속성파일(데이터소스,트랜잭션 등) 등으로 구성되어 있다.
Service Project
Service 타입의 프로젝트가 생성되고, Service 타입의 프로젝트가 Domain 프로젝트라면 도메인 클래스 및 User 서비스 샘플에 대한 비즈니스 레이어 소스코드, 속성파일(spring/context-*.xml) 등으로 구성되어 있다. 도메인 프로젝트가 아닌 Service 타입의 프로젝트는 샘플없이 Service 타입의 구조로 프로젝트 만 생성된다.
추가로 생성된 Service 타입 프로젝트의 경우 샘플 코드는 생성되지 않고 프로젝트 구조와 빌드 스크립트만 생성된다.
Web Project
Web 타입의 프로젝트가 생성되고, Web 타입 프로젝트는 컨트롤러, UI파일(JSP 또는 MiPlatform XML)등으로 구성되어 있다.
Eclipse에서 Contents를 포함하여 프로젝트를 삭제 한 후, 동일 어플리케이션에서 프로젝트를 다시 생성하고자 하는 경우에 어플리케이션 설정파일(application-build.properties)의 값을 수작업으로 변경하여 변경된 사항을 적용해야 한다.
application-build.properties 파일에 프로젝트명이 반영되는 프로퍼티는 다음의 5가지가 있다.
표 12.2. application-build.properties(어플리케이션 정보)
| Property Name | Value |
|---|---|
| domain.project.name | Domain 타입 프로젝트 명 |
| service.project.name | Service 타입 프로젝트 명 |
| project.list | 어플리케이션 내에 생성되는 프로젝트 이름 목록 |
| common.project.name | Common 타입 프로젝트 명 |
| web.project.name | Web 타입 프로젝트 명 |
해당 프로젝트 이름이 기입되어 있는 프로퍼티(Property)의 값(Value)을 지운 후 저장하면 Create Projects wizard 의 기능을 정상적으로 사용할 수 있다.
Anyframe Gen을 이용해 Domain Class 를 생성해본다.
DB 테이블 기반으로 Domain Class를 생성시키기 때문에 JDBC 설정이 제대로 되었는지 [JDBC Configuration 설정방법]을 참조하여 확인 한 후, Domain Class를 생성하도록 한다.
모든 프로젝트에서 Domain Class를 생성시킬 수 있는 것이 아니라 Domain 타입 프로젝트로 지정된 프로젝트에서만 Domain Class를 생성시킬 수 있다. Multi Projects Structure인 경우, Domain 타입 프로젝트는 최초 생성되는 Service 타입 프로젝트로 지정된다. 그러므로 Domain 타입 프로젝트로 지정된 Service 타입 프로젝트에서만 Anyframe Gen Editor를 통해 Domain Class를 생성시킬 수 있다.
프로젝트 (Multi Projects Structure인 경우 Service 프로젝트)를 선택한 후 우 클릭 >> Anyframe Gen 메뉴를 선택한다. 이때 해당 Service 프로젝트가 Domain 타입 프로젝트가 아닌 경우, Anyframe Gen 메뉴는 비활성화되어 보여진다.
Anyframe Gen Editor에서 Domain Generation Tab을 선택한다. Refresh 버튼을 수행하면 현재 선택 가능한 DB Table들과 소스 코드 패키지가 트리 형태로 조회된다. 이때 Domain Class로 생성하고자 하는 Table을 선택하고, Domain Class를 어느 소스 코드 패키지 하위로 생성시킬 것인지를 선택한 후 Generate 버튼을 클릭한다.
참조관계에 있는 테이블의 경우 해당 테이블을 동시에 선택하여 Domain Class를 생성 해야 하며, 이를 통해 참조관계에 관한 정보가 제공된다.
Choose Tables: JDBC 구성에 따라 연결된 DB의 테이블 목록이 조회된다.
Choose a package: 해당 프로젝트에 있는 소스 코드 패키지 경로가 조회된다.(src/main/java 소스 폴더에 한함)

Domain Class 가 제대로 생성되었는지 확인해 본다. 원하는 패키지 하위로 Domain Class들이 위치하고 있는지 확인한다.
생성된 Domain Class는 JPA Annotation 설정을 통해 DB Table, Column 정보들을 가지고 있다.
@Entity
@Table(name = "BOARD", schema = "PUBLIC")
public class Board implements Serializable {
private BoardId id;
private BoardMaster boardMaster;
private String boardName;
중략...
@EmbeddedId
@AttributeOverrides({@AttributeOverride(name = "boardId",column =
@Column(name = "BOARD_ID",nullable = false)
)
, @AttributeOverride(name = "boardMasterId",column =
@Column(name = "BOARD_MASTER_ID",nullable = false)
)
})
public BoardId getId() {
return this.id;
}
public void setId(BoardId id) {
this.id = id;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "BOARD_MASTER_ID", nullable = false,
insertable = false, updatable = false)
public BoardMaster getBoardMaster() {
return this.boardMaster;
}
public void setBoardMaster(BoardMaster boardMaster) {
this.boardMaster = boardMaster;
}
@Column(name = "BOARD_NAME", nullable = false, length = 150)
public String getBoardName() {
return this.boardName;
}
public void setBoardName(String boardName) {
this.boardName = boardName;
}
}위에서 설명한 기능 수행 도중에는 어플리케이션/프로젝트 생성, 코드 생성 및 DB 변경 등과 같은 Anyframe Gen의 기능을 동시에 수행시킬 수 없으므로 유의하도록 한다. (Background 실행을 통한 기능 수행 시)
Anyframe Gen을 이용해 CRUD를 생성해본다.
Domain Class를 중심으로 CRUD에 대한 기본 코드를 생성하고 자동으로 테스트 코드와 테스트 데이터를 생성해줌으로써 생성된 코드의 기능 확인까지 손쉽게 할 수 있다. 따라서, CRUD Generation 기능을 사용하기 전에 Domain Generation 기능을 이용하여, 연결된 DB 테이블 기반의 Domain Class를 먼저 생성하도록 한다.
Single Project Structure 일 경우에는 생성된 하나의 프로젝트에서 CRUD 코드를 생성이 가능하다. Multi Projects Structure일 경우에는 모든 프로젝트에서 Domain Class를 중심으로 CRUD 코드 생성 기능을 사용할 수 있는 것은 아니며, Domain 타입 프로젝트로 지정된 프로젝트에서만 가능하다. 왜냐하면 Domain Class들을 모두 하나의 Domain 타입 프로젝트에서 관리하고 있기 때문이다. Domain 타입 프로젝트는 최초 생성되는 Service 타입 프로젝트로 지정된다. 그러므로 Domain 타입 프로젝트로 지정된 Service 타입 프로젝트에서만 Anyframe Gen Editor를 통해 Domain Class 중심의 CRUD 코드를 생성시킬 수 있다.
프로젝트 (Multi Projects Structure인 경우 Service 타입 프로젝트를 선택)를 선택한 후 우 클릭 >> Anyframe Gen 을 선택한다.
Anyframe Gen Editor에서 CRUD Generation Tab을 선택한다. Refresh 버튼을 수행하면 현재 선택 가능한 Domain Class들과 타겟 프로젝트로 지정된 프로젝트 목록이 조회된다.
CRUD 기능을 구현하고 싶은 Domain Class를 선택하고, CRUD Project Configuration 내용을 입력한다.
CRUD Service: CRUD 기능이 구현될 서비스 명으로 Default로 이름이 지정된다.
Package: CRUD가 생성될 패키지 이름이며, 특정 서브 시스템 하위로 코드를 생성하고 싶다면 중간 패키지 정보를 함께 입력하면 된다. (ex. sub.categories)
Service Project: Service 타입의 프로젝트는 여러 개 존재할 수 있으므로 코드 생성 후 타겟 프로젝트를 무엇으로 할지 원하는 service 프로젝트를 선택하면 된다.
Web Project: 비즈니스 레이어에 해당하는 소스 뿐 아니라 프리젠테이션 레이어 소스 코드들도 함께 생성하고자 한다면 체크 박스에 체크하도록 한다.

Generate 버튼을 클릭한 후, CRUD 코드가 정상적으로 생성되었는지 확인해본다. 타겟 프로젝트로 지정한
프로젝트에는 Domain Class에 대한 비즈니스 서비스 인터페이스,구현 클래스, DAO 인터페이스, DAO 구현 클래스,
Spring 설정 파일들, 테스트 코드, 테스트 데이터 등이 생성된다. Web 타입 프로젝트에는 Spring MVC
Controller 클래스, Spring MVC 설정 파일, 테스트 코드, JSP 페이지 등이 생성된다.
참고로, CRUD 생성 후 소스파일에
표시가 뜨는 경우는, test 플러그인이 없기 때문이다. Anyframe Gen
Editor의 Installation 탭에서 test 플러그인을 다운받아 설치하면 해결된다.
서비스인터페이스 (src/main/java/[대표패키지]/[-package 값]/service/[Entity 클래스명]Service.java)
public interface BoardService extends GenericService<Board, BoardId> {
Page getPagingList(SearchVO searchVO) throws Exception;
}서비스구현클래스 (src/main/java/[대표패키지]/[-package 값]/service/impl/[Entity 클래스명]ServiceImpl.java)
@Service("boardService")
@Transactional(rollbackFor = {Exception.class}, propagation = Propagation.REQUIRED)
public class BoardServiceImpl extends GenericServiceImpl<Board, BoardId>
implements BoardService {
@Resource
private BoardDao boardDao;
@PostConstruct
public void initialize(){
super.setGenericDao(boardDao);
}
/** {@inheritDoc} */
public Page getPagingList(SearchVO searchVO) throws Exception {
return super.getGenericDao().getPagingList(searchVO);
}
}DAO인터페이스 (src/main/java/[대표패키지]/[-package 값]/dao/[Entity 클래스명]Dao.java)
public interface BoardDao extends GenericDao<Board, BoardId> {
Page getPagingList(SearchVO searchVO) throws Exception;
}DAO구현클래스 (src/main/java/[대표패키지]/[-package 값]/dao/impl/[Entity 클래스명]Dao[DAO Framework 명]Impl.java)
@Repository("boardDao")
public class BoardDaoQueryImpl extends GenericDaoQuery<Board, BoardId>
implements BoardDao {
@Resource
IQueryService queryService;
@Resource
IPropertiesService propertiesService;
public BoardDaoQueryImpl() {
super(Board.class);
}
@PostConstruct
public void initialize(){
super.setQueryService(queryService);
super.setPropertiesService(propertiesService);
}
/** {@inheritDoc} */
public Page getPagingList(SearchVO searchVO) throws Exception {
int pageIndex = searchVO.getPageIndex();
int pageSize = super.getPropertiesService().getInt("PAGE_SIZE");
int pageUnit = super.getPropertiesService().getInt("PAGE_UNIT");
중략...
return super.findListWithPaging(ClassUtils.getShortName(getPersistentClass()),
args, pageIndex, pageSize, pageUnit);
}
}매핑쿼리문 (src/main/resources/query/mapping-query-[Entity 클래스명].xml)
<queryservice>
<queries>
<query id="createBoard">
<statement>
INSERT INTO BOARD (BOARD_ID, BOARD_DESC, BOARD_MASTER_ID, BOARD_NAME,
BOARD_ORDER, BOARD_TOPICS, REG_DATE)
VALUES (:vo.id.boardId, :vo.boardDesc, :vo.id.boardMasterId, :vo.boardName,
:vo.boardOrder, :vo.boardTopics, :vo.regDate)
</statement>
</query>
중략...
</queries>
</queryservice>MessageSoruce (src/main/resources/message/message-generation.properties)
# -- Board-START board.id.boardId=Board Id board.id.boardMasterId=Board Master Id board.boardDesc=Board Desc board.boardName=Board Name board.boardOrder=Board Order board.boardTopics=Board Topics board.regDate=Reg Date # -- success messages -- success.board.create=Board has been added successfully. success.board.update=Board has been updated successfully. success.board.delete=Board has been deleted successfully. # -- error messages -- error.boardserviceimpl.create=Board data not created error.boardserviceimpl.create.solution=Enter correct data for mandatory field or enter data according to formats means date format as yyyy-mm-dd error.boardserviceimpl.create.reason=Entered incorrect data for Board 중략...
통합테스트케이스 (src/test/java/[대표패키지]/[-package 값]/dao/[Entity 클래스명]DaoTest.java)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:/spring/context-*.xml" })
public class BoardDaoTest{
@Resource(name="boardDao")
private BoardDao boardDao;
@Test
public void testAddAndRemoveBoard() throws Exception {
Board board = new Board();
BoardId id = new BoardId();
id.setBoardId(new Integer(1732013925));
id.setBoardMasterId(new Integer(1681092908));
board.setId(id);
중략...
}
}단위테스트 케이스 (src/test/java/[대표패키지]/[-package 값]/service/impl/[Entity 클래스명]ServiceImplTest.java)
@RunWith(JMock.class)
public class BoardServiceImplTest{
private BoardServiceImpl service = null;
private BoardDao dao = null;
private Mockery context = new JUnit4Mockery();
@Before
public void setUp() {
System.setProperty("log4j.configuration", "log4j-test.xml");
this.dao = context.mock(BoardDao.class);
this.service = new BoardServiceImpl();
ObjectUtil.setField(this.service, "boardDao", this.dao);
this.service.initialize();
}
@After
public void tearDown() {
service = null;
}
@Test
public void testGetBoard() throws Exception {
log.debug("testing get...");
final BoardId id = new BoardId();
id.setBoardId(257077485);
id.setBoardMasterId(555604496);
final Board board = new Board();
// set expected behavior on dao
context.checking(new Expectations() {{
one(dao).get(with(equal(id)));
will(returnValue(board));
}});
Board result = service.get(id);
assertSame(board, result);
}
중략...컨트롤러 (src/main/java/[대표패키지]/[-package 값]/web/[Entity 클래스명]Controller.java)
@Controller
@RequestMapping("/board.do")
public class BoardController {
/**
* Resource Injection on BoardService
*/
@Resource(name="boardService")
private BoardService boardService;
중략...
/**
* Display Board list.
* @param request current HTTP request
* @param searchVO form object with request parameters bound onto it
* @param model model containing control data
* @return the prepared Board list view
* @throws Exception in case of getting Board paging list
*/
@RequestMapping(params = "method=list")
public String list(HttpServletRequest request,
@ModelAttribute("search") SearchVO searchVO, Model model) throws Exception
{
String pageParam = (new ParamEncoder("boardList").
encodeParameterName(TableTagParameters.PARAMETER_PAGE));
String pageParamValue = request.getParameter(pageParam);
int pageIndex = StringUtil.isNotEmpty(pageParamValue) ?
(Integer.parseInt(pageParamValue)) : 1;
searchVO.setPageIndex(pageIndex);
Page resultPage = boardService.getPagingList(searchVO);
model.addAttribute("boardList", resultPage.getList());
model.addAttribute("size", resultPage.getTotalCount());
model.addAttribute("pagesize", resultPage.getPagesize());
model.addAttribute("pageunit", resultPage.getPageunit());
return "generation/board/listBoard";
}
}UI JSP 파일 (src/main/webapp/WEB-INF/jsp/[프로젝트명]/*.jsp)
<%@ include file="/sample/common/taglibs.jsp"%>
<html>
<head>
<%@ include file="/sample/common/meta.jsp" %>
<title><fmt:message key="boardList.title"/></title>
<meta name="heading" content="<fmt:message key='boardList.heading'/>"/>
<link rel="stylesheet" type="text/css" media="all"
href="<c:url value='/sample/css/displaytag.css'/>" />
<link rel="stylesheet" href="<c:url value='/sample/css/admin.css'/>"
type="text/css">
<script type="text/javascript"
src="<c:url value='/sample/javascript/prototype.js'/>"></script>
<script type="text/javascript"
src="<c:url value='/sample/javascript/global.js'/>"></script>
<script type="text/javascript"
src="<c:url value='/sample/javascript/CommonScript.js'/>"></script>
<script language="JavaScript">
function fncAddBoardView() {
document.location.href="<c:url value='/board.do?method=addView'/>";
}
function fncSearchBoard(arg) {
var conditions = ["boardId","boardMasterId","boardTopics"]
중략...단위테스트케이스 (src/test/java/[대표패키지]/[-package 값]/web/[Entity 클래스명]ControllerTest.java)
@RunWith(JMock.class)
public class BoardControllerTest {
private BoardController controller;
private String SUCCESS_ADDVIEW = "generation/board/viewBoard";
private String SUCCESS_ADD = "redirect:/board.do?method=list";
private String SUCCESS_GET = "generation/board/viewBoard";
private String SUCCESS_UPDATE = "forward:/board.do?method=list";
private String SUCCESS_LIST = "generation/board/listBoard";
private String SUCCESS_DELETE = "redirect:/board.do?method=list";
private Mockery context = new JUnit4Mockery();
private BoardService mockService = null;
@Before
public void setUp() throws Exception {
System.setProperty("log4j.configuration", "log4j-test.xml");
this.mockService = context.mock(BoardService.class);
this.controller = new BoardController();
this.controller.setBoardService(this.mockService);
}
public void setBoardController(BoardController controller) {
this.controller = controller;
}
@Test
public void testAddView() throws Exception{
String viewName = this.controller.addView(new ExtendedModelMap());
assertEquals("returned correct view name", SUCCESS_ADDVIEW, viewName);
}
중략...위에서 설명한 기능 수행 도중에는 어플리케이션/프로젝트 생성, 코드 생성 및 DB 변경 등과 같은 Anyframe Gen의 기능을 동시에 수행시킬 수 없으므로 유의하도록 한다. (Background 실행을 통한 기능 수행 시)
현재 Multi 프로젝트 구조에서 Query Service와 Hibernate/JPA를 DAO Framework으로 사용하는 경우, HibernateTransactionManager를 공통으로 사용할 수 있다. (Query Service만 사용하는 경우 DataSourceTransactionManager를 사용할 수도 있다.) 단, Multi 프로젝트 중 공통(common) 타입 프로젝트에 설정된 HibernateTransactionManager에서 dataSource property에 대한 설정을 반드시 해줘야 한다. 아래 예시를 참고하도록 한다. Single 프로젝트 구조에서는 HibernateTransactionManager bean에 dataSource property 설정을 해주지 않아도 된다.
<bean id="hibernateTxManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
<property name="dataSource" ref="dataSource" />
</bean>
중략...Anyframe Gen을 사용하기 위해 Application Location 확인 및 DAO Frameworks, Template 정보를 설정한다.
어플리케이션과 프로젝트를 생성할 때 설정한 Single Project, Multi Projects 정보에 따라 활성화 되는 메뉴가 다르다.
프로젝트는 기본적으로 Query Service DAO Framework 을 사용하도록 설정되어 있으며, Hibernate/JPA으로 DAO Frameworks 설정을 변경하고 싶을 경우 Installation Tab에서 Hibernate 플러그인을 설치해야 한다. Hibernate/JPA 플러그인이 설치되어 있지만 예외적으로 Template이 MiPlatform으로 되어 있는 경우는 Hibernate/JPA Framework을 사용할 수 없다.
Single Project structure일때, Template은 기본적으로 default만 제공되고, Installation Tab에서 MiPlatform 플러그인을 설치한 경우 추가적으로 선택할 수 있다.
Multi Projects structure일때, Template에 따라 설치되는 프로젝트 아키타입이 다르므로, 프로젝트를 생성한 후에 사용할 수 있는 Anyframe Gen configuration 에서는 Template 정보에 대해 조회만 가능하다.
프로젝트 (Multi Projects Structure인 경우 Service 프로젝트)를 선택한 후 우 클릭 >> Anyframe Gen 을 선택한다.
Anyframe Gen Editor에서 Configuration Tab을 선택하고 어플리케이션 경로 확인 및 DAO Framework, Template 정보를 구성한다.
Application Location: 현재 프로젝트가 생성된 어플리케이션 위치정보가 보인다.
DAO Frameworks: Query Service, Hibernate/JPA 중에 하나를 선택할 수 있고, Hibernate/JPA는 Hibernate 플러그인을 설치한 이후에 선택이 가능하다. MiPlatform Template의 경우 Query Service만 지원된다.
Template Selection: Single Project Structure의 경우 기본적으로 default, default-xml, map 템플릿이 지원되며, default 템플릿은 Annotation 기반의 Spring/SpringMVC 등으로 구성된 소스 코드 템플릿이 제공된다. MiPlatform 플러그인을 설치한 경우 MiPlatform Template도 선택할 수 있다. MiPlatform 의 경우 PID(Presentation Interface Developer)가 설치되어 있어야 생성된 소스가 정상적으로 동작한다. Multi Projects structure일때, Template에 따라 설치되는 프로젝트 아키타입이 다르므로, 프로젝트를 생성한 후에 사용할 수 있는 Anyframe Gen configuration 에서는 Template 정보에 대해 조회만 가능하다.

입력정보 작성이 끝나면 반드시 Apply 버튼을 클릭하여 Configuration 정보가 저장되도록 한다. 구성한 정보가 정상적으로 반영되었는지 확인하기 위해서는 탐색기에서 선택한 어플리케이션 경로로 이동하여, application-build.properties 파일내의 dao.framework(DAO Frameworks), template_type(Template Type) 항목의 값을 확인해본다. 정상적으로 반영이 되었다면, 해당 항목의 값이 입력한 값들로 변경되어 보일 것이다. 참고로, app.home 은 어플리케이션 경로 정보이다.
Anyframe Gen의 Domain Class 를 생성 기능을 사용하기 위해서 DB 연결정보를 설정한다.
Single Project Structure 일 경우에는 생성된 하나의 프로젝트에서 Domain, CRUD, Configuration 등이 가능하지만, Multi Project Structure일 경우에는 모든 프로젝트에서 Domain Class 를 생성시킬 수 있는 것이 아니라 Domain 타입 프로젝트로 지정된 프로젝트에서만 Domain Class 를 생성시킬 수 있다. Domain 타입 프로젝트는 최초 생성되는 Service 타입 프로젝트로 지정된다. 그러므로 Domain 타입 프로젝트로 지정된 Service 타입 프로젝트에서만 Anyframe Gen 팝업메뉴를 통해 Domain Class 를 생성시킬 수 있으므로 JDBC Configuration 도 마찬가지로 Domain 타입 프로젝트에서만 가능하다.
프로젝트 (Multi Projects Structure인 경우 Service 프로젝트)를 선택한 후 우 클릭 >> Anyframe Gen 을 선택한다.
Anyframe Gen Editor에서 JDBC Setting Tab을 선택하고 JDBC 연결정보를 입력한다.
Database Type: Database 타입으로 HSQL, Oracle, MySQL, Sybase 를 제공하고 있다.
Database Name: Database의 이름
User Name: DB 유저 이름
Schema: DB 스키마의 이름
Password: 패스워드
Server: DB가 설치된 서버 ip 정보, 로컬에서 사용하는 경우 localhost
Port: HSQL의 경우 -1, Oracle의 경우 1521, MySQL의 경우 3306, Sybase는 3000
Hibernate Dialect: Hibernate에서 쿼리 수행 시, DBMS에 최적화된 기능을 제공하기 위해 사용되는 것이 SQL Dialect 이며, 이 Dialect 프로퍼티를 사용하여 해당 DB 별 Dialect 정보를 설정할 수 있다. 각 DB 별 Dialect 클래스가 따로 존재하여 HSQL DB를 선택한 경우, 디폴트로 org.hibernate.dialect.HSQLDialect값이 선택된다.(Oracle, MySQL, Sybase Dialect 도 제공함)
Driver Class Name: DB의 드라이버 클래스를 설정해 주기 위한 값으로, HSQL의 경우 org.hsqldb.jdbcDriver 값으로 설정된다. Database Type 선택 시 해당 DB에 맞는 값이 셋팅된다.
Driver Jar Path: Anyframe Gen 설치 시 샘플 DB를 위한 HSQL DB Driver Jar 파일이 제공되므로 디폴트로 설정된다. 만약 다른 DB를 사용한다면 해당 DB의 Driver jar 파일로 연결시켜준다.

입력정보 작성이 끝나면 반드시 Apply 버튼을 클릭하여 JDBC Configuration 정보가 저장되도록 한다.
Schema 정보를 리스트에서 선택하지 않고 Apply 버튼을 클릭할 경우, Schema 를 선택하라는 메시지가 출력된다. Schema 를 제외한 나머지 JDBC Configuration 정보가 정상적인 경우 Schema 정보를 얻어올 수 있으며, 얻어온 리스트에서 Schema 를 선택하여 Apply 하면 Configuration 정보가 반영된다.
JDBC 환경 설정 정보가 정상적으로 구성되어 DB와 잘 연결되는지 확인하기 위해서는 Domain Generation Tab으로 이동하여 Refresh 버튼을 클릭해본다. 이때 정상적으로 연결이 잘 되는 경우라면 해당 DB의 Table들이 조회될 것이다.
위에서 설명한 기능 수행 도중에는 어플리케이션/프로젝트 생성, 코드 생성 및 DB 변경 등과 같은 Anyframe Gen의 기능을 동시에 수행시킬 수 없으므로 유의하도록 한다. (Background 실행을 통한 기능 수행 시)
Anyframe Gen에서 Anyframe에서 제공하는 플러그인 을 Install/Uninstall 하기 위해서 사용한다.
프로젝트 (Multi Projects Structure인 경우 Service 타입 프로젝트)를 선택한 후 우 클릭 >> Anyframe Gen 을 선택한다.
Anyframe Gen Editor에서 Installation Tab을 선택하면 다음과 같은 화면이 보인다.
!: Install/Uninstall 할 대상을 체크하는 부분으로, foundation 플러그인은 Anyframe 사용을 위한 기본 플러그인이므로, Install/Uninstall 대상에서 제외된다.
Plugin Type: 플러그인 타입
Group Id: 플러그인 Library의 Group 명
Artifact Id: 플러그인 Library 명
Version: 플러그인 버전
Installed: 플러그인이 설치되었는지 여부

설치 또는 제거할 플러그인 항목을 체크한 후, Install 혹은 Uninstall 버튼을 클릭한다.
Install/Uninstall 할 경우 tomcat은 stop 시킨 상태에서 수행하도록 한다. 그렇지 않은경우, 동작은 정상적으로 수행되나, 아래 4번 내용과 같은 에러가 발생하게 된다.
플러그인 이 설치되었으면 Installed 항목에서 O표시가, 제거되었으면 X표시가 되며, 현재 설치되어 있는 플러그인 다음과 같은 방법으로 확인할 수 있다.
Single Project Structure의 경우 해당 플러그인과 샘플이 함께 설치되며, 해당 플러그인 적용된 샘플은 single project를 실행시켜봄으로써 확인할 수 있다. Multi projects Structure의 경우 해당 플러그인의 라이브러리만 설치된다.
샘플 실행방법은[ New Application Creation]의 어플리케이션 실행방법 내용을 참조한다.
아래는 플러그인 설치 및 제거와 관련하여 정상적으로 반영되었는지 확인하는 방법이다.
metadata 정보확인: 프로젝트(Multi Projects Structure인 경우 어플리케이션)폴더 >> .metadata폴더>> anyframe-plugins-metadata.mf 파일에 list로 관리한다.
foundation=anyframe,anyframe.plugin.foundation,4.0.0,com.sds.emp,sample miplatform=anyframe,anyframe.plugin.miplatform,4.0.0,com.sds.emp,
Single Project Structure: 플러그인 추가/삭제 시 관련된 라이브러리는 프로젝트 Web App Libraries에 추가/삭제 되며, 샘플이 설치된다.
Multi Projects Structure: Common 타입 프로젝트의 .classpath에 설치된 플러그인 정보가 표시되고, Web 타입 프로젝트의 Web App Libraries에 추가/삭제된다. 아래는 Common 타입 프로젝트의 .classpath일부분이다.
중략...
<!--dynamicmodule here -->
<!--dynamicmodule-START-->
<!--dynamicmodule-END-->
<!--hibernate here -->
<!--hibernate-START-->
<classpathentry exported="true" kind="var"
path="GEN_REPO/antlr/antlr/2.7.7/antlr-2.7.7.jar" />
<classpathentry exported="true" kind="var"
path="GEN_REPO/anyframe/anyframe.hibernate/4.0.0/
anyframe.hibernate-4.0.0.jar" />
<classpathentry exported="true" kind="var"
path="GEN_REPO/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar" />
<classpathentry exported="true" kind="var"
path="GEN_REPO/net/sf/ehcache/ehcache/1.6.2/ehcache-1.6.2.jar" />
중략...
<!--hibernate-END-->플러그인 Install/Uninstall 시에 다음 그림과 같은 메시지가 뜨는 경우는 tomcat이 실행된 상태에서 tomcat이 인식하고 있는 파일에 변경이 있는 경우에 발생하는 것이다.
아래와 같은 메시지는 플러그인 Install/Uninstall 전에 tomcat 동작을 stop 시킬 경우에는 뜨지 않는다.

위에서 설명한 기능 수행 도중에는 어플리케이션/프로젝트 생성, 코드 생성 및 DB 변경 등과 같은 Anyframe Gen의 기능을 동시에 수행시킬 수 없으므로 유의하도록 한다. (Background 실행을 통한 기능 수행 시)
Anyframe Gen 을 이용해 단위 프로젝트 별 빌드 혹은 어플리케이션 전체 빌드를 수행할 수 있다.
각각의 단위 프로젝트 생성 시에 빌드 스크립트 파일이 함께 생성되어, 빌드를 수행할 수 있다. 빌드 도구로 Ant를 사용하며 디폴트 타겟 빌드 수행 시 컴파일, 테스트, 패키징, 배포 등의 공통적인 빌드 프로세스 단계를 수행해주고 있다.
아래의 두 가지 경우로 나누어서 살펴보자.
[1. Project Build :] 단위 프로젝트 별 빌드 수행
[2. Application Build :] 어플리케이션 전체 빌드 수행
프로젝트 내 build.xml 확인
프로젝트 내부로 자동 생성되어진 build.xml 파일이 존재한다. 빌드 스크립트 내에는 빌드 수행을 위한 compile, test, package, deploy 등 공통적으로 사용되는 빌드 타겟들이 존재한다. 실제 구동 내역을 가지고 있는 공통 스크립트는 [Gen Home]\cli\scripts\project-build.xml 파일 내에 작성되어 있다. 프로젝트 별로 변경해야 하는 일이 생기면 공통 스크립트를 수정하면 된다. 또한 각 프로젝트 단위 별로 공통 빌드 내역 외에 특화된 빌드 내용을 추가해야 하는 경우에는 해당 빌드 타겟을 확장하여 추가해 넣을 수 있다.
다음은 Single 타입 프로젝트에 생성된 build.xml 의 일부분이다.
<project name="Build module" default="default" basedir=".">
<property file = "build.properties"/>
<property file = "./../application-build.properties"/>
<import file = "${gen.home}/cli/scripts/project-build.xml"/>
<target name="clean" depends = "shared:clean" />
<target name="init" depends = "shared:init" />
<target name="resources" depends = "shared:resources" />
<target name="compile" depends = "shared:compile" />
<target name="report-compile" depends="shared:report-compile" />
<target name="test-resources" depends = "shared:test-resources" />
<target name="test-compile" depends = "shared:test-compile" />
<target name="package" depends = "shared:package" />
<target name="emma-jars" depends = "shared:emma-jars" />
<target name="test" depends = "shared:test" />
<target name="report" depends = "shared:report" />
<target name="deploy" depends = "shared:deploy"/>
<target name = "default" depends = "init, resources, compile, package, deploy"/>
<target name = "all" depends = "clean, init, resources, report-compile,
test-resources, test-compile, package, emma-jars, test,
report, deploy"/>
</project>프로젝트 내 build.xml 선택 후 >> Run As >> Ant Build 을 선택
디폴트 타겟이 수행되어 다음과 같은 빌드 프로세스를 거치게 된다. 최종 결과물인 프로젝트 바이너리 파일은 repo 폴더 하위에 존재하게 된다.
init -> resources -> compile -> package -> deploy
프로젝트 내 build.xml 선택 후 >> Run As >> Ant Build... 을 선택
디폴트 타겟이 아닌 리포팅 결과물을 생성해내는 타겟을 실행시켜 본다. 빌드 시 코드 분석 리포트, 테스트 수행 결과 리포트, 코드 커버리지 리포트 등을 생성시킨다. 리포트 결과물은 프로젝트 내 output 폴더에 생성되므로 빌드가 모두 완료된 뒤 확인해보도록 한다.
clean -> init -> resources -> report-compile -> test-resources -> test-compile -> package -> emma-jars -> test -> report -> deploy
어플리케이션이 생성된 폴더 경로로 이동한 후 Command Prompt 창을 열고, 빌드를 수행한다. (CLI(Command Line Interface)이용)
이때 gen 이라는 command를 이용하여 빌드를 수행할 것이기 때문에 [Gen Home]\bin 폴더 하위에 있는 env.bat 파일을 해당 Command Prompt 창에서 먼저 실행해준다.
어플리케이션을 빌드하는 방법은 다음과 같이 3가지가 있으며, 해당 command 는 어플리케이션이 생성된 경로로 이동하여 실행한다.
어플리케이션 빌드 후 WEB-INF/classes 폴더 하위에 CLASS 형태로 배포하는 방법
gen build-app -deploy class
어플리케이션 빌드 후 WEB-INF/lib 폴더 하위에 JAR 파일 형태로 배포하는 방법
gen build-app -deploy jar
어플리케이션 빌드 후 WEB-INF/modules 폴더 하위에 JAR 파일 형태로 배포하는 방법(* Dynamic Reloading 기능을 이용하여 개발된 어플리케이션에 한함)
gen build-app
Anyframe Gen 툴을 통해 자동 생성되는 프로젝트 구조와 소스 코드는 각 개발자 혹은 프로젝트 상황에 맞게 확장하여 사용할 수 있는 구조를 제공한다. 템플릿 파일들의 배포 위치는 [Gen Home] 폴더 하위의 templates 폴더이며 Anyframe Gen 설치 시 기본적으로 default, default-xml, map, miplatform, miplatform-xml 템플릿을 제공하고 있다.
기본적으로 제공되는 각각의 템플릿에 대해서 살펴본 후, 필요한 템플릿에 대해서 확장해보도록 한다.
표 35. 기본 템플릿
| template name | description |
|---|---|
| default, default-xml | 가장 기본이 되는 템플릿으로 spring/spring mvc 기반으로 Business Layer와 Presentation Layer 간의 데이터 통신을 DTO(Data Transfer Object) 객체를 이용하여 구현하며, 화면은 JSP 페이지로 구성되어 있다. |
| map | spring 기반으로 Business Layer와 Presentation Layer 간의 데이터 통신을 Map(java.util.Map) 객체를 이용하도록 Business Layer 코드, Presentation Layer 코드를 생성해준다. 또한 DAO 코드는 Query Service를 이용하여 생성해주고 있다. Hibernate를 이용한 DAO 코드는 생성하지 않는다. |
| miplatform, miplatform-xml | spring/spring mvc 기반으로 Business Layer와 Presentation Layer 간의 데이터 통신을 MiPlatform의 객체(DatasetList,VariableList)를 이용하여 구현하며, 화면은 MiPlatform을 이용한 UI로 구성되어 있다. |
[Gen Home] 폴더 하위의 templates 폴더를 살펴보면 default, default-xml, map, miplatform, miplatform-xml 폴더가 존재하고 그 하위로 각각 project와 source 폴더가 존재하고 있음을 확인할 수 있다.
프로젝트 템플릿을 확장한다는 것은 Anyframe Gen을 통해 생성되는 프로젝트 구조를 포함하여 샘플 코드, 프로젝트 내부 빌드 파일 등을 각 개발자 혹은 프로젝트 상황에 맞게 수정하여 사용할 수 있다는 것으로 여기서는 Maven의 Archetype을 작성함으로써 프로젝트 템플릿을 확장할 수 있다. Archetype에 대한 자세한 내용은 Introduction to Archetypes 을 참조하도록 한다.
어플리케이션의 프로젝트 구조가 Single 인지 Multi 인지에 따라 Project Template 확장 방법이 다르므로 유의하도록 한다.
Single 프로젝트의 경우, 기본적인 프로젝트 구조 및 샘플 코드가 Anyframe의 Foundation Plugin(anyframe.plugin.foundation-4.0.0.jar)으로부터 생성된다.
Anyframe Gen을 통해서는 샘플 코드 일부와 빌드 스크립트가 생성되므로 이 매뉴얼에서는 Anyframe Gen을 통해 변경될 수 있는 부분을 설명하겠다. Anyframe Foundation Plugin에 대한 설명은 Anyframe 매뉴얼을 참고하도록 한다.
아래 나열한 순서에 따라서 확장해보도록 한다. 아래에서는 message source 파일(properties)을 더 추가해보는 예제로 구성되어 있다.
Anyframe source code repository(Subversion)으로부터 anyframe.gen.archetype.singleconfig 프로젝트(SVN URL:http://dev.anyframejava.org/subv/anyframe-opensource/gen/tags/gen-1.0.0/dev/archetype/anyframe.gen.archetype.singleconfig)를 내려받는다. Subversion에 Access하는 자세한 방법은 이곳(Subversion 연결) 을 참고하도록 한다.
Eclipse에 anyframe.gen.archetype.singleconfig 프로젝트를 Import한 후, 프로젝트 명을 변경시킨다. 이때 이름은 반드시 anyframe.gen.archetype.singleconfig로 시작 하는 이름이어야 한다.
예를 들어, anyframe.gen.archetype.singleconfig.ext로 프로젝트 명을 변경시켜보자.
Eclipse Project 명 변경: 프로젝트 선택 후 마우스 우측 버튼 선택 > Refactor > Rename...> anyframe.gen.archetype.singleconfig.ext 입력 > OK
Maven Project 명 변경: 프로젝트 하위에 있는 pom.xml 파일을 Open하여 아래와 같이 groupId, artifactId, version 정보를 원하는 정보로 변경하도록 한다.
<groupId>templates.project.ext</groupId> <artifactId>anyframe.gen.archetype.singleconfig.ext</artifactId> <version>1.0.0</version>
Project 폴더명까지 모두 anyframe.gen.archetype.singleconfig.ext으로 변경하여 기존의 anyframe.gen.archetype.singleconfig 프로젝트와 혼동되지 않도록 관리한다.
anyframe.gen.archetype.singleconfig.ext 프로젝트 하위의 src/main/resources/archetype-resources 폴더 내 파일들을 변경 및 추가할 수 있다.
샘플 코드 혹은 빌드 스크립트 파일을 변경할 수 있다. 샘플 코드는 src/main/resources/archetype-resources/src 폴더 하위에, 빌드 스크립트 파일(build.xml, build.properties)은 src/main/resources/archetype-resources/pjt 폴더 하위에 위치하고 있다.
신규 message resource 파일을 추가하여, 프로젝트 생성 시 나타나도록 message-ext.properties 파일을 추가한다.
그러므로 src/main/resources/archetype-resources/src/main/resources/message 폴더 하위에 message-ext.properties 파일을 추가한다.
수정 및 추가한 정보에 의해 부가적으로 변경되어야 하는 파일이 존재하는 경우, 함께 수정하도록 한다.
message resource 파일이 추가되면, spring messageSource bean에 properties 파일을 추가 설정해주도록 한다. 즉, src/main/resources/archetype-resources/src/main/resources/spring/context-common.xml 파일에 다음과 같이 value 태그를 추가해넣는다.
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basenames"> <list> <value>message/message-ext</value> <value>message/message-generation</value> <value>message/message-productmgmt</value> <value>anyframe/core/properties/messages/properties</value> 중략... </list> </property> </bean>
확장된 anyframe.gen.archetype.singleconfig.ext 프로젝트를 패키징한다.
Maven으로 프로젝트를 빌드하여 jar 파일로 패키징하도록 한다. Maven 빌드를 하기 위해서는 Maven을 먼저 설치해야 하는데 이는 Anyframe 매뉴얼 중 Maven 설치 및 환경 설정 부분을 참고하도록 한다. Maven 설치 및 환경 설정 한 이 후 "mvn package" command를 수행시킨다. 그 결과 패키지 파일은 anyframe.gen.archetype.singleconfig.ext 프로젝트 하위의 target 폴더에 anyframe.gen.archetype.singleconfig.ext-1.0.0.jar 파일로 생성된다.
mvn package
확장된 anyframe.gen.archetype.singleconfig.ext 배포 파일을 [Gen Home] 폴더 하위의 templates 폴더에 위치시키는데 이때, 새로운 템플릿으로 명명하여 사용할 것이므로 templates 폴더 하위에 ext와 같이 템플릿명을 나타내는 폴더를 생성한 뒤 다음과 같이 ext 폴더 하위로 project 폴더를 두고, anyframe.gen.archetype.singleconfig.ext-1.0.0.jar 파일을 배포한다.
즉, [Gen Home]/templates/default 폴더 전체를 복사하여 [Gen Home]/templates/ext 폴더에 위치시킨 후 기존의 anyframe.gen.archetype.singleconfig-1.0.0.jar 파일을 project 폴더에서 삭제하고 새로 패키징한 anyframe.gen.archetype.singleconfig.ext-1.0.0.jar 파일을 위치시킨다.
Single 프로젝트 생성 기능을 수행시켜서 위에서 추가한 message-ext.properties 파일이 자동생성되어 구성되는지 확인해보도록 한다.
CLI상에서 Single 타입 프로젝트 생성 시 application-build.properties 파일의 template_type 항목의 값을 ext로 변경하고 생성하도록 한다. Eclipse Plugin을 이용하여 Single 타입 프로젝트 생성 시에는 AnyframeGen Editor의 Configuration Tab 내에서 template을 ext로 변경하고 생성하도록 한다.
Multi 프로젝트의 경우, 프로젝트 타입(common, service, web) 별로 프로젝트 구조 및 샘플 코드가 구성되어 생성된다.
다음 표와 같이 여러 종류의 Archetype이 있으므로 확장하고 싶은 Archetype에 대해 작업하도록 한다.
표 19.1. Multi Projects Archetypes
| archetype | description |
|---|---|
| anyframe.gen.archetype.common | 공통(common) 타입 프로젝트의 구조와 샘플 코드를 생성시켜주는 archetype으로 공통 Exception, Aspect 클래스와 message source 파일, spring 설정 파일 그리고 빌드 스크립트를 제공한다. |
| anyframe.gen.archetype.domain | Users 도메인 클래스, hibernate/query 설정 파일, spring 설정 파일을 제공하는 archetype이다. |
| anyframe.gen.archetype.service | 서비스(service) 타입 프로젝트의 구조와 샘플 코드를 생성시켜주는 archetype으로 UsersService와 AuthenticationService 클래스 및 테스트 클래스, spring 설정 파일 그리고 빌드 스크립트를 제공한다. 특히 이 archetype은 최초로 생성되는 서비스(service) 타입 프로젝트로 복수 개의 서비스(service) 타입 프로젝트가 생성될 때에는 이 archetype이 사용되지 않는다는 것에 유의하도록 한다. |
| anyframe.gen.archetype.scaffold.service | 서비스(service) 타입 프로젝트의 구조와 샘플 코드를 생성시켜주는 archetype으로 샘플 클래스 없이 spring 설정 파일 그리고 빌드 스크립트를 제공한다. 특히 이 archetype은 최초로 생성되는 서비스(service) 타입 프로젝트에는 사용되지 않고 복수 개의 서비스(service) 타입 프로젝트가 생성될 때 이 archetype이 사용되고 있으므로 유의하도록 한다. |
| anyframe.gen.archetype.web | 웹(web) 타입 프로젝트의 구조와 샘플 코드를 생성시켜주는 archetype으로 UsersController와 LogIn/LogOutContoller 클래스 및 테스트 클래스, spring/spring mvc 설정 파일 그리고 빌드 스크립트를 제공한다. 이 archetype은 웹 프로젝트를 생성시키므로 Users에 관한 JSP 페이지, 이미지, CSS 파일 등이 모두 함께 제공된다. |
아래 나열한 순서에 따라서 확장해보도록 한다. 아래에서는 anyframe.gen.archetype.common을 확장한 예만 설명하고 있으나, anyframe.gen.archetype.domain 등 나머지 모든 archetype에 대해서도 동일한 방법으로 확장가능하다.
Anyframe source code repository(Subversion)으로부터 archetype 프로젝트를 내려받도록 한다. (SVN URL은 다음 표를 참조한다.) Subversion에 Access하는 자세한 방법은 이곳(Subversion 연결) 을 참고하도록 한다.
표 19.2. Archetype SVN URL
| archetype | SVN URL |
|---|---|
| anyframe.gen.archetype.common | http://dev.anyframejava.org/subv/anyframe-opensource/gen/tags/gen-1.0.0/dev/archetype/anyframe.gen.archetype.common |
| anyframe.gen.archetype.domain | http://dev.anyframejava.org/subv/anyframe-opensource/gen/tags/gen-1.0.0/dev/archetype/anyframe.gen.archetype.domain |
| anyframe.gen.archetype.service | http://dev.anyframejava.org/subv/anyframe-opensource/gen/tags/gen-1.0.0/dev/archetype/anyframe.gen.archetype.service |
| anyframe.gen.archetype.scaffold.service | http://dev.anyframejava.org/subv/anyframe-opensource/gen/tags/gen-1.0.0/dev/archetype/anyframe.gen.archetype.scaffold.service |
| anyframe.gen.archetype.web | http://dev.anyframejava.org/subv/anyframe-opensource/gen/tags/gen-1.0.0/dev/archetype/anyframe.gen.archetype.web |
Eclipse에 각각의 archetype 프로젝트를 Import한 후, 프로젝트 명을 변경시킨다. 이때 이름은 반드시 anyframe.gen.archetype.[archetype명]으로 시작 하는 이름이어야 한다.
예를 들어, anyframe.gen.archetype.common.ext로 프로젝트 명을 변경시켜보자.
Eclipse Project 명 변경: 프로젝트 선택 후 마우스 우측 버튼 선택 > Refactor > Rename...> anyframe.gen.archetype.common.ext 입력 > OK
Maven Project 명 변경: 프로젝트 하위에 있는 pom.xml 파일을 Open하여 아래와 같이 groupId, artifactId, version 정보를 원하는 정보로 변경하도록 한다.
<groupId>templates.multiproject.ext</groupId> <artifactId>anyframe.gen.archetype.common.ext</artifactId> <version>1.0.0</version>
Project 폴더명까지 모두 anyframe.gen.archetype.common.ext으로 변경하여 기존의 anyframe.gen.archetype.common 프로젝트와 혼동되지 않도록 관리한다.
anyframe.gen.archetype.common.ext 프로젝트 하위의 src/main/resources/archetype-resources 폴더 내 파일들을 변경 및 추가할 수 있다.
샘플 코드 혹은 빌드 스크립트 파일을 변경할 수 있다. 샘플 코드는 src/main/resources/archetype-resources/src 폴더 하위에, 빌드 스크립트 파일(build.xml, build.properties, build-dynamic.xml)은 src/main/resources/archetype-resources/pjt 폴더 하위에 위치하고 있다.
LoggingAspect 클래스에 afterLogging 메소드를 추가한다.
아래와 같이 src/main/java/common/aspect/LoggingAspect.java 파일을 열어서 afterLogging 메소드를 추가해넣는다. 메소드 호출 후에도 로깅을 남기도록 수정한다.
private MessageSource messageSource;
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}
public void afterLogging(JoinPoint thisJoinPoint) {
Class clazz = thisJoinPoint.getTarget().getClass();
String className = clazz.getName();
String classSimpleLowerName = thisJoinPoint.getTarget().getClass().
getSimpleName().toLowerCase();
String methodName = thisJoinPoint.getSignature().getName();
String methodLowerName = methodName.toLowerCase();
StringBuffer buf = new StringBuffer();
buf.append("\n** After Logging Aspect : executed " + methodName + "() in "
+ className + " Class.");
buf.append("\n*******************************************\n");
buf.append(messageSource.getMessage("success." + classSimpleLowerName + "."
+ methodLowerName, new String[] {}, "no messages", Locale.getDefault()));
buf.append("\n*******************************************\n");
Log logger = LogFactory.getLog(clazz);
if (logger.isDebugEnabled())
logger.debug(buf.toString());
}수정 및 추가한 정보에 의해 부가적으로 변경되어야 하는 파일이 존재하는 경우, 함께 수정하도록 한다.
Aspect 클래스에 메소드가 추가되고 이를 반영하기 위해 src/main/resources/archetype-resources/src/main/resources/spring/context-aspect.xml 파일에 다음과 같이 aop:after 태그를 추가해넣는다.
<aop:config> <aop:pointcut id="loggingMethod" expression="execution(* *..*Service+.*(..))" /> <aop:aspect ref="methodLoggingAspect" > <aop:before method="beforeLogging" pointcut-ref="loggingMethod"/> <aop:after method="afterLogging" pointcut-ref="loggingMethod" /> </aop:aspect> </aop:config>
확장된 anyframe.gen.archetype.common.ext 프로젝트를 패키징한다.
Maven으로 프로젝트를 빌드하여 jar 파일로 패키징하도록 한다. Maven 빌드를 하기 위해서는 Maven을 먼저 설치해야 하는데 이는 Anyframe 매뉴얼 중 Maven 설치 및 환경 설정 부분 을 참고하도록 한다. Maven 설치 및 환경 설정한 이후 "mvn package" command를 수행시킨다. 그 결과 패키지 파일은 anyframe.gen.archetype.common.ext 프로젝트 하위의 target 폴더에 anyframe.gen.archetype.common.ext-1.0.0.jar 파일로 생성된다.
mvn package
확장된 anyframe.gen.archetype.common.ext 배포 파일을 [Gen Home] 폴더 하위의 templates 폴더에 위치시키는데 이때, 새로운 템플릿으로 명명하여 사용할 것이므로 templates 폴더 하위에 ext와 같이 템플릿명을 나타내는 폴더를 생성한 뒤 다음과 같이 ext 폴더 하위로 project 폴더를 두고, anyframe.gen.archetype.common.ext-1.0.0.jar 파일을 배포한다.
즉, [Gen Home]/templates/default 폴더 전체를 복사하여 [Gen Home]/templates/ext 폴더에 위치시킨 후 기존의 anyframe.gen.archetype.common-1.0.0.jar 파일을 project 폴더에서 삭제하고 새로 패키징한 anyframe.gen.archetype.common.ext-1.0.0.jar 파일을 위치시킨다.
Multi 프로젝트 생성 기능을 수행시켜서 위에서 추가한 LoggingAspect.java 파일이 자동생성되어 구성되는지 확인해보도록 한다.
CLI상에서 Multi 타입 프로젝트 생성 시 application-build.properties 파일의 template_type 항목의 값을 ext로 변경하고 생성하도록 한다. Eclipse Plugin을 이용하여 Multi 타입 프로젝트 생성 시에는 AnyframeGen Editor의 Configuration Tab 내에서 template을 ext로 변경하고 생성하도록 한다.
[Gen Home] 폴더 하위의 templates 폴더를 살펴보면 아래와 같이 default, default-xml, map, miplatform, miplatform-xml 폴더가 존재하고 그 하위로 각각 project와 source 폴더가 존재하고 있음을 확인할 수 있다.
소스 코드 템플릿을 확장한다는 것은 Anyframe Gen을 통해 생성되는 도메인 클래스, CRUD 소스 코드에 대해서 각 개발자 혹은 프로젝트 상황에 맞게 수정하여 사용할 수 있다는 것으로 여기서는 FreeMarker Template을 수정함으로써 소스 코드 템플릿을 확장할 수 있다. FreeMarker에 대한 자세한 내용은 FreeMarker 사이트 를 참조하도록 한다.
어플리케이션의 프로젝트 구조가 Single 인지 Multi 인지에 상관없이 소스 코드 템플릿 확장 방법은 동일하다.
FreeMarker Template(*.ftl) 파일들을 수정하여 자동 생성되는 소스 코드에 대한 템플릿을 확장해보도록 한다.
default 템플릿을 확장하여 ext 템플릿을 구성해보자. 이때 프로젝트 템플릿은 확장하지 않고 소스 코드 템플릿만 확장해본다. 프로젝트 템플릿 확장하는 방법은 [프로젝트 템플릿 확장 매뉴얼] 을 참고하도록 한다.
[Gen Home]/templates/default 폴더 전체를 복사한 후 이름을 ext로 변경시켜서 [Gen Home]/templates/ext 폴더를 만들고 [Gen Home]/templates/ext/source 폴더 하위의 template.config 파일이 있는지 확인한다.
template.config 파일을 열고 소스 코드 생성에 필요한 템플릿 파일 목록을 작성한다.
template.config 파일 내 작성되는 정보는 소스 코드 생성 시 필요한 코드 템플릿 목록 정보로 default 템플릿을 통해 제공되는 템플릿 정보는 다음 표와 같다.
타입 별 템플릿 파일에 대한 설명으로, template.config 파일 내 템플릿 목록으로 작성되어야 CRUD 소스 코드 생성 시 결과 코드로 생성된다. service 타입 템플릿은 Business Layer 코드 생성 시 사용되는 템플릿이고, web 타입 템플릿은 Presentation Layer 코드 생성 시 사용된다.
template.config 파일 내 템플릿 정보 등록 시 아래와 같은 항목 내용을 작성하도록 한다.
type: service, web 타입
ftl: freemarker template 파일
src: 생성될 소스 코드 파일 명
{basepkg-name} : 대표패키지
{class-name} : 엔티티 클래스 명
share: sample db data 공유 여부를 true, false로 설정
dao: hibernate, query 중 dao framework 설정
description: 템플릿 설명
표 20.1. Service Type template configuration
| type | ftl | src | share | dao | description |
|---|---|---|---|---|---|
| service | dao/sample-data.ftl | src/test/resources/{class-name}-sample-data.xml | false | N/A | test sample db data |
| service | dao/dao-test.ftl | src/test/java/{basepkg-name}/dao/{class-name}Dao Test.java | true | N/A | dao class test case |
| service | dao/dao.ftl | src/main/java/{basepkg-name}/dao/{class-name}Dao.java | false | N/A | dao class |
| service | dao/dao-bean.ftl | src/main/resources/{class-name}Dao-bean.xml | false | N/A | dao class spring bean configuration xml 파일 |
| service | service/service-test.ftl | src/test/java/{basepkg-name}/service/impl/{class-name}Service ImplTest.java | false | N/A | service implementation class에 대한 test case |
| service | service/service.ftl | src/main/java/{basepkg-name}/service/{class-name} Service.java | false | N/A | service interface class |
| service | service/service-impl.ftl | src/main/java/{basepkg-name}/service/impl/{class-name}Service Impl.java | false | N/A | service implementation class |
| service | dao/hibernate/dao-impl.ftl | src/main/java/{basepkg-name}/dao/impl/{class-name} DaoHibernate Impl.java | false | hibernate | hibernate dao implementation class |
| service | dao/hibernate/dynamic-hibernate.ftl | src/main/resources/hibernate/dynamic/dynamic-hibernate-{class-name}.xml | false | hibernate | hibernate dynamic hql mapping xml file |
| service | dao/query/dao-impl.ftl | src/main/java/{basepkg-name}/dao/impl/{class-name}Dao QueryImpl.java | false | query | query dao implementation class |
| service | dao/query/mapping-query.ftl | src/main/resources/query/mapping-query-{class-name}.xml | false | query | query service mapping xml file |
| service | service/service-bean.ftl | src/main/resources/{class-name}Service-bean.xml | false | N/A | service class spring bean configuration xml 파일 |
| service | web/Application Resources.ftl | src/main/resources/{class-name}-Application Resources .properties | false | N/A | message source properties 파일 |
표 20.2. Web Type template configuration
| type | ftl | src | share | dao | description |
|---|---|---|---|---|---|
| web | web/spring/controller-test.ftl | src/test/java/{basepkg-name}/web/{class-name}Controller Test.java | false | N/A | spring mvc controller class test case |
| web | web/spring/controller.ftl | src/main/java/{basepkg-name}/web/{class-name} Controller.java | false | N/A | spring mvc controller class |
| web | web/spring/list-view.ftl | src/main/webapp/WEB-INF/jsp/sample/{class-name}/list{class-name}.jsp | false | N/A | list view jsp page |
| web | web/spring/form-view.ftl | src/main/webapp/WEB-INF/jsp/sample/{class-name}/view{class-name}.jsp | false | N/A | detail view jsp page |
| web | web/spring/controller-beans.ftl | src/main/webapp/WEB-INF/{class-name}-beans.xml | false | N/A | spring mvc controller class spring configuration xml file |
| web | web/menu.ftl | src/main/webapp/common/{class-name}-menu.jsp | false | N/A | menu jsp page |
[Gen Home]/templates/ext/source 폴더 하위에서 확장하고 싶은 ftl 파일들을 선정하여 수정하도록 한다.
source 폴더 하위에 있는 ftl 파일들은 원하는 폴더로 묶어서 관리할 수 있다. 현재에는 다음 표와 같이 4개의 폴더(model, service, dao, web)로 구분되어 있다. 자유롭게 변경할 수 있다. 단, 폴더명과 ftl 파일 명 변경 시 위에서 설명한 template.config 파일 내 ftl 항목 내용도 반드시 변경시켜줘야 한다.
표 20.3. template folder
| folder name | description |
|---|---|
| model | 도메인 클래스 생성 시 사용되는 ftl들 존재 |
| service | service 클래스/테스트 케이스 및 Spring bean 설정 파일 ftl들 존재 |
| dao | 샘플 데이터, hibernate/query dao 클래스/테스트 케이스 및 Spring bean 설정 파일 ftl들 존재 |
| web | 메뉴, message resource, spring mvc 클래스/테스트 케이스 및 Spring bean 설정 파일, JSP ftl들 존재 |
예를 들어 service 생성 시 기본 CRUD 메소드 외 다른 메소드를 추가해보자.
[Gen Home]/templates/ext/source/service/service.ftl 파일을 열어 다음과 같이 getProcedureList 메소드를 추가한다.
getProcedureList의 리턴 타입이 List 이므로 클래스 상단에 import 구문을 추가해줘야 함에 유의하도록 한다.
package ${basepackage}.service;
import java.util.List;
import anyframe.common.Page;
import anyframe.common.util.SearchVO;
import ${appfusepackage}.service.GenericService;
import ${pojo.packageName}.${pojo.shortName};
<#if c2j.isComponent(pojo.identifierProperty) >
import ${pojo.packageName}.${pojo.getJavaTypeName(pojo.identifierProperty, jdk5)};
</#if>
public interface ${pojo.shortName}Service extends
GenericService<${pojo.shortName},
${pojo.getJavaTypeName(pojo.identifierProperty, jdk5)}> {
public Page getPagingList(SearchVO searchVO) throws Exception;
public List getProcedureList(SearchVO searchVO) throws Exception;
}이 ftl 구문 내에서 클래스, 메소드 등의 이름을 변경하거나 내용을 수정할 수 있다. service interface(service.ftl) 클래스에 대한 내용 수정 시 service implementation(service-impl.ftl) 클래스에 대한 내용도 함께 수정해줘야 함에 유의하도록 한다.
[Gen Home]/templates/ext/source/service/service-impl.ftl 파일을 열어 다음과 같이 getProcedureList 메소드를 추가한다.
getProcedureList의 리턴 타입이 List 이므로 클래스 상단에 import 구문을 추가해줘야 함에 유의하도록 한다.
<#assign pojoNameLower = pojo.shortName.substring(0,1).toLowerCase()+
pojo.shortName.substring(1)>
package ${basepackage}.service.impl;
import java.util.List;
import anyframe.common.Page;
import anyframe.common.util.SearchVO;
import ${basepackage}.dao.${pojo.shortName}Dao;
import ${pojo.packageName}.${pojo.shortName};
<#if c2j.isComponent(pojo.identifierProperty) >
import ${pojo.packageName}.${pojo.getJavaTypeName(pojo.identifierProperty, jdk5)};
</#if>
import ${basepackage}.service.${pojo.shortName}Service;
import ${appfusepackage}.service.impl.GenericServiceImpl;
public class ${pojo.shortName}ServiceImpl extends
GenericServiceImpl<${pojo.shortName},
${pojo.getJavaTypeName(pojo.identifierProperty, jdk5)}>
implements ${pojo.shortName}Service {
${pojo.shortName}Dao ${pojoNameLower}Dao;
public ${pojo.shortName}ServiceImpl(${pojo.shortName}Dao ${pojoNameLower}Dao) {
super(${pojoNameLower}Dao);
this.${pojoNameLower}Dao = ${pojoNameLower}Dao;
}
public Page getPagingList(SearchVO searchVO) throws Exception {
return this.${pojoNameLower}Dao.getPagingList(searchVO);
}
public List getProcedureList(SearchVO searchVO) throws Exception{
중략...
}
}