1
2
3
4
5
6
7
8
9
10
11 package org.mule.transport.jdbc;
12
13 import org.mule.DefaultMuleMessage;
14 import org.mule.api.MuleMessage;
15 import org.mule.api.construct.FlowConstruct;
16 import org.mule.api.endpoint.InboundEndpoint;
17 import org.mule.api.lifecycle.CreateException;
18 import org.mule.api.transaction.Transaction;
19 import org.mule.api.transport.Connector;
20 import org.mule.transaction.TransactionCoordination;
21 import org.mule.transaction.XaTransactionFactory;
22 import org.mule.transport.TransactedPollingMessageReceiver;
23 import org.mule.transport.jdbc.i18n.JdbcMessages;
24 import org.mule.util.ArrayUtils;
25 import org.mule.util.MapUtils;
26
27 import java.sql.Connection;
28 import java.util.ArrayList;
29 import java.util.HashMap;
30 import java.util.List;
31
32
33 public class JdbcMessageReceiver extends TransactedPollingMessageReceiver
34 {
35
36 public static final String RECEIVE_MESSAGE_IN_TRANSCTION = "receiveMessageInTransaction";
37 public static final String RECEIVE_MESSAGES_IN_XA_TRANSCTION = "receiveMessagesInXaTransaction";
38
39 protected JdbcConnector connector;
40 protected String readStmt;
41 protected String ackStmt;
42 protected List readParams;
43 protected List ackParams;
44 public boolean receiveMessagesInXaTransaction = false;
45 private volatile boolean aggregateResult;
46
47 public JdbcMessageReceiver(Connector connector,
48 FlowConstruct flowConstruct,
49 InboundEndpoint endpoint,
50 String readStmt,
51 String ackStmt) throws CreateException
52 {
53 super(connector, flowConstruct, endpoint);
54 this.setFrequency(((JdbcConnector) connector).getPollingFrequency());
55
56 boolean transactedEndpoint = endpoint.getTransactionConfig().isTransacted();
57 boolean xaTransactedEndpoint = (transactedEndpoint &&
58 endpoint.getTransactionConfig().getFactory() instanceof XaTransactionFactory);
59
60 boolean receiveMessageInTransaction = MapUtils.getBooleanValue(endpoint.getProperties(),
61 RECEIVE_MESSAGE_IN_TRANSCTION, false);
62 this.setReceiveMessagesInTransaction(receiveMessageInTransaction && transactedEndpoint);
63 if (receiveMessageInTransaction && !transactedEndpoint)
64 {
65 logger.warn(JdbcMessages.forcePropertyNoTransaction(RECEIVE_MESSAGE_IN_TRANSCTION, "transaction"));
66 receiveMessageInTransaction = false;
67 }
68
69 receiveMessagesInXaTransaction = MapUtils.getBooleanValue(endpoint.getProperties(),
70 RECEIVE_MESSAGES_IN_XA_TRANSCTION, false);
71 if (receiveMessagesInXaTransaction && !receiveMessageInTransaction)
72 {
73 logger.warn(JdbcMessages.forceProperty(RECEIVE_MESSAGES_IN_XA_TRANSCTION, RECEIVE_MESSAGE_IN_TRANSCTION));
74 receiveMessagesInXaTransaction = false;
75 }
76 else if (receiveMessagesInXaTransaction && isReceiveMessagesInTransaction() && !xaTransactedEndpoint)
77 {
78 logger.warn(JdbcMessages.forcePropertyNoTransaction(RECEIVE_MESSAGES_IN_XA_TRANSCTION, "XA transaction"));
79 receiveMessagesInXaTransaction = false;
80 }
81
82 this.connector = (JdbcConnector) connector;
83 this.setReceiveMessagesInTransaction(endpoint.getTransactionConfig().isTransacted()
84 && !this.connector.isTransactionPerMessage());
85
86 this.readParams = new ArrayList();
87 this.readStmt = this.connector.parseStatement(readStmt, this.readParams);
88 this.ackParams = new ArrayList();
89 this.ackStmt = this.connector.parseStatement(ackStmt, this.ackParams);
90 }
91
92 @Override
93 protected void doDispose()
94 {
95
96 }
97
98 @Override
99 protected void doConnect() throws Exception
100 {
101
102 }
103
104 @Override
105 protected void doDisconnect() throws Exception
106 {
107
108 }
109
110 @Override
111 public void processMessage(Object message) throws Exception
112 {
113 Connection con = null;
114 Transaction tx = TransactionCoordination.getInstance().getTransaction();
115 try
116 {
117 con = this.connector.getConnection();
118 MuleMessage muleMessage = createMuleMessage(message, endpoint.getEncoding());
119 if (this.ackStmt != null)
120 {
121 if (aggregateResult)
122 {
123 List rows = (List) message;
124 Object[][] paramValuesArray = new Object[rows.size()][];
125
126 HashMap record;
127 for (int i = 0; i < rows.size(); i++)
128 {
129 record = (HashMap) rows.get(i);
130 paramValuesArray[i] = connector.getParams(endpoint, this.ackParams, new DefaultMuleMessage(record, connector.getMuleContext()), this.endpoint.getEndpointURI().getAddress());
131 }
132 if (logger.isDebugEnabled())
133 {
134 logger.debug("SQL UPDATE: " + ackStmt + ", params = " + ArrayUtils.toString(ackParams));
135 }
136 int[] nbRows = connector.getQueryRunnerFor(endpoint).batch(con, this.ackStmt, paramValuesArray);
137 if (nbRows[0] == 0)
138 {
139 logger.warn(".ack statement did not update any rows");
140 }
141
142 aggregateResult = false;
143 }
144 else
145 {
146 Object[] paramValues = connector.getParams(endpoint, this.ackParams, muleMessage, this.endpoint.getEndpointURI().getAddress());
147 if (logger.isDebugEnabled())
148 {
149 logger.debug("SQL UPDATE: " + ackStmt + ", params = " + ArrayUtils.toString(paramValues));
150 }
151 int nbRows = connector.getQueryRunnerFor(endpoint).update(con, this.ackStmt, paramValues);
152 if (nbRows == 0)
153 {
154 logger.warn(".ack statement did not update any rows");
155 }
156 }
157 }
158 routeMessage(muleMessage);
159
160 }
161 catch (Exception ex)
162 {
163 if (tx != null)
164 {
165 tx.setRollbackOnly();
166 }
167
168
169 throw ex;
170 }
171 finally
172 {
173 if (tx == null || tx.isXA())
174 {
175
176
177
178
179
180
181
182
183
184
185
186 JdbcUtils.close(con);
187 }
188 }
189 }
190
191 @Override
192 public List<MuleMessage> getMessages() throws Exception
193 {
194 Connection con = null;
195 try
196 {
197 con = this.connector.getConnection();
198
199 Object[] readParams = connector.getParams(endpoint, this.readParams, null, this.endpoint.getEndpointURI().getAddress());
200 if (logger.isDebugEnabled())
201 {
202 logger.debug("SQL QUERY: " + readStmt + ", params = " + ArrayUtils.toString(readParams));
203 }
204 Object results = connector.getQueryRunnerFor(endpoint).query(con, this.readStmt, readParams,
205 connector.getResultSetHandler());
206
207 List resultList = (List) results;
208 if (resultList != null && resultList.size() > 1 && isReceiveMessagesInTransaction() && !receiveMessagesInXaTransaction)
209 {
210 aggregateResult = true;
211 logger.warn(JdbcMessages.moreThanOneMessageInTransaction(RECEIVE_MESSAGE_IN_TRANSCTION, RECEIVE_MESSAGES_IN_XA_TRANSCTION));
212 List singleResultList = new ArrayList(1);
213 singleResultList.add(resultList);
214 return singleResultList;
215 }
216
217 return resultList;
218 }
219 finally
220 {
221 if (TransactionCoordination.getInstance().getTransaction() == null)
222 {
223 JdbcUtils.close(con);
224 }
225 }
226 }
227
228 }