스프링에서 제공하는 메일은 다양한 형태를 지원한다.
그중에 Velocity Engine을 이용하여 Template메일을 보낼수 있다.
SpringReference를 보면서 하나씩 세팅하면서 테스트 한 결과는 다음과 같다.

VelocityEngine에 대한 xml 세팅은 다음과 같다.
<bean id="velocityEngine"
  class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
  <property name="velocityProperties">
   <props>
    <prop key="resource.loader">class</prop>
    <prop key="class.resource.loader.class">
     org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
    </prop>
   </props>
  </property>
 </bean>

이렇게 선언된 velocityEngine은
<bean id="springMailSender"
  class="com.xxx.xxxx.mail.SpringMailSender" abstract="true">
  <property name="mailSender" ref="mailSender" />
  <property name="velocityEngine" ref="velocityEngine" />
 </bean>
으로 세팅하고...
본문내용은
String mailText = VelocityEngineUtils.mergeTemplateIntoString(
     velocityEngine, "com/xxx/mail/mailContent.vm",
     new HashMap());

을 이용하여 변환한 내용을 메일로 발송하는 것이다.

그런데 위의 방법은 *.vm 파일이 클래스 패스에 있어야만 파일을 찾아서 파싱할수 있다.
일반 파일로 바꾸기 위해서는 다음과 같이 변경해야 한다.
<property name="velocityProperties">
   <props>
    <prop key="resource.loader">file</prop>
    <prop key="file.resource.loader.class">org.apache.velocity.runtime.resource.loader.FileResourceLoader
    </prop>
    <prop key="file.resource.loader.path">${webapp.root}/WEB-INF/velocity</prop>
    <prop key="file.resource.loader.cache">false</prop>
   </props>
  </property>

그런데 위의 내용중에 ${webapp.root}가 있는데... 별도의 properties를 선언해서 webapp.root를 선언해야 한다. 음... 좀 거시기 하다... 귀찮기도 하고...

그래서 다시 찾아본 결과... (영어가 짧아서 자세히 읽어보지 않으면 잘 모르고 그냥 지나치곤 한다.)

<property name="resourceLoaderPath" value="WEB-INF/velocity"/>

이거 한줄이면 다 된다. ㅎㅎㅎ

암튼 짧은 영어라도 천천히 읽어보면 답이 보인다.





How do I get dynamic DataSources with iBATIS and Spring

원제는 위와 같다... 즉 여러개의 분산Database 또는 이와 유사한 환경에서 커넥션을 상황에 맞게
다르게 해야 하는경우 Spring에서 지원하는 형식은 다음과 같다.

1. datasource를 여러개 만들어 놓고
2. 해당 DataSource의 ID를 Map 형태로 지정한다.
3. 사용자 정의 datasource 클래스를 만들고
4. 각 Dao 클래스에선 사용자 정의 datasource를 이용한다.

위의 링크에 소개된 예제는 다음과 같다.

<!--
    Pulls the VendorOne DataSource from JNDI and sets up the
    SqlMapClient for VendorOne, the other vendors look the same.
    
    I also use Spring's 2.x AOP declarative transaction management
    around each vendor's DataSource, but I'm leaving that out for this
    example.

    Also, in my case, all my SqlMapClients use the same sqlmap config.
-->
<bean id="vendorOneDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName">
        <value>java:/comp/env/jdbc/VendorOne</value>
    </property>
</bean>
<bean id="vendorOneSqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
    <property name="configLocation" value="classpath:sqlmap-config.xml"/>
    <property name="dataSource" ref="vendorOneDataSource"/>
</bean>

<!--
    Sets up the RoutingSqlMapClient with a Map of vendor specific
    SqlMapClient beans and it keyed by the VendorTypes enum.
-->
<bean id="sqlMapClient" class="com.localmatters.bo.core.util.RoutingSqlMapClient">
    <property name="targetSqlMapClients">
    <map key-type="com.localmatters.bo.core.commons.VendorTypes">
        <entry key="VendorOne" value-ref="vendorOneSqlMapClient"/>
        <entry key="VendorTwo" value-ref="vendorTwoSqlMapClient"/>
        <entry key="VendorThree" value-ref="vendorThreeSqlMapClient"/>
    </map>
    </property>
</bean>

<!--
    Creates an Abator-generated DAO bean and sets the RoutableSqlMap.
-->
<bean id="userDAO" class="com.localmatters.bo.core.nontology.dao.UserDAOImpl">
    <property name="sqlMapClient" ref="sqlMapClient"/>
</bean>

public UserDAO getUserDAO(VendorTypes vendor) {
VendorContextHolder.setVendorType(vendor);
return (UserDAO) context.getBean("userDAO");
}

UserDAO vendorOneDAO = ServiceLocator.getUserDAO(VendorTypes.VendorOne);
UserDAO vendorTwoDAO = ServiceLocator.getUserDAO(VendorTYpes.VendorTwo);
vendorOneDAO.update(vendorOneUser);
vendorTwoDAO.update(vendorTwoUser);

VendorContextHolder.set(VendorTypes.VendorOne);
    vendorDAO.update(vendorOneUser);
    VendorContextHolder.set(VendorTypes.VendorTwo);
    vendorDAO.update(vendorTwoUser);

======================== RoutingSqlMapClient.java =========================
package com.localmatters.bo.core.util;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import com.ibatis.common.util.PaginatedList;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapSession;
import com.ibatis.sqlmap.client.event.RowHandler;
import com.ibatis.sqlmap.engine.execution.SqlExecutor;
import com.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient;
import com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate;
import com.ibatis.sqlmap.engine.mapping.statement.MappedStatement;
import com.localmatters.bo.core.commons.VendorTypes;

public class RoutingSqlMapClient implements ExtendedSqlMapClient {
  private Map<VendorTypes, ExtendedSqlMapClient> targetSqlMapClients;
 
  public void flushDataCache() {
    targetSqlMapClients.get(VendorContextHolder.getVendorType()).flushDataCache();
  }
  public void flushDataCache(String cacheId) {
    targetSqlMapClients.get(VendorContextHolder.getVendorType()).flushDataCache(cacheId);
  }
  public SqlMapSession getSession() {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).getSession();
  }
  public SqlMapSession openSession() {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).openSession();
  }
  public SqlMapSession openSession(Connection conn) {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).openSession(conn);
  }
  public int delete(String id, Object parameterObject) throws SQLException {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).delete(id, parameterObject);
  }
  public int executeBatch() throws SQLException {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).executeBatch();
  }
  public Object insert(String id, Object parameterObject) throws SQLException {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).insert(id, parameterObject);
  }
  public List queryForList(String id, Object parameterObject)
      throws SQLException {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).queryForList(id, parameterObject);
  }
  public List queryForList(String id, Object parameterObject, int skip,
      int max) throws SQLException {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).queryForList(id, parameterObject, skip, max);
  }
  public Map queryForMap(String id, Object parameterObject, String keyProp)
      throws SQLException {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).queryForMap(id, parameterObject, keyProp);
  }
  public Map queryForMap(String id, Object parameterObject, String keyProp,
      String valueProp) throws SQLException {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).queryForMap(id, parameterObject, keyProp, valueProp);
  }
  public Object queryForObject(String id, Object parameterObject)
      throws SQLException {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).queryForObject(id, parameterObject);
  }
  public Object queryForObject(String id, Object parameterObject,
      Object resultObject) throws SQLException {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).queryForObject(id, parameterObject, resultObject);
  }
  public PaginatedList queryForPaginatedList(String id,
      Object parameterObject, int pageSize) throws SQLException {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).queryForPaginatedList(id, parameterObject, pageSize);
  }
  public void queryWithRowHandler(String id, Object parameterObject,
      RowHandler rowHandler) throws SQLException {
    targetSqlMapClients.get(VendorContextHolder.getVendorType()).queryWithRowHandler(id, parameterObject, rowHandler);
  }
  public void startBatch() throws SQLException {
    targetSqlMapClients.get(VendorContextHolder.getVendorType()).startBatch();
  }
  public int update(String id, Object parameterObject) throws SQLException {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).update(id, parameterObject);
  }
  public void commitTransaction() throws SQLException {
    targetSqlMapClients.get(VendorContextHolder.getVendorType()).commitTransaction();
  }
  public void endTransaction() throws SQLException {
    targetSqlMapClients.get(VendorContextHolder.getVendorType()).endTransaction();
  }
  public Connection getCurrentConnection() throws SQLException {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).getCurrentConnection();
  }
  public DataSource getDataSource() {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).getDataSource();
  }
  public Connection getUserConnection() throws SQLException {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).getUserConnection();
  }
  public void setUserConnection(Connection connnection) throws SQLException {
    targetSqlMapClients.get(VendorContextHolder.getVendorType()).setUserConnection(connnection);
  }
  public void startTransaction() throws SQLException {
    targetSqlMapClients.get(VendorContextHolder.getVendorType()).startTransaction();
  }
  public void startTransaction(int transactionIsolation) throws SQLException {
    targetSqlMapClients.get(VendorContextHolder.getVendorType()).startTransaction(transactionIsolation);
  }
  public Map<VendorTypes, ExtendedSqlMapClient> getTargetSqlMapClients() {
    return targetSqlMapClients;
  }
  public void setTargetSqlMapClients(
      Map<VendorTypes, ExtendedSqlMapClient> targetSqlMapClients) {
    this.targetSqlMapClients = targetSqlMapClients;
  }
  public SqlMapExecutorDelegate getDelegate() {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).getDelegate();
  }
  public MappedStatement getMappedStatement(String id) {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).getMappedStatement(id);
  }
  public SqlExecutor getSqlExecutor() {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).getSqlExecutor();
  }
  public boolean isEnhancementEnabled() {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).isEnhancementEnabled();
  }
  public boolean isLazyLoadingEnabled() {
    return targetSqlMapClients.get(VendorContextHolder.getVendorType()).isLazyLoadingEnabled();
  }
}


========================= VendorContextHolder.java ==================
package
com.localmatters.bo.core.util;
import org.apache.log4j.Logger; import com.localmatters.bo.core.commons.VendorTypes; public class VendorContextHolder {
 
  private static Logger log = Logger.getLogger(VendorContextHolder.class);
  private static final ThreadLocal<VendorTypes> contextHolder
    = new ThreadLocal<VendorTypes>();
  public static void setVendorType(VendorTypes vendor) {
   
    if (contextHolder.get() != null &&
        !contextHolder.get().equals(vendor)) {
      log.warn("Resetting vendor from " + contextHolder.get() + " to "
          + vendor);
    }
   
    contextHolder.set(vendor);
  }
  public static VendorTypes getVendorType() {
   
    if (contextHolder.get() == null) {
      return VendorTypes.LocalMatters;
    }
   
    return (VendorTypes) contextHolder.get();
  }
  public static void clearVendorType() {
    contextHolder.remove();
  }
}

===================== VendorFilter.java ==========================
package com.localmatters.bo.core.nontology.servlet;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;
import com.localmatters.bo.core.commons.VendorTypes;
import com.localmatters.bo.core.util.VendorContextHolder;
public class VendorFilter implements Filter {
  public static final String VENDOR_PARAM = "vendor";
 
  Logger log = Logger.getLogger(VendorFilter.class);
 
  public void destroy() {
  }
  public void doFilter(ServletRequest req, ServletResponse resp,
      FilterChain chain) throws IOException, ServletException {
    log.debug("Handling request");
   
    HttpServletRequest httpReq = (HttpServletRequest) req;
   
    if (req.getParameter(VENDOR_PARAM) == null) {
      throw new RuntimeException("vendor parameter must be specified");
    }
    VendorContextHolder.setVendorType(VendorTypes.valueOf(req.getParameter(VENDOR_PARAM)));
    log.debug("Setting vendor context to : " + VendorContextHolder.getVendorType());
    chain.doFilter(req, resp);
   
    log.debug("Clearing vendor");
    VendorContextHolder.clearVendorType();
  }
  public void init(FilterConfig arg0) throws ServletException {
    log.info("Initializing VendorFilter");
  }
}

============================= VendorTypes.java ==================
package
com.localmatters.bo.core.commons; public enum VendorTypes { VendorOne, VendorTwo, VendorThree }




또다른 링크 : Dynamic DataSource Routing

위의 내용은 interface21의 팀블로그에 나온 내용임.

















Spring관련 영문자료 사이트

Posted 2007. 11. 28. 16:24


« PREV : 1 : 2 : 3 : 4 : 5 : NEXT »