Flex(Cairngorm) + Spring + iBATIS 연동
1)전체 아키텍처
3-Tier 구조 : Presentation(혹은 UI) Layer,Business Layer,Persistence Layer 로 구성
1.1 Presentation Layer : Flex
1.2 Business Layer : Spring(부분)
1.3 Persistence Layer : iBATIS
Flex : adobe 사의 enterprise용 presentation tier 솔루션
Cairngorm : Flex framework
Spring : layered Java/J2EE application framework
iBATIS : data mapper framework
2)환경 설정
2.1 J2EE 설정 파일 : web.xml
2.2 Flex 설정 파일 : remoting-config.xml, services-config.xml
2.3 Spring 설정 파일 : applicationContext.xml
2.4 iBATIS 설정 파일 : SqlMapConfig.xml 과 sqlmap.xml 파일들
2.1 J2EE 설정 파일 web.xml 수정 사항
//아래처럼 context-param, listener 태그를 추가한다.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
2.2.1 Flex 설정 파일 remoting-config.xml 수정 사항
//아래처럼 <factory>spring</factory> 태그를 추가하고, <source>contactService</source> 처럼 패키지 이름이 아니라,
서비스 이름을 적어준다(applicationContext.xml 파일에 해당 서비스에 맞는 자바빈즈 설정을 해준다)
<destination id="contactService">
<properties>
<factory>spring</factory>
<source>contactService</source>
</properties>
</destination>
//서비스 추가시 위 형식과 동일하게 계속 추가해준다.
2.2.2 Flex 설정 파일 services-config.xml 수정 사항
//아래처럼 factories 태그를 추가한다.
//더불어, 관련 class 파일 두개를 패키지 경로에 맞게(flex.samples.factories) 넣어준다.
// SpringFactory.class, SpringFactory$SpringFactoryInstance.class 이다.
<factories>
<factory id="spring" class="flex.samples.factories.SpringFactory"/>
</factories>
2.3 Spring 설정 파일 applicationContext.xml 수정 사항
applicationContext.xml 파일을 참고한다,그 안의 내용을 요약하면,
2.3.1 Application 설정
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location"><value>classpath:../application.properties</value></property>
</bean>
application.properties 는 jdbc 실제 정보를 입력한다.
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost/ibatis?user=root&password=mysql
jdbc.username=root
jdbc.password=mysql
2.3.2 DB Connection 설정
dataSource와 transactionManager 설정을 한다.
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName"><value>${jdbc.driverClassName}</value></property>
<property name="url"><value>${jdbc.url}</value></property>
<property name="username"><value>${jdbc.username}</value></property>
<property name="password"><value>${jdbc.password}</value></property>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource"><ref local="dataSource"/></property>
</bean>
2.3.3 iBATIS 설정
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="classpath:../SqlMapConfig.xml" />
</bean>
2.3.4 DAO 설정
Dao 인터페이스의 구현클래스 지정한다.
<bean id="contactDao" class="com.appfoundation.flexibatis.dao.ibatis.ContactDaoImpl">
<property name="dataSource"><ref local="dataSource"/></property>
<property name="sqlMapClient"><ref local="sqlMapClient"/></property>
</bean>
<bean id="mycontactDao" class="com.appfoundation.flexibatis.dao.ibatis.MyContactDaoImpl">
<property name="dataSource"><ref local="dataSource"/></property>
<property name="sqlMapClient"><ref local="sqlMapClient"/></property>
</bean>
클래스가 추가되면 위와 같은 형식으로 추가한다.
2.3.5 Flex 서비스 설정
Service 인터페이스의 구현클래스 지정한다.
<bean id="contactService" class="com.appfoundation.flexibatis.services.ContactServiceImpl">
<property name="contactDao"><ref bean="contactDao"/></property>
</bean>
<bean id="myContactService" class="com.appfoundation.flexibatis.services.MyContactServiceImpl">
<property name="mycontactDao"><ref bean="mycontactDao"/></property>
</bean>
2.3.6 sqlmapconfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<settings useStatementNamespaces="true"/>
<sqlMap resource="../sqlmaps/Contact.xml" />
<sqlMap resource="../sqlmaps/MyContact.xml"/>
</sqlMapConfig>
2.3.7 Contact.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="Contact">
<typeAlias alias="contact" type="com.appfoundation.flexibatis.domain.Contact"/>
<resultMap id="contactResult" class="contact">
<result property="objectIdentifier" column="objectidentifier"/>
<result property="name" column="name" />
<result property="businessPhone" column="business_phone"/>
<result property="mobilePhone" column="mobile_phone" />
<result property="homePhone" column="home_phone"/>
<result property="addressLine1" column="address_line1" />
<result property="addressLine2" column="address_line2"/>
<result property="addressLine3" column="address_line3"/>
<result property="city" column="city"/>
<result property="state" column="state"/>
<result property="zip" column="zip"/>
<result property="email" column="email"/>
<result property="company" column="company"/>
<result property="title" column="title"/>
<result property="responsibility" column="responsibility"/>
<result property="image" column="image"/>
<result property="department" column="department"/>
<result property="phoneExtension" column="phone_extension"/>
<result property="fax" column="fax"/>
<result property="status" column="status"/>
<result property="refferedBy" column="reffered_by"/>
<result property="country" column="country"/>
<result property="webSite" column="website"/>
</resultMap>
<sql id="contacts_table" >
contacts
</sql>
<select id="getContacts" resultMap="contactResult">
select *
from <include refid="contacts_table" />
order by name
</select>
<select id="getContact" resultMap="contactResult">
select *
from <include refid="contacts_table" />
where objectidentifier = #value#
</select>
<insert id="insertContact" parameterClass="contact" >
<selectKey resultClass="int" keyProperty="objectIdentifier">
SELECT max(objectidentifier) from contacts
</selectKey>
insert into <include refid="contacts_table"/>(objectidentifier, name, business_phone,mobile_phone, home_phone, address_line1, address_line2, address_line3,city, state, zip, email, company, title, responsibility, image,department, phone_extension, fax, status, reffered_by, country, website)
values(#objectIdentifier#+1,
#name#,
#businessPhone#,
#mobilePhone#,
#homePhone#,
#addressLine1#,
#addressLine2#,
#addressLine2#,
#city#,
#state#,
#zip#,
#email#,
#company#,
#title#,
#responsibility#,
#image#,
#department#,
#phoneExtension#,
#fax#,
#status#,
#refferedBy#,
#country#,
#webSite#)
</insert>
<update id="updateContact" parameterClass="contact">
update <include refid="contacts_table"/>
set name = #name#,
business_phone = #businessPhone#,
mobile_phone = #mobilePhone#,
home_phone = #homePhone#,
address_line1 = #addressLine1#,
address_line2 = #addressLine2#,
address_line3 = #addressLine3#,
city = #city#,
state = #state#,
zip = #zip#,
email = #email#,
company = #company#,
title = #title#,
responsibility = #responsibility#,
image = #image#,
department = #department#,
phone_extension = #phoneExtension#,
fax = #fax#,
status = #status#,
reffered_by = #refferedBy#,
country = #country#,
website = #webSite#
where objectidentifier = #objectIdentifier#
</update>
<delete id="deleteContact" parameterClass="int">
delete from <include refid="contacts_table"/> where objectidentifier = #value#
</delete>
</sqlMap>
2.3.8 실제 자바 구현 클래스
총 세 부분으로 나뉜다
domain - flex에서의 vo 클래스라고 생각하면 된다.
dao - dao 인터페이스와, 구현 클래스
service - service 인터페이스와,구현 클래스
Contact 클래스.
--------------------------------------------------
package com.appfoundation.flexibatis.domain;
import java.io.Serializable;
public class Contact implements Serializable {
int objectIdentifier;
String name;
String businessPhone;
String mobilePhone;
String homePhone;
String addressLine1;
String addressLine2;
String addressLine3;
String city;
String state;
String zip;
String email;
String company;
String title;
String responsibility;
String image;
String department;
String phoneExtension;
String fax;
String status;
String refferedBy;
String country;
String webSite;
....
셋터,겟터
//이 글 아래 참고 사이트에 가면 해당 클래스 다운받을수 있다.
--------------------------------------------------
ContactDao 클래스.
--------------------------------------------------
package com.appfoundation.flexibatis.dao;
import com.appfoundation.flexibatis.domain.Contact;
import java.util.List;
public interface ContactDao {
public List getContacts();
public int updateContact(Contact contact);
public int deleteContact(int contactKey);
public int insertContact(Contact contact);
}
--------------------------------------------------
ContactDaoImpl 클래스.
--------------------------------------------------
package com.appfoundation.flexibatis.dao.ibatis;
import java.util.List;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import org.springframework.dao.DataAccessException;
import com.appfoundation.flexibatis.domain.Contact;
import com.appfoundation.flexibatis.dao.ContactDao;
public class ContactDaoImpl extends SqlMapClientDaoSupport implements ContactDao {
//이 글 아래 주의 사항 꼭 참고!
public List getContacts() throws DataAccessException {
return getSqlMapClientTemplate().queryForList("Contact.getContacts");
}
public int insertContact(Contact contact) throws DataAccessException {
return ((Integer)getSqlMapClientTemplate().insert("Contact.insertContact", contact)).intValue();
}
public int updateContact(Contact contact) throws DataAccessException {
return ((Integer)getSqlMapClientTemplate().update("Contact.updateContact", contact)).intValue();
}
public int deleteContact(int contactKey) throws DataAccessException {
return ((Integer)getSqlMapClientTemplate().delete("Contact.deleteContact", contactKey)).intValue();
}
}
--------------------------------------------------
ContactService 클래스.
--------------------------------------------------
package com.appfoundation.flexibatis.services;
import com.appfoundation.flexibatis.domain.Contact;
import java.util.List;
public interface ContactService {
public abstract List getContacts() throws Exception;
public abstract int insertContact(Contact contact) throws Exception;
public abstract int updateContact(Contact contact) throws Exception;
public abstract int deleteContact(int contactKey) throws Exception;
}
--------------------------------------------------
ContactServiceImpl 클래스.
--------------------------------------------------
package com.appfoundation.flexibatis.services;
import com.appfoundation.flexibatis.domain.*;
import com.appfoundation.flexibatis.dao.ContactDao;
import java.util.List;
import java.io.Serializable;
public class ContactServiceImpl implements Serializable, ContactService {
// injected by Spring
ContactDao contactDao;
public ContactDao getContactDao() {
return contactDao;
}
public void setContactDao(ContactDao contactDao) {
this.contactDao = contactDao;
}
public List getContacts() throws Exception {
return contactDao.getContacts();
}
public int insertContact(Contact contact) throws Exception{
return ((Integer)contactDao.insertContact(contact));
}
public int deleteContact(int contactKey) throws Exception {
return ((Integer)contactDao.deleteContact(contactKey));
}
public int updateContact(Contact contact) throws Exception {
return ((Integer)contactDao.updateContact(contact));
}
}
--------------------------------------------------
2.3.9 MySQL 테이블 구조
# Host: localhost Database: ibatis
# ------------------------------------------------------
# Server version 5.0.27-community-nt
#
# Table structure for table contacts
#
DROP TABLE IF EXISTS `contacts`;
CREATE TABLE `contacts` (
`objectidentifier` int(11) NOT NULL,
`name` varchar(120) default NULL,
`business_phone` varchar(16) default NULL,
`mobile_phone` varchar(16) default NULL,
`home_phone` varchar(16) default NULL,
`address_line1` varchar(120) default NULL,
`address_line2` varchar(120) default NULL,
`city` varchar(45) default NULL,
`state` varchar(25) default NULL,
`zip` varchar(10) default NULL,
`email` varchar(120) default NULL,
`company` varchar(120) default NULL,
`title` varchar(45) default NULL,
`responsibility` varchar(45) default NULL,
`image` varchar(45) default NULL,
`department` varchar(45) default NULL,
`phone_extension` varchar(16) default NULL,
`fax` varchar(16) default NULL,
`status` varchar(45) default NULL,
`reffered_by` varchar(45) default NULL,
`address_line3` varchar(120) default NULL,
`country` varchar(60) default NULL,
`website` varchar(120) default NULL,
PRIMARY KEY (`objectidentifier`)
) ENGINE=InnoDB DEFAULT CHARSET=euckr;
#
# Dumping data for table contacts
#
INSERT INTO `contacts` VALUES (0,'기본값',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'def@default.com',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
INSERT INTO `contacts` VALUES (1,'양현석',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'iamyh@hitel.net',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
INSERT INTO `contacts` VALUES (2,'jjong jj',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'jjong@offton.co.kr',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
INSERT INTO `contacts` VALUES (3,'기본값',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'def@default.com',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
INSERT INTO `contacts` VALUES (4,'test',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'test@hitel.net',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
3)테스트 환경
Tomcat 5.0
Flex 3.0b,Cairngorm 2.2
Spring 2.0.6
iBATIS 2.3.0.677
MySQL 5.0
4)참고 사이트
Flex+Spring
http://coenraets.org/flex-spring
Flex+Cairngorm+Spring+iBATIS
http://www.appfoundation.com/blogs/giametta/2007/05/09/flex-spring-ibatis-caringorm-bringing-it-all-together/
바로 위 Chris Giametta가 구현한 자바 클래스 코딩을 좀 달리했다,난 SqlMapClientDaoSupport extend 해서 구현한거다.
주의)
ContactDaoImpl 클래스를 코딩할때 아래처럼 Contact.getContacts,해줘야한다
이분 블로그 처럼 getContacts 하고,다른 map 파일에서 똑같은 이름의 메소드가 있다면,아래 에러가 난다.
이 에러때문에 한참 헤맸었다.
//com.ibatis.sqlmap.client.SqlMapException: There is already a statement named getContacts in this SqlMap.
위와 관련해서 sqlmapconfig.xml 에 아래의 태그를 추가해준다.
<settings useStatementNamespaces="true"/>
public List getContacts() throws DataAccessException {
return getSqlMapClientTemplate().queryForList("Contact.getContacts");
}
3tier 각 부분별로 framework 을 적용해봤다.
그런데, 정말 중요한 질문은 이거다.
왜 Spring 을 쓰나?
왜 iBATIS 를 쓰나?
왜 Cairngorm 을 쓰나?
왜 Flex 를 쓰나?
명쾌한 자신만을 답을 가지고 있다면 이 조합이 꽤 쓸만할꺼다.
ps
지금까지 포스팅한글중에 가장 길고 정성들인것 같다.
댓글을 달아 주세요
댓글 RSS 주소 : http://iamyhs.com/tc/rss/comment/337