JNDI DataSource Loading for TDD
Tomcat 등의 Servlet Container를 사용하여, 웹애플리케이션을 개발할 때, DataSource를 Servlet Container의 Context 에 JNDI Resource로 bind 하여 사용하는 경우가 많다.
test case를 실행하기 위해 JNDI remote provider 를 제공하는 application server (glassfish, jboss 등)를 사용할 수도 있으나, 이러한 것은 test의 원자성을 저해하기 때문에 test 환경 자체에서 JNDI resource를 생성할 수 있는 방법을 생각해 보았다.
Sun에서 제공하는 File System Service Provider를 이용하는 것이다. 사용법은 매우 간단하다. 단순히 naming context의 initail context factory 를 com.sun.jndi.fscontext.RefFSContextFactory 로 지정하기만 하면 된다.
다음은 간단히 만들어 본 class 이다. 이 class는 context xml 파일을 읽어서 JNDI resource를 loading해 주는 역할을 한다. test를 수행하기 전에 JNDILoader.init()을 실행 해주면 다른 작업 없이 test case를 실행시킬 수 있을 것이다.
test case를 실행하기 위해 JNDI remote provider 를 제공하는 application server (glassfish, jboss 등)를 사용할 수도 있으나, 이러한 것은 test의 원자성을 저해하기 때문에 test 환경 자체에서 JNDI resource를 생성할 수 있는 방법을 생각해 보았다.
Sun에서 제공하는 File System Service Provider를 이용하는 것이다. 사용법은 매우 간단하다. 단순히 naming context의 initail context factory 를 com.sun.jndi.fscontext.RefFSContextFactory 로 지정하기만 하면 된다.
다음은 간단히 만들어 본 class 이다. 이 class는 context xml 파일을 읽어서 JNDI resource를 loading해 주는 역할을 한다. test를 수행하기 전에 JNDILoader.init()을 실행 해주면 다른 작업 없이 test case를 실행시킬 수 있을 것이다.
package com.fguy.test;
import java.io.File;
import java.io.IOException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.log4j.Logger;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class JNDILoader {
private static final Logger LOG = Logger.getLogger(JNDILoader.class);
private static final boolean initialized = false;
private static final String CONTEXT_XML = "WebContent/META-INF/context.xml";
private JNDILoader() {
}
public static final void init() throws ParserConfigurationException,
SAXException, IOException, DOMException, NamingException {
if (!initialized) {
Context context = getNamingContext();
List resourceNames = new ArrayList();
Map> references = new HashMap>();
NodeList contextResourceNodeList = getContextResourceNodeList();
for (int i = 0; i < contextResourceNodeList.getLength(); i++) {
Node item = contextResourceNodeList.item(i);
// print comment;
if (LOG.isDebugEnabled()
&& item.getNodeType() == Node.COMMENT_NODE
&& item != null) {
LOG.debug(item.getNodeValue());
}
// register to JNDI
if ("resource".equalsIgnoreCase(item.getNodeName())
&& "javax.sql.DataSource".equals(item.getAttributes()
.getNamedItem("type").getNodeValue())) {
NamedNodeMap attributes = item.getAttributes();
String name = attributes.getNamedItem("name")
.getNodeValue();
Map reference = references.get(name);
if (reference == null) {
reference = new HashMap();
}
for (int j = 0; j < attributes.getLength(); j++) {
String n = attributes.item(j).getNodeName();
String v = attributes.item(j).getNodeValue();
if (!"name".equals(n)) {
reference.put(n, v);
}
LOG.debug(attributes.item(j));
}
resourceNames.add(name);
references.put(name, reference);
}
if ("resourceparams".equalsIgnoreCase(item.getNodeName())) {
NodeList parameters = item.getChildNodes();
String name = item.getAttributes().getNamedItem("name")
.getNodeValue();
Map reference = references.get(name);
if (reference == null) {
reference = new HashMap();
}
for (int j = 0; j < parameters.getLength(); j++) {
Node paramItem = parameters.item(j);
if ("parameter".equalsIgnoreCase(paramItem
.getNodeName())) {
NodeList children = paramItem.getChildNodes();
String n = null;
String v = null;
for (int k = 0; k < children.getLength(); k++) {
Node child = children.item(k);
if ("name"
.equalsIgnoreCase(child.getNodeName())) {
n = child.getNodeValue();
} else if ("value".equalsIgnoreCase(child
.getNodeName())) {
v = child.getNodeValue();
}
LOG.debug(child);
}
reference.put(n, v);
}
}
references.put(name, reference);
}
}
for (String name : resourceNames) {
Reference reference = new Reference("javax.sql.DataSource",
"org.apache.commons.dbcp.BasicDataSourceFactory", null);
Map referenceMap = references.get(name);
for (String key : referenceMap.keySet()) {
reference
.add(new StringRefAddr(key, referenceMap.get(key)));
}
context.rebind("java:comp/env/".concat(name), reference);
}
}
}
private static final NodeList getContextResourceNodeList()
throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document doc = docBuilder.parse(new File(CONTEXT_XML));
return doc.getFirstChild().getChildNodes();
}
private static final Context getNamingContext() throws NamingException {
System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.fscontext.RefFSContextFactory");
System.setProperty(Context.PROVIDER_URL, "file:///tmp");
return new InitialContext();
}
}
댓글
댓글 쓰기