DB 조회 중재자 단점을 극복하기 위해 다른 서비스를 작성하거나 WS02 데이터 서비스 서버를 완전히 설치하지 않기 위해 기존 중재자를 확장했지만 시간 제약으로 인해 코드를 커뮤니티에 다시 제공하지 않았습니다. 다음은 업데이트 된 org.apache.synapse.mediators.db.DBLookupMediator의 코드입니다.
기본적으로 ResultSet을 XML 형식으로 변환하고 결과를 DB_SEARCH_RESULT 속성으로 설정합니다. 경주 조건에 대해서도 약간의 연마와 테스트가 필요할 것입니다.
package org.apache.synapse.mediators.db;
import org.apache.synapse.MessageContext;
import org.apache.synapse.SynapseException;
import org.apache.synapse.SynapseLog;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.io.StringWriter;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Connection;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
/**
* Simple database table lookup mediator. Designed only for read/lookup
*/
public class DBLookupMediator extends AbstractDBMediator {
public static final String DB_SEARCH_RESULTS_PROPERTY_NAME = "DB_SEARCH_RESULT";
protected void processStatement(Statement stmnt, MessageContext msgCtx) {
SynapseLog synLog = getLog(msgCtx);
// execute the prepared statement, and extract the first result row and
// set as message context properties, any results that have been specified
Connection con = null;
ResultSet rs = null;
try {
PreparedStatement ps = getPreparedStatement(stmnt, msgCtx);
con = ps.getConnection();
rs = ps.executeQuery();
// convert RS to XML
String rsXML = convertRSToXML(rs);
// add result XML to the Message Context
msgCtx.setProperty(DB_SEARCH_RESULTS_PROPERTY_NAME, rsXML);
// rollback to the beginning of ResultSet to allow standard processing
rs = ps.executeQuery();
if (rs.next()) {
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug(
"Processing the first row returned : " + stmnt.getRawStatement());
}
for (String propName : stmnt.getResultsMap().keySet()) {
String columnStr = stmnt.getResultsMap().get(propName);
Object obj;
try {
int colNum = Integer.parseInt(columnStr);
obj = rs.getObject(colNum);
} catch (NumberFormatException ignore) {
obj = rs.getObject(columnStr);
}
if (obj != null) {
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("Column : " + columnStr +
" returned value : " + obj +
" Setting this as the message property : " + propName);
}
msgCtx.setProperty(propName, obj.toString());
} else {
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebugWarn("Column : " + columnStr +
" returned null Skip setting message property : " + propName);
}
}
}
} else {
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("Statement : "
+ stmnt.getRawStatement() + " returned 0 rows");
}
}
} catch (SQLException e) {
handleException("Error executing statement : " + stmnt.getRawStatement() +
" against DataSource : " + getDSName(), e, msgCtx);
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {}
}
if (con != null) {
try {
con.close();
} catch (SQLException ignore) {}
}
}
}
private String convertRSToXML(ResultSet rs) throws SQLException {
ResultSetMetaData rsmd = rs.getMetaData();
// create XML document
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder;
Document doc = null;
try {
docBuilder = dbfac.newDocumentBuilder();
doc = docBuilder.newDocument();
} catch (ParserConfigurationException pce) {
throw new SynapseException("Failed to transform Resultset to XML", pce);
}
// create Root element
Element rootElement = doc.createElement("table");
doc.appendChild(rootElement);
while (rs.next()) {
// add Record element
Element recordElement = doc.createElement("record");
rootElement.appendChild(recordElement);
for (int i = 1; i <= rsmd.getColumnCount(); i++) {
String columnName = rsmd.getColumnName(i);
String columnValue = rs.getObject(i).toString();
// add Field element
Element fieldElement = doc.createElement("field");
fieldElement.appendChild(doc.createTextNode(columnValue));
// set Name attribute to Field element
Attr nameAttr = doc.createAttribute("name");
nameAttr.setValue(columnName);
fieldElement.setAttributeNode(nameAttr);
// add Field to Record
recordElement.appendChild(fieldElement);
}
}
//Output the XML
String xmlString = null;
try {
//set up a transformer
TransformerFactory transfac = TransformerFactory.newInstance();
Transformer trans = transfac.newTransformer();
trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
trans.setOutputProperty(OutputKeys.INDENT, "yes");
//create string from XML tree
StringWriter sw = new StringWriter();
StreamResult result = new StreamResult(sw);
DOMSource source = new DOMSource(doc);
trans.transform(source, result);
xmlString = sw.toString();
} catch (javax.xml.transform.TransformerException te) {
throw new SynapseException("Failed to transform Resultset to XML", te);
}
return xmlString;
}
}
셸란에게 감사드립니다. 저는 이것이 매우 일반적인 문제라고 생각합니다. Synapse 또는 WSO2가 대답의 옵션 2 번을 제공하지 않은 이유를 알고 있습니까? 아마도 메시지의 페이로드 (쿼리의 결과가 너무 큼)가 시냅스의 메시지 컨텍스트에 몇 가지 단점을 가질 수 있습니까 ?? 아니면 문제가되지 않습니까? 산티아고에 다시 한 번 감사드립니다. – smontico
예. 결과 집합이 너무 큰 경우 메시지 컨텍스트에 추가하는 것이 문제입니다. 아직이 JIRA 관련 내용은 개방형 상태입니다. https://issues.apache.org/jira/browse/SYNAPSE-533 제공된 솔루션은 훌륭하지 않습니다. –
네, 제가 왜 당신에게 물어 보는 거죠 ... 응답 셸란에게 고마워요! – smontico