View Javadoc
1 /* ==================================================================== 2 * License: 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * 3. The end-user documentation included with the redistribution, 17 * if any, must include the following acknowledgment: 18 * "This product includes software developed by 19 * Robert Half International (http://www.rhi.com/)." 20 * Alternately, this acknowledgment may appear in the software itself, 21 * if and wherever such third-party acknowledgments normally appear. 22 * 23 * 4. The names "Parc", "RHI", and "Robert Half International" must 24 * not be used to endorse or promote products derived from this 25 * software without prior written permission. For written 26 * permission, please contact pete.mckinstry@rhi.com. 27 * 28 * 5. Products derived from this software may not be called "PARC", 29 * nor may "PARC" appear in their name, without prior written 30 * permission of Robert Half International. 31 * 32 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 33 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 34 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 35 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 36 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 38 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 39 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 40 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 41 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 42 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 43 * SUCH DAMAGE. 44 * ==================================================================== 45 * 46 */ 47 package com.rhi.architecture.parc.adapter.jdbc; 48 49 import com.rhi.architecture.config.ConfigurationException; 50 import com.rhi.architecture.db.DBUtil; 51 import com.rhi.architecture.logging.LogUtil; 52 import com.rhi.architecture.logging.Logger; 53 import com.rhi.architecture.parc.ProcessingException; 54 import com.rhi.architecture.parc.Record; 55 import com.rhi.architecture.parc.adapter.AbstractInputAdapter; 56 import com.rhi.architecture.resource.InitializationException; 57 58 import java.sql.Connection; 59 import java.sql.PreparedStatement; 60 import java.sql.ResultSet; 61 import java.sql.SQLException; 62 import java.util.ArrayList; 63 import java.util.Collection; 64 import java.util.Properties; 65 66 import javax.sql.DataSource; 67 68 /*** 69 * Generic JDBC InputAdapter. 70 * 71 * @author Pete McKinstry 72 * @copyright 2002, Robert Half Int'l., Inc. All rights reserved. 73 * 74 * @since 1.0 75 */ 76 public abstract class JDBCInputAdapter extends AbstractInputAdapter { 77 78 private static Logger log = null; 79 80 private static String query; 81 private static final String QUERY_KEY = 82 "JDBCInputAdapter.SELECT_RECORDS"; 83 84 private static long batchSize; 85 private static final String BATCH_SIZE_KEY = 86 "JDBCInputAdapter.BATCH_SIZE"; 87 88 /*** 89 * Default Constructor 90 * 91 * @since 1.0 92 */ 93 public JDBCInputAdapter() { 94 // no-op 95 } 96 97 /*** 98 * Perform any resource initialization. 99 * 100 * @param props 101 * @throws InitializationException 102 * @since 1.0 103 */ 104 public void init(Properties props) throws InitializationException { 105 // in case AbstractInputAdapter needs to do anything... 106 super.init(props); 107 108 query = props.getProperty(QUERY_KEY, "N/A"); 109 if (query.equals("N/A")) { 110 throw new InitializationException( 111 "JDBCInputAdapter config error. " 112 + QUERY_KEY 113 + " property not found."); 114 } 115 116 String batchSizeString = props.getProperty(BATCH_SIZE_KEY, "0"); 117 try { 118 batchSize = Long.parseLong(batchSizeString); 119 } 120 catch (NumberFormatException e) { 121 throw new InitializationException( 122 "batch size not number. " + "value = " + batchSizeString, 123 e); 124 } 125 126 try { 127 log = LogUtil.getLogger(); 128 } 129 catch (ConfigurationException e) { 130 throw new InitializationException(e.toString(), e); 131 } 132 } 133 134 /*** 135 * Retrieve all the source records that should be processed by the pipeline. 136 * 137 * @return Collection - contains all the records ready for processing. 138 * @throws ProcessingException 139 * @since 1.0 140 */ 141 protected Collection loadBatch() throws ProcessingException { 142 log.debug("loadBatch()"); 143 144 ArrayList records = new ArrayList(); 145 146 Connection conn = null; 147 PreparedStatement stmt = null; 148 ResultSet rs = null; 149 try { 150 DataSource ds = DBUtil.getDataSource(); 151 if (ds == null) { 152 log.error("DataSource invalid."); 153 throw new ProcessingException("DataSource invalid."); 154 } 155 156 conn = ds.getConnection(); 157 if (conn == null) { 158 log.error("connection error."); 159 throw new ProcessingException("unable to retrieve db connection"); 160 } 161 162 stmt = prepareStatement(conn); 163 164 rs = stmt.executeQuery(); 165 while (rs.next()) { // using PK in select. only 1 row. 166 Record record = readRow(rs); 167 records.add(record); 168 } 169 log.debug("found " + records.size() + " source records"); 170 171 return records; 172 } 173 catch (SQLException e) { 174 log.error("sqlexception thrown loading record", e); 175 throw new ProcessingException(e.toString(), e); 176 } 177 catch (ConfigurationException e) { 178 log.error("configuration exception in JDBCInputAdapter", e); 179 throw new ProcessingException(e.toString(), e); 180 } 181 finally { 182 if (rs != null) { 183 try { 184 rs.close(); 185 } 186 catch (SQLException e) { 187 log.error("sqlexception closing resultset.", e); 188 } 189 } 190 if (stmt != null) { 191 try { 192 stmt.close(); 193 } 194 catch (SQLException e) { 195 log.error("sqlexception closing db statement.", e); 196 } 197 } 198 if (conn != null) { 199 try { 200 conn.close(); 201 } 202 catch (SQLException e) { 203 log.error("sqlexception closing db connection.", e); 204 } 205 } 206 } 207 208 } 209 210 /*** 211 * Allow override of Statement preparation in cases where the Input 212 * Adapters should load batches of records. 213 * 214 * @param conn 215 * @return PreparedStatement 216 * @throws SQLException 217 * 218 * @since 1.1 219 */ 220 protected PreparedStatement prepareStatement(Connection conn) 221 throws SQLException { 222 StringBuffer buf = new StringBuffer(); 223 buf.append(getQuery()); 224 if (getBatchSize() > 0) { 225 buf.append(" FETCH FIRST "); 226 buf.append(getBatchSize()); 227 buf.append(" ROWS ONLY "); 228 } 229 else if (getQuery().indexOf("FOR FETCH ONLY") == -1) { 230 buf.append(" FOR FETCH ONLY "); 231 } 232 PreparedStatement stmt = conn.prepareStatement(buf.toString()); 233 234 // bind values may be useful if you need to set parameters 235 // for your input adapter query. 236 bindValues(stmt); 237 238 return stmt; 239 } 240 241 /*** 242 * Get method for SQL - allows override by sub-classes 243 * 244 * @return String SQL 245 * 246 * @since 1.0 247 */ 248 protected String getQuery() { 249 return query; 250 } 251 252 /*** 253 * Get method for batch size - allows override by sub-classes 254 * 255 * @return long batch size 256 * 257 * @since 1.0 258 */ 259 protected long getBatchSize() { 260 return batchSize; 261 } 262 263 /*** 264 * If necessary, bind the appropriate values to the PreparedStatement. 265 * The default implemenation is empty. 266 * 267 * @param stmt - the prepared statement to be executed. 268 * @throws SQLException 269 * 270 * @since 1.1 271 */ 272 protected void bindValues(PreparedStatement stmt) throws SQLException { 273 // no op 274 } 275 276 /*** 277 * Extract the attributes from the ResultSet and return a Record object. 278 * When overriding this method, create the appropriate Record type for 279 * your interface & return it through the generic Record interface. 280 * 281 * @param rs 282 * @exception SQLException 283 * 284 * @return Record 285 * 286 * @since 1.0 287 */ 288 protected abstract Record readRow(ResultSet rs) throws SQLException; 289 290 }

This page was automatically generated by Maven