 |  |
|
난이도 : 중급 Robert Peterson, WebSphere Enablement, Austin, TX, IBM
2007 년 3 월 13 일 IBM Rational Software Architect, Version 7.0을 사용하여 소프트웨어 프로젝트에서 발생하는 문제들을 해결하는 개인화 된 툴을 구현해 봅시다. 이 글에서는 그래픽 인터페이스와 표준 기반 템플릿으로 개발 툴을 구현하는 새로운 Transformation Authoring 기능을 소개합니다.
소프트웨어 개발자 또는 아키텍트의 업무는 매우 복잡하고, 가끔은 한번도 결합해 본적 없는 다른 기술들을 통합하는 일도 해야 할 수도 있다. 신종 기술의 끊임없는 출현과 기존 기술을 토대로 또 다른 변종 기술들이 끊임없이 출현하는 가운데, 그 아무리 최상의 엔터프라이즈 개발 툴이라고 해도 한계를 보이기 마련이다.
IBM® Rational® Software Architect 7.0에는 Transformation Authoring이라고 하는 새로운 기능이 포함되어 있다. 이클립스 프레임웍을 잘 알지 못해도, 또는 개별 코딩 없이도 커스텀 툴을 구현할 수 있다. 단순한 XPath 신택스(syntax)를 사용하는 그래픽 툴링과 템플릿을 사용한다. (참고자료) 이 글에서는 이 기술을 적용한 비즈니스 케이스를 설명하고, Transformation Authoring 기능이 어떻게 작동하는지를 설명하며, 예제를 통해 데이터베이스 액세스에 필요한 툴을 구현해 보도록 하겠다.
Transformation Authoring의 효과
Rational Software Architect의 Transformation Authoring 기능은 비즈니스 니즈(needs)와 연관된 커스텀 툴을 구현하는 방식을 제공하고 특별한 기술 없이도 구현될 수 있다. Transformation Authoring의 주요 장점에 대해 알아보자.
생산성 향상. 개발팀은 두 개의 개별 기술이나 시스템을 통합해야 할 때가 있다. 예를 들어, 기존 백엔드와 첨단 비즈니스 모델링 시스템을 통합해야 할 경우를 생각해 보자. 문제는 이 같은 상황에 사용할 수 있는 툴이 없다는 것이다. Transformation Authoring을 사용하여 커스텀 툴을 구현하여 이러한 특수한 문제를 해결할 수 있고, 팀의 생산성을 높이고 소프트웨어 시스템의 총 소유 비용을 줄일 수 있다.
일관성 유지를 통한 관리의 최소화. 이와 같은 커스텀 툴을 만들면 두 가지 효과를 볼 수 있다. 관례와 일관성이 생긴다는 점이다. 커스텀 툴을 구현하면, 개발팀은 best practices를 따르는 일관성 있는 패턴으로 시스템 컴포넌트를 생성할 수 있다. 이것은 마치 기름이 잘 칠해진 기계와 같은 시스템이 될 것이며, 아울러 문서화와 관리도 쉬워진다.
기민성, 유연성, 구체성. 가끔, 매우 특수한 문제를 해결하는 툴이 필요하지만, 여러분의 필요에 맞는 제품이 없다. 정작 필요한 것은 Philips의 스크루드라이버인데 Swiss Army 칼을 사기 위해 많은 비용을 들이는 것과 같다. 따라서, Transformation Authoring으로 툴을 구현하면 여러분의 필요에 최대한 맞출 수 있다. 여러분이 몸담고 있는 업계에 맞는 웹 서비스를 생성하는 툴에 투자할 수 있으며, 너무 일반적이거나 너무 복잡한 툴로 작업하지 않아도 된다.
교육과 사용의 용이성. 커스텀 툴을 구현할 때, Rational Software Architect 소프트웨어는 많은 것을 제공한다. Transformation Authoring은 이미 성숙한 단계에 와 있는 JET(JET는 2002년에 시작되었다.) 라고 하는 이클립스 오픈 소스 프로젝트에 기반하고 있고 XPath 같은 오픈 표준을 사용한다. 가장 중요한 점은 그래픽 사용자 인터페이스를 제공하기 때문에 사용하기가 쉽다는 점이다.
 | |
주:JET는 이전에는 Java™ Enabler Templates으로 알려졌다. 하지만, 더 이상 자바에만 국한되지 않게 되면서 JET로 불리게 되었다. XML 기반 템플릿은 이제 JET 프로그래밍 언어를 사용한 툴 구현에도 사용될 수 있다. |
|
두 가지 고려사항
지금까지의 개발 툴을 버리고 이 기술을 사용하기에 앞서 두 가지 고려해야 할 것이 있다. 다음 섹션에서 설명하겠지만, 모든 개발 툴이 Transformation Authoring 그래픽 인터페이스를 사용하여 빠르게 구현될 수 있는 것은 아니다. (적어도 XML 태그 또는 임베디드 자바 코드의 형태로 중요한 커스텀 코드는 있어야 한다.) 또한 Transformation Authoring을 효과적으로 사용하려면 마스터 레벨에서 풀어야 할 문제에 대해 이해해야 한다. 예를 들어, XML 프로퍼티 파일을 생성하는 툴을 구현해야 한다면 생성할 XML을 상세히 이해해야 한다.
따라서 Transformation Authoring은 많은 시간을 절약할 수 있게 해주고, 생산성을 향상시키면서 요구 사항를 채울 수 있다. 하지만, 모든 툴링 문제를 해결하는 것은 아니며 툴을 사용하여 문제를 해결하기 전에 당면 문제에 대해 완전히 이해해야 한다.
핵심 개념
이 기술은 Rational Software Architect 소프트웨어에 포함된 표준 툴의 기능을 확장한 것이다. Transformation Authoring 기능은 JET라고 하는 이클립스 오픈 소스 기술에 기반하고 있다. (참고자료).
그림 1에서 보듯, Transformation Authoring으로 툴을 구현하기 전에, 여러분이 필요로 하는 툴의 특징을 파악해야 한다. 즉, 해결해야 하는 문제를 명확히 정의해야 한다는 의미이다. Transformation Authoring을 사용하여 빠르게 만들 수 있는 두 가지 유형의 툴이 있다.
-
파일을 생성하는 툴. Transformation Authoring을 사용하여 어떤 유형의 파일 컬렉션이든 생성할 수 있는 툴을 빠르게 개발할 수 있다. 여기에는 특정 언어로 된 소스 코드, XML 파일, 심지어는 Java 2 Platform, Enterprise Edition (J2EE) 프로젝트까지 포함되어 있다. 예를 들어, 일련의 워크플로우 프로세스들이 매우 비슷하고 수가 많다면 이들을 자동으로 생성하는 툴을 구현할 수 있다. 보다 구체적으로는 IBM WebSphere Process Server용 Business Process Execution Language (BPEL) 비즈니스 프로세스 프로젝트를 생성하는 툴을 만들 수 있다. 따라서 하나씩 직접 구현할 필요는 없다.
-
다른 파일 구조나 파일 포맷으로 파일을 변형하는 툴. 변형을 수행하는 툴을 만들 수 있다. XSLT에 익숙하다면, JET 템플릿은 하나의 파일 포맷을 또 다른 파일 포맷으로 변형할 수 있고, 이는 마치 XSL 스타일시트가 하는 방식과 비슷하다. 차이점은 XSLT는 기본적으로 프로그래밍 언어이지만, Transformation Authoring은 시각적 인터페이스를 갖고 있는 모형 분석(exemplar analysis)이라고 하는 프로세스를 사용한다는 점이다. 게다가, Transformation Authoring은 바이너리를 포함하여 어떤 파일 유형이든 생성할 수 있기 때문에 더 큰 규모에서 파일 구조를 만들 수 있다. Java 2 Platform, Enterprise Edition (J2EE) 유틸리티 자바 압축 파일 (JAR)과 엔터프라이즈 애플리케이션 프로젝트(EAR) 같은 이클립스 워크스페이스에 나타날 수 있는 어떤 것이든 만들 수 있다.
그렇다고 해서 모든 문제들이 Transformation Authoring을 사용하여 해결되는 것은 아니다. 그나마, 파일 구성물이나 소스 코드를 생성하는 것, 또는 파일을 또 다른 포맷으로 변환하는 기능이 없었다면 쓸모가 없었을 것이다. 다음은 두 가지 예제는 그렇게 단순하지 않다.
-
빌드 툴. Apache Ant 같은 빌드 스크립트는 파일 시스템, 컴파일러, 소스 컨트롤 시스템 호출 같은 외부 호출을 수행한다. Transformation Authoring의 일부인 JET 템플릿이 외부 호출을 수행할 수 있지만, 이들의 목적은 이러한 유형의 컨트롤 로직이 아닌 변형이다.
-
시각적 에디터. 입력을 받아들여서 이클립스 워크스페이스로 결과를 만들어 내는 엔진이다. 바로 이것 때문에 전통적인 이클립스 플러그인 개발이 시각적 에디터 생성에 더 잘 맞는다.
그림 1을 보면, 어떤 문제를 해결해야 하는지를 파악한 후에, 다음 단계는 모형(exemplar)을 만드는 것이다. 모형은 문제에 대한 예제 솔루션이라고 할 수 있다. 예를 들어, 여러분 기업의 웹 포탈의 룩앤필에 순응하는 포틀릿을 생성하는 툴을 구현해야 한다면 모형으로서 포틀릿 예제로 시작해야 한다. 모형은 여러분 워크스페이스에 있는 파일 컬렉션이 될 수 있다. 하나의 XML 파일이나 12 개의 자바 클래스를 가진 폴더가 모형이 될 수 있다. 단, 이들은 여러분이 궁극적으로 만들고자 하는 툴을 나타낼 수 있어야 한다.
주: 고급 사용자라면 이 단계를 건너뛰고, 모형 없이 입력 모델과 JET 템플릿을 직접 만들 수 있지만, 고급 사용자라 할지라도, 모형 분석 과정은 시간 절약에 도움이 된다.
그림 1. Transformation Authoring 프로세스
워크스페이스에 모형이 생겼다면 다음 단계는 JET Transformation Authoring 프로젝트를 생성할 차례이다. 이 프로젝트에서는 모형 분석을 수행할 수 있는데, 이는 모형에서 나오는 툴의 아웃풋 중에서 어떤 것을 똑같이 유지해야 하고, 어떤 것을 수정해야 하는지를 알려주는 프로세스이다. 예를 들어, 자바 클래스를 생성하는 툴을 구현해야 한다면 그러한 객체의 이름들이 툴에 하드 코딩 하지 않을 것이다. 대신, 툴에 입력을 제공하여 사용하고자 하는 클래스 이름을 설정할 수 있다. 이는 모형 분석 과정에서 수행된다.
모형 분석의 결과는 입력 모델(input model)과 JET 템플릿(JET templates)이다. (실제로, 다른 많은 파일들도 생성되지만, 여러분이 알아야 할 것은 이 두 가지이다.) 툴에 대한 입력 모델은 XML 스키마, Eclipse Modeling Framework (EMF) Ecore Model, UML 모델을 포함하여 기능적으로 동등한 여러 폼들을 취할 수 있다. 따라서, XML 스키마 입력 모델을 사용하여 임의의 폴더와 빈 파일을 만드는 툴을 생성하고자 한다면 툴에 대한 입력은 다음과 같을 것이다. (Listing 1)
Listing 1. 입력 예제
<root>
<folder name="bozo-folder">
<file name="im-an-empty-file1.txt"/>
</folder>
<folder name="blueberry-folder">
<file name="im-an-empty-file2.txt"/>
<file name="im-an-empty-file3.txt"/>
</folder>
</root>
|
JET 템플릿 역시 모형 분석 프로세스의 일부로 만들어진다. 처음에는, 이들은 모형에 있는 파일들의 복제들이다. 따라서, 모형에 Book.java 파일을 제공한다면, 모형 분석은 이에 상응하는 Book.java.jet 파일을 만들어 낼 것이다. JET 템플릿을 XPath 1.0(참고자료)에 기반하여 JET 태그로 꾸밀 수 있다. 이 태그는 어떤 것이 정적이어야 하고, 툴에 의해서 동적으로 수정될 것은 무엇인지를 구별한다. 그림 1에서는 Edit Templates 단계이다. 이 글 후반에 Pojo 데이터베이스 예제에서 이 부분을 상세히 설명하도록 하겠다.
템플릿 편집을 끝마친 후에, Transformation Authoring 프로젝트는 그림 2와 같이 커스터마이징 된, 재사용 가능한 툴이 된다. 입력 모델에 순응하는 입력을 사용하여 JET 변형을 수행할 수 있다.
그림 2. 커스텀 툴 사용 모습
이제는, 간단한 데이터베이스 액세스 구현 예제를 통해 모형 분석 프로세스에 대해 설명하도록 하겠다.
전제 조건
표준 Rational Software Architect 7.0 외에도, Transformation Authoring 기능이 실행되어야 한다. (그림 3) 이것이 설치되었는지를 확인하려면, Microsoft® Windows에서 Start > Programs > IBM Installation Manager의 Modify Packages를 선택한다.
그림 3. Transformation Authoring 기능 추가하기
Pojo 데이터베이스 예제
이 섹션에서는 Transformation Authoring으로 툴을 구현하는 예제를 설명하겠다. 여러분이 구현하고자 하는 툴에 의해서 해결될 문제는 대형 애플리케이션 내에서 일관성 있는 데이터베이스 액세스이다. 객체 지향 언어로 데이터베이스에 액세스 할 때 데이터베이스 테이블을 객체로 매핑해야 하며, 일반적인 패턴은 Database Access Object (DAO) 패턴(참고자료)이다. 이 패턴은 객체에 대한 테이블(table-per-object) 매핑을 수행하는데, 여기에서, 각 테이블은 상응하는 객체 유형을 갖고 있다. 하지만, 데이터베이스 테이블이 많이 있을 경우, 각 테이블에 대해 상응하는 객체를 작성하기란 여간 성가신 일이 아닐 수 없다. 자바의 경우, 많은 자바 빈 또는 plain old Java object (Pojo)와 수 많은 빈 프로퍼티를 작성해야 한다. 이 예제 툴의 목적은 Pojo 데이터베이스를 만드는 것이다. 전체 개발팀이 표준 툴을 사용하여 데이터베이스 액세스 객체를 만들 수 있기 때문에 조직 전반에 걸쳐 일관성이 생긴다.
주: 물론, Apache iBatis와 Java Persistence API 같이, 이러한 유형의 객체 관계형 매핑 문제를 해결하는 훨씬 더 나은 툴들도 있다. 이 예제에서는 이해하기 쉽도록 단순한 툴을 선택했지만 이들도 충분히 유용하다.
앞서 언급했듯이, 툴 구현을 시작하려면 모형이 필요하다. 즉, 해당 툴로 무엇을 만들어 내야 할 것인지에 대한 모형이 필요한 것이다. 그림 4는 이 예제의 모형이 되는 자바 객체 모습이다. 이것은 관계형 데이터베이스의 고객 테이블의 그것과 상응한다.
그림 4. 예제에 사용되는 Pojo 모형
그림 5는 Transformation Authoring 프로세스를 보여주고 있다. Rational Software Architect 워크스페이스의 Web 프로젝트로 시작하는데, 여기에는 모형으로서 고객 Pojo가 포함되어 있다. 대부분의 예제는 모형 분석 과정을 통해 데이터베이스 Pojo 생성 툴을 만든다. 툴이 완성되면 XML 파일을 수정하고 이를 실행하여 Web 프로젝트와 캡슐화 된 데이터베이스 Pojo를 만들 수 있다.
그림 5. Transformation Authoring 프로세스
모형 만들기
이 섹션에서는 이 예제의 모형이 되는 Web 프로젝트를 반입하는 과정을 설명한다. 또한, Pojo와 Web 프로젝트 설정을 보다 상세히 살펴볼 것이다.
- Web perspective에서 Rational Software Architect를 연다.
-
File > Import... > Other > Project Interchange 순으로 선택하고 Exampleexemplar.zip 파일을 반입한다.
- Web Project를 분석한다.
J2EE Web 프로젝트에는 하나의 자바 빈 또는 CustomerDAO (Listing 2)라고 하는 Pojo가 포함되어 있다. Pojo는 여러 개의 빈 프로퍼티와, 기본 키를 사용하여 데이터베이스에서 고객을 쿼리하여 CustomerDAO의 인스턴스를 리턴하는 retrieveCustomer라고 하는 정적 메소드를 갖고 있다.
Listing 2. CustomerDAO Pojo
public class CustomerDAO {
/* constants */
private static String SQL = "SELECT CUSTOMER FROM ACME.DB WHERE SOCIAL = ?"; [1]
private static String DATASOURCE = "java:comp/env/jdbc/ACMEDataSource"; [2]
/* attributes */
private int social;
private String name;
private Date joined;
/* getters and setters */
public int getSocial() { return social; }
public void setSocial(int social) { this.social = social; }
public Date getDateJoined() { return joined; }
public void setDateJoined(Date joined) { this.joined = joined; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
/* constructor */
public CustomerDAO(int social, String name, Date joined) {
setSocial(social);
setName(name);
setDateJoined(joined);
}
/* DAO method to retrieve a customer from the database */ [3]
public static CustomerDAO retrieveCustomer(int social) throws ServletException {
CustomerDAO customer = null;
try {
// execute database query
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup(DATASOURCE);
Connection conn = ds.getConnection();
PreparedStatement stmt = conn.prepareStatement(SQL);
stmt.setInt(1, social);
stmt.execute();
ResultSet result = stmt.getResultSet();
// create and populate CustomerDAO object
customer = new CustomerDAO(result.getInt(1), result.getString(2), result.getDate(3));
} catch(NamingException ne) {
throw new ServletException(ne);
} catch(SQLException sqle) {
throw new ServletException(sqle);
}
return customer;
}
}
|
Listing 2에서 숫자로 표시한 부분을 주목해 보자.
- 이 클래스의 위에 있는 상수 문자열은 고객을 검색하는 SQL 쿼리를 저장하는데 사용된다.
- 상수 문자열은 JDBC 데이터 소스에 대한 콘텍스트 레퍼런스를 저장하는데 사용된다.
- 데이터베이스에서 고객을 검색하는 정적 메소드.
DatabasePojo/WebContent/WEB-INF/ 밑에 있는 web.xml을 더블 클릭하고, References 탭을 선택한다. Web 프로젝트용 Java® Database Connectivity (JDBC) 데이터 소스에 대한 외부 레퍼런스가 있다. (그림 6) 이 리소스 레퍼런스는 다음 섹션에서 중요한 역할을 한다.
그림 6. JDBC 데이터 소스 리소스 레퍼런스
모형 분석 프로젝트 만들기
이 섹션에서는 Transformation Authoring 프로젝트와 모형 분석 프로젝트를 만드는 방법을 설명한다. 이 과정에서, 툴에 대한 입력을 정의할 XML 스키마를 만들 것이다. 또한, 툴을 설정하여 아웃풋의 디렉토리 구조와 파일 이름을 만들 것이다. DatabasePojo 같은 디렉토리 이름 또는 모형에서 Customer로 시작하는 파일 이름 같은 디렉토리 이름은 하드 코딩 하지 않겠지만 툴의 사용자에 의해 제공된 입력에서 온 것들이다.
-
모형 분석 프로젝트를 만든다.
-
DatabasePojo Web Project를 오른쪽 클릭하고, New > Other > Transformation Authoring > EMFT JET Project with exemplar Authoring을 선택한다.
- 프로젝트 이름에
MyExamplarAnalysis를 입력하고, Finish를 선택한다.
-
입력 모델 유형과 애트리뷰트를 만든다.
-
root를 오른쪽 클릭하고 New > Type을 선택하여
war라는 이름을 정한다.
-
war를 오른쪽 클릭하고 New > Attribute를 선택하여
datasourceJNDI라고 이름을 정한다.
- 필요한 만큼 유형과 애트리뷰트를 만들어서 오른 편에 디렉토리 구조(트리)를 만든다. (그림 7)
그림 7. 입력 모델의 정의
그림 7의 오른 편은 이 툴의 입력 모델을 나타낸다. 상응하는 XML 스키마는 MyexemplarAnlysis/schema.xsd 파일에 있다. 표 1에서는 입력 모델의 각 유형과 애트리뷰트의 목적을 설명하고 있다.
표 1. 입력 모델 설명
| 이름 | 설명 |
|---|
|
root
| Transformation Authoring을 사용하여 생성된 모든 입력 모델에 대한 기본 루트(root) 유형이다. | |
war
| 웹 압축 파일(war)을 의미하는데, J2EE Web 프로젝트용 압축 포맷이다. 사용자들은 입력 모델에서 원하는 만큼의 WAR 노드를 지정할 수 있고, 이것은 Web 프로젝트의 아웃풋이 된다. | | datasourceJNDI | 툴에 의해 생성된 Web 프로젝트는 Java™ Naming and Directory Interface (JNDI) 이름으로 지정된 다른 JDBC 데이터 소스를 사용할 수 있다. 이 모형의 경우 jdbc/ACMEDataSource이다. | | name | Web 프로젝트의 이름이다. | |
daoBean
| 사용자는 해당 Web 프로젝트용 툴에 의해서 생성될 수 있는 DAO 자바 빈의 수를 지정할 수 있다. | | key | 사용자는 기본 키 애트리뷰트의 이름을 입력할 수 있다. (이 예제에서는 기본 키가 하나의 애트리뷰트로 구성되었다고 간주한다.) | | name | DAO 자바 빈에 사용될 이름이다. | | SQL | 데이터베이스로부터 빈 프로퍼티를 내보내는데 사용되는 SQL 쿼리 텍스트이다. | |
beanProperty
| 사용자는 빈을 위한 프로퍼티를 지정할 수 있다. | | name | 프로퍼티 이름(소문자) | | type | 프로퍼티의 자바 유형 |
이것은 입력 모델의 예제일 뿐이다. 언제라도 수정될 수 있다. 예를 들어, 이 예제를 완료한 후에, package 애트리뷰트를 daoBean에 추가하여 사용자들이 각 빈에 사용될 자바 패키지를 지정할 수 있도록 한다.
-
Web Project 폴더에 네이밍을 설정한다.
-
DatabasePojo 폴더를 오른쪽에 있는 war 유형으로 가져온다. (그림 8)
-
Create Project: DatabasePojo를 선택한 다음 Properties 탭을 선택한다.
-
*name 필드의 DatabasePojo에서 Database text 를 오른쪽 클릭하고 Replace with
Model Reference...를 선택한다.
- war 유형 밑에 있는 name 애트리뷰트를 선택한다.
그림 8. Web 프로젝트 이름
-
Pojo 자바 클래스용 네이밍 및 폴더 구조를 설정한다.
-
CustomerDAO.java를 daoBean으로 가져온다. (그림 9)
-
Create File: CustomerDAO를 선택한 다음 Properties 탭을 선택한다.
-
*path 필드에서, Database를 오른쪽 클릭하고 Replace with Model Reference...를 선택한 다음, 이것을
the name attribute under the war type으로 대체한다.
- 마찬가지로 Customer text from CustomerDAO를
the name attribute under the daoBean type으로 대체한다.
그림 9. Pojo 경로와 파일 이름
-
파일에 대한 네이밍 및 폴더 구조를 설정한다.
-
그림 10의 왼쪽 편에서 강조된 파일들을 오른쪽의 war type으로 가져온다.
-
Create File: .project를 선택한 다음 Properties 탭을 선택한다.
-
*path 필드에서, Database 텍스트를
the name attribute under the war type으로 대체한다. (그림 11)
- 여러분이 복사했던 나머지 여덟 개의 파일에 대해서도 이 단계를 반복한다.
그림 10. 나머지 Web 프로젝트 파일 설정
그림 11. .project 파일의 경로
JET 템플릿 수정하기
이 시점에서, 여러분의 툴은 입력 모델에 기반하여 올바른 폴더와 파일 이름 구조를 만드는 방법에 대해서는 알고 있지만, 파일의 내용을 수정하는 방법은 모르고 있다. 이 섹션에서는, 모형에 있는 파일에 기반하여 템플릿을 편집하여 무엇을 정적으로 남겨두고, 사용자 입력에 기반해야 할 텍스트가 무엇인지를 설정한다.
초기 JET 템플릿을 생성하려면 Transformation Authoring 프로젝트를 업데이트 해야 한다.
- 입력 모델 패널을 오른쪽 클릭하고 Update Project를 선택한다. (그림 12)
그림 12. Update project
-
MyexemplarAnalysis 프로젝트를 분석해 보면, templates 밑에 여러 개의 새로운 파일들이 생성되었음을 알 수 있다. (그림 13).
그림 13. JET 템플릿
이 단계에서, 템플릿들은 모형 프로젝트에 있는 파일들의 복제 형태로 제공된다. web.xml.jet 과 CustomerDAO.java.jet 템플릿으로 작업하게 될 것이며, 입력 모델에 기반하여 툴에서 수정할 텍스트가 포함되어 있다. 나머지 파일 대부분이 Web 프로젝트 아웃풋으로 복사될 것이다.
web.xml.jet 템플릿에서 두 가지를 수정해야 한다. 먼저, 프로젝트의 이름이 <display-name>DatabasePojo</display-name>으로 하드 코딩 되어 있다. Database는 파란 색으로 밑줄이 그어 있다. Rational Software Architect는 Database를 입력 모델에 있는 WAR 이름 애트리뷰트로 수정해야 한다는 것을 자동으로 탐지하기 때문에 직접 편집할 필요 없이 수정이 된다.
-
디스플레이 이름을 일반화 하기 위해 web.xml 템플릿을 편집한다.
-
MyexemplarAnalysis/templates/war/web.xml.jet를 연다.
-
Problems 탭을 선택한다.
- 스크롤을 내려 web.xml.jet에 상응하는 Info 아이템을 선택한다. (그림 14)
- 오른쪽 클릭하여 Quick Fix를 선택하고 OK를 클릭한다.
그림 14. Rational Software Architect
두 번째로 수정해야 할 것은 JDBC 데이터 소스의 이름이다. 현재, 이것은 jdbc/ACMEDataSource로 하드 코딩 되어 있다. 이것은 자동으로 탐지되지 않기 때문에, 입력 모델에서 어떤 애트리뷰트를 수정할 것인지를 지정해야 한다.
-
JDBC Datasource JDNI 이름을 일반화하기 위해 web.xml 템플릿을 편집한다.
-
jdbc/ACMEDataSource 텍스트를 선택한다.
- 오른쪽 클릭하여 Replace with Model Reference...를 선택한다.
- 이것을 WAR 유형 밑에 있는
the datasourceJNDI 애트리뷰트로 대체한다.
결과 web.xml.jet 템플릿은 Listing 3과 같다.
Listing 3. web.xml.jet 템플릿
<web-app id="WebApp_ID" version="2.4">
<display-name>
<c:get select="$war/@name" />Pojo
</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<resource-ref id="ResourceRef_1164745141546">
<description></description>
<res-ref-name>
<c:get select="$war/@datasourceJNDI" />
</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
</web-app>
|
나머지 섹션에서는 CustomerDAO.java.jet 템플릿을 수정하는 방법을 설명하도록 하겠다. 특정 텍스트를 태그로 대체하여 Customer 툴이 실행될 때 입력 모델에서 검색될 수 있도록 한다. 특히, Customer 또는, social 또는 joined 같은 자바 빈 프로퍼티들을 나타내는 텍스트를 대체해야 한다.
Customer 템플릿을 열면, Rational Software Architect에는 이미 많은 텍스트에 밑줄이 그어져 있는 것을 보게 된다. 이는 무엇이 대체되어야 하는지가 이미 탐지되었다는 것을 나타낸다. 이 모든 권고를 수락하는 것부터 시작한다.
-
나머지 Info를 사용하여 텍스트를 태그로 대체한다.
-
MyexemplarAnalysis/templates/daoBean/CustomerDAO.java.jet를 연다.
-
Problems 탭을 선택한다.
- CustomerDAO.java.jet 리소스용 first Info item을 오른쪽 클릭한다.
-
Quick Fix > Replace all instances를 선택하고(그림 15) OK를 클릭한다.
그림 15. Customer 템플릿 내에서 모든 제안들 수락하기
- 몇 가지 제안들은 Problems 탭에 남아있다. 계속 진행하여 이것 역시도 수락하라.
Customer 템플릿은 정확히 Listing 4와 같다. 하지만 여전히 모형에서 온 하드 코딩 된 정보들이 많이 있고, 이들은 입력 모델과 동기화 될 수 있도록 수정되어야 한다. 예를 들어, 고객에 대한 SQL 쿼리는 여전히 하드 코딩 되어 있고, social, name, joined 프로퍼티와 관련된 정보 역시도 마찬가지다.
Listing 4. Customer 템플릿
public class <c:get select="$daoBean/@name" />DAO {
/* constants */
private static String SQL =
"SELECT CUSTOMER FROM ACME.DB WHERE SOCIAL = ?";
private static String DATASOURCE =
"java:comp/env/<c:get select="$war/@datasourceJNDI" />";
/* attributes */
private int social;
private String name;
private Date joined;
/* getters and setters */
public int getSocial() { return social; }
public void setSocial(int social) { this.social = social; }
public Date getDateJoined() { return joined; }
public void setDateJoined(Date joined) { this.joined = joined; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
/* constructor */
public <c:get select="$daoBean/@name" />DAO
(int social, String name, Date joined) {
setSocial(social);
setName(name);
setDateJoined(joined);
}
/* DAO method to retrieve a customer from the database */
public static <c:get select="$daoBean/@name" />DAO
retrieve<c:get select="$daoBean/@name" />
(int social) throws ServletException {
<c:get select="$daoBean/@name" />DAO customer = null;
try {
// execute database query
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup(DATASOURCE);
Connection conn = ds.getConnection();
PreparedStatement stmt = conn.prepareStatement(SQL);
stmt.setInt(1, social);
stmt.execute();
ResultSet result = stmt.getResultSet();
// create and populate <c:get select="$daoBean/@name" />DAO object
customer = new <c:get select="$daoBean/@name" />DAO
(result.getInt(1), result.getString(2), result.getDate(3));
} catch(NamingException ne) {
throw new ServletException(ne);
} catch(SQLException sqle) {
throw new ServletException(sqle);
}
return customer;
}
}
|
-
SQL 쿼리 스트링을 일반화 한다.
- SELECT CUSTOMER FROM ACME.DB WHERE SOCIAL = ? 텍스트를 선택한다.
- 오른쪽 클릭하여, 이것을 입력 모델에 있는
the SQL 애트리뷰트로 대체한다.
Attributes 섹션을 보면 입력 모델에서의 단순한 대체로는 더 이상 충분하지 않음을 알게 된다. 이유는 사용자가 Pojo에 얼마나 많은 프로퍼티들을 제공할지 모르기 때문이다. 해결책은 툴 사용자가 제공한 빈 프로퍼티에 JET <c:iterate/> 태그를 사용하는 것이다.
-
social, name, joined 애트리뷰트를 <c:iterate/> 태그로 대체한다. (Listing 5)
Listing 5. Attributes 섹션 수정
/* attributes */
<c:iterate select="$daoBean/beanProperty" var="prop">
private <c:get select="$prop/@type" /> <c:get select="$prop/@name" />;
</c:iterate>
|
get/set 메소드 섹션을 구현하는 것은 또 다른 문제이다. 이번에는 iterate 태그를 사용해야 하지만, 문제는 get 메소드의 경우 프로퍼티 이름의 첫 문자는 대문자로 해야 한다는 점이다. 예를 들어, 사용자가 빈 프로퍼티 이름에 foo 를 입력하면, getFoo()를 구현해야 한다. 해결책은 uppercaseFirst()라고 하는 JET XPath 식을 사용하는 것이다.
-
social, name, joined get/ set 메소드를 <c:iterate/> 태그로 대체한다. (Listing 6)
Listing 6. get/set 메소드의 수정
/* getters and setters */
<c:iterate select="$daoBean/beanProperty" var="prop">
public <c:get select="$prop/@type" />
get<c:get select="uppercaseFirst($prop/@name)" />() {
return <c:get select="$prop/@name" />;
}
public void set<c:get select="uppercaseFirst($prop/@name)" />
(<c:get select="$prop/@type" /> <c:get select="$prop/@name" />){
this.<c:get select="$prop/@name" /> = <c:get select="$prop/@name" />;
}
</c:iterate>
|
생성자(constructor)의 인자 섹션에서는 iterate 태그가 필요하지만, 콤마로 분리된 리스트가 만들어져야 한다. iterate 태그의 delimiter 애트리뷰트를 사용한다.
- 생성자 시그너처
(int social, String name, Date joined) 를 수정한다. (Listing 7)
Listing 7. 생성자 시그너처 수정
(<c:iterate select="$daoBean/beanProperty" var="prop" delimiter=", ">
<c:get select="$prop/@type" /> <<c:get select="$prop/@name" />
</c:iterate>)
|
-
Listing 8처럼 생성자의 바디를 수정한다.
Listing 8. 생성자 바디 수정
<c:iterate select="$daoBean/beanProperty" var="prop">
set<c:get select="uppercaseFirst($prop/@name)" />(<c:get select="$prop/@name" />);
</c:iterate>
|
Customer 템플릿의 customer 세 개의 인스턴스가 있다. JET XPath 식, lowercaseFirst()를 사용하여 첫 번째 문자가 소문자로 생성되도록 한다.
- 세 개의 고객 인스턴스들을 <c:get select="lowercaseFirst($war/@name)" />로 바꾼다.
Customer 템플릿의 정적인 검색 메소드는 인자로서 프라이머리 키(Primary Key)를 취한다. 프라이머리 키에 대한 유형을 결정할 때에는 보다 고급의 XPath가 필요하다. 키의 이름을 먼저 체크하고 이것을 beanProperty 와 맞춘다. (그림 16)
그림 16. 기본 키 유형 결정하기
이를 수행하기 위해서는 XPath predicate를 사용해야 한다. 이 predicate에는 XPath 경로를 지정하여 특정 노드나 노드 세트가 선택되도록 하는 Boolean 문이 포함되어 있다.
-
(int social)의 검색 메소드용 인자를 수정한다. (Listing 9)
Listing 9. 검색 메소드 시그너처 수정
(<c:get select="$daoBean/beanProperty[@name
= $daoBean/@key]/@type" /> <c:get select="$daoBean/@key" />)
|
-
stmt.setInt(1, social); 텍스트를 Listing 10처럼 수정한다.
Listing 10. JDBC 문 수정
stmt.set<c:get select="uppercaseFirst($daoBean/beanProperty[@name
= $daoBean/@key]/@type)" />(1,
<c:get select="$daoBean/@key" />);
|
JDBC ResultSet에서 정보를 가져올 때 새로운 문제가 생긴다. ResultSet은 데이터 액세스에 숫자 인덱스를 필요로 하기 때문이다. (이 모형에서는 1-3을 사용했다.) 표준 XPath 함수는 현재 노드 위치를 리턴하면서, position()이라고 하는 노드 세트를 반복한다. 따라서 인덱스를 배치할 때 이 위치를 사용할 수 있다.
-
(result.getInt(1), result.getString(2), result.getDate(3)) 텍스트를 수정한다. (Listing 11)
Listing 11. JDBC ResultSet 수정
(<c:iterate select="$daoBean/beanProperty" var="prop" delimiter=", ">
result.get<c:get select=" uppercaseFirst($prop/@type)" />
(<c:get select=" position()" />)
</c:iterate>>)
|
이것으로 모형 분석과 커스텀 툴의 개발이 끝났다. 문제가 생기거나 템플릿 수정 방법이 궁금하다면 Solution.zip 프로젝트를 참조하기 바란다. (참고자료).
변형하기
모형 분석을 끝마쳤으니, 이제는 커스텀 툴을 실행할 차례이다. 입력 XML을 만들고 변형을 해본다.
-
변형하고자 하는 입력을 정의한다.
-
MyexemplarAnalysis/test.xml을 연다.
-
Listing 12에
<root/> 노드를 배치한다.
Listing 12. 입력 예제
<root xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation='schema.xsd'>
<war name='MyResult' datasourceJNDI='jdbc/MyDatasource'>
<daoBean name="Boat" sql="SELECT BOAT FROM ACME.DB WHERE ID = ?' key='id'>
<beanProperty name='d' type='int'/>
<beanProperty name='desc' type='String'/>
</daoBean>
<daoBean name='Plane' sql="SELECT PLANE FROM ACME.DB WHERE ID = ?' key='id'>
<beanProperty name='id' type='long'/>
<beanProperty name='color' type='String'/>
</daoBean>
</war>
</root>
|
-
변형을 시작한다.
-
test.xml을 오른쪽 클릭한다.
-
Run As > Input for JET Transformation 순으로 선택한다. (그림 17)
그림 17. JET 변형
Figure 18과 같이 MyResultPojo라고 하는 새로운 Web 프로젝트가 생겼다.
그림 18. 변형 결과
BoatDAO 와 PlaneDAO 라고 하는 두 개의 Pojo가 생겼다. (그림 19)
그림 19. Database Access Objects
물론, 이것은 여러분이 만들었던 커스텀 툴에서 만들어낸 유일한 아웃풋이다. 시간 날 때 XML 입력을 수정하여 다른 아웃풋도 만들어 보기 바란다. 한번에 한 개 이상의 Web 프로젝트도 만들어야 할 경우도 있다.
통합과 마이그레이션 문제 이 글에서 Transformation Authoring을 소개했고, Rational Software Architect 7.0을 사용하여 유용한 커스텀 툴을 구현하는 방법을 설명했다. 이 글을 읽고, 예제를 직접 연습해 보면 Transformation Authoring을 적용할 수 있는 방법이 떠오를 것이다. 지루한 통합 문제나 마이그레이션 문제에도 이를 적용할 수 있다. 이 경우에 커스텀 툴을 만들어서 보다 쉽고 생산적인 작업을 할 수 있다.
기사의 원문보기
다운로드 하십시오 | 설명 | 이름 | 크기 | 다운로드 방식 |
|---|
| Examples | ExampleExemplar.zip | 6KB | HTTP |
|---|
| Examples | Solution.zip | 25KB | HTTP |
|---|
참고자료 교육
제품 및 기술 얻기
토론
필자소개
기사에 대한 평가
|  |