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