/** * Initializes this object. * * @param key Property-key to use for locating initialization properties. * @param type Property-type to use for locating initialization properties. * @exception ProcessingException when initialization fails */ public void initialize(String key, String type) throws ProcessingException { super.initialize(key, type); StringBuffer errorBuf = new StringBuffer(); // serverName = getRequiredProperty(SERVER_NAME_PROP, errorBuf); headerLocation = getPropertyValue(NF_HEADER_LOCATION_PROP); isAsyncLocation = getPropertyValue(IS_ASYNCHRONOUS_LOCATION_PROP); orbAgentAddr = getPropertyValue(ORB_AGENT_ADDR_PROP); orbAgentPort = getPropertyValue(ORB_AGENT_PORT_PROP); orbAgentAddrLocation = getPropertyValue(ORB_AGENT_ADDR_PROP_LOCATION); orbAgentPortLocation = getPropertyValue(ORB_AGENT_PORT_PROP_LOCATION); if (!StringUtils.hasValue(isAsyncLocation)) { try { isAsync = StringUtils.getBoolean( (String) getRequiredPropertyValue(DEFAULT_IS_ASYNCHRONOUS_PROP, errorBuf)); } catch (FrameworkException fe) { errorBuf.append( "No value is specified for either " + IS_ASYNCHRONOUS_LOCATION_PROP + "or" + DEFAULT_IS_ASYNCHRONOUS_PROP + ". One of the values should be present" + fe.getMessage()); } } if (!StringUtils.hasValue(headerLocation)) { try { header = getRequiredPropertyValue(DEFAULT_HEADER_PROP, errorBuf); } catch (Exception e) { errorBuf.append( "No value is specified for " + NF_HEADER_LOCATION_PROP + "or" + DEFAULT_HEADER_PROP + ". One of the values should be present" + e.getMessage()); } } if (errorBuf.length() > 0) throw new ProcessingException(errorBuf.toString()); }
/** * Initialize the event queue. * * @param props A container of configuration properties. * @exception FrameworkException Thrown if configuration is invalid. */ public void initialize(Map props) throws FrameworkException { String temp = (String) props.get(LOAD_EVENT_BATCH_SIZE_PROP); if (StringUtils.hasValue(temp)) { maxDatabaseEventLoadSize = StringUtils.getInteger(temp); if (Debug.isLevelEnabled(Debug.SYSTEM_CONFIG)) Debug.log( Debug.SYSTEM_CONFIG, "QUEUE OPERATION: Initializing: Maximum-database-event-batch-load-size is [" + maxDatabaseEventLoadSize + "] rows."); } }
/** * Initializes the Splitter. * * @param key Property-key to use for locating initialization properties. * @param type Property-type to use for locating initialization properties. * @exception ProcessingException when initialization fails */ public void initialize(String key, String type) throws ProcessingException { // Call the abstract super class's initialize method. This initializes // the adapterProperties hashtable defined in the super class and // retrieves the name and toProcessorNames values from the properties. super.initialize(key, type); if (Debug.isLevelEnabled(Debug.OBJECT_LIFECYCLE)) Debug.log(Debug.OBJECT_LIFECYCLE, "Splitter: Initializing....."); StringBuffer errorBuffer = new StringBuffer(); truncHeaderFooter = getRequiredPropertyValue(TRUNCATE_HEADER_FOOTER_PROP, errorBuffer); if (Debug.isLevelEnabled(Debug.MSG_DATA)) Debug.log(Debug.MSG_DATA, "Splitter: truncHeaderFooter? ---->" + truncHeaderFooter); String temp = getPropertyValue(FILE_SEPARATOR_PROP); if (StringUtils.hasValue(temp)) { fileSeparator = StringUtils.replaceSubstrings(temp, "\\r", "\r"); fileSeparator = StringUtils.replaceSubstrings(fileSeparator, "\\n", "\n"); if (Debug.isLevelEnabled(Debug.MSG_DATA)) Debug.log(Debug.MSG_DATA, "Splitter: fileSeparator---->" + fileSeparator); } try { splitLength = Integer.parseInt(getRequiredPropertyValue(SPLIT_LENGTH_PROP, errorBuffer)); if (Debug.isLevelEnabled(Debug.MSG_DATA)) Debug.log(Debug.MSG_DATA, "Splitter: splitLength---->" + splitLength); } catch (NumberFormatException nx) { throw new ProcessingException("ERROR: Splitter: The SPLIT_LENGTH " + "must be a number."); } if (splitLength <= 0) { throw new ProcessingException( "ERROR: Splitter: The SPLIT_LENGTH " + "must be greater than zero."); } if (errorBuffer.length() > 0) { String errMsg = errorBuffer.toString(); Debug.log(Debug.ALL_ERRORS, errMsg); throw new ProcessingException(errMsg); } }
/** * Reset any events meeting the given criteria so that they can be retried. * * @param criteria An event containing the event-selection criteria. * @return The number of events reset. * @exception FrameworkException Thrown on errors. */ protected static int reset(Event criteria) throws FrameworkException { Debug.log( Debug.MSG_STATUS, "QUEUE OPERATION: Resetting events in database for database queue ..."); if (!StringUtils.hasValue(criteria.channelName)) { throw new FrameworkException( "ERROR: Event channel name is a required queue search criteria."); } Connection dbConn = null; PreparedStatement ps = null; long startTime = -1; if (Debug.isLevelEnabled(Debug.BENCHMARK)) startTime = System.currentTimeMillis(); try { dbConn = DBConnectionPool.getInstance().acquireConnection(); if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log( Debug.DB_DATA, "Criteria used to reset events in database:\n" + criteria.describe()); // If no identifier was given that uniquely identifies a single event ... if (criteria.id == 0) { // Use last error time and error count, if available. if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log(Debug.DB_DATA, "\n" + LINE + "\nExecuting SQL:\n" + UPDATE_EVENT_RETRY_SQL); ps = dbConn.prepareStatement(UPDATE_EVENT_RETRY_SQL); ps.setString(1, criteria.channelName); if (criteria.lastErrorTime == null) ps.setNull(2, Types.DATE); else ps.setTimestamp(2, criteria.lastErrorTime); if (criteria.errorCount < 1) ps.setNull(3, Types.INTEGER); else ps.setInt(3, criteria.errorCount); } else { // An Id was given which should uniquely identify a single event, so we should // skip using any other qualifying criteria, if present. if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log( Debug.DB_DATA, "\n" + LINE + "\nExecuting SQL:\n" + UPDATE_EVENT_RETRY_BY_ID_SQL); ps = dbConn.prepareStatement(UPDATE_EVENT_RETRY_BY_ID_SQL); ps.setString(1, criteria.channelName); ps.setInt(2, criteria.id); } int numRows = ps.executeUpdate(); DBConnectionPool.getInstance().commit(dbConn); if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log( Debug.DB_DATA, "Committed SQL execution affected [" + numRows + "] rows.\n" + LINE); return numRows; } catch (SQLException sqle) { throw new DatabaseException( "ERROR: Could not execute SQL statement:\n" + DBInterface.getSQLErrorMessage(sqle)); } catch (Exception e) { throw new DatabaseException("ERROR: Could not execute SQL statement:\n" + e.toString()); } finally { releaseDatabaseResources(dbConn, ps); if (Debug.isLevelEnabled(Debug.BENCHMARK) && (startTime > 0)) { long stopTime = System.currentTimeMillis(); Debug.log( Debug.BENCHMARK, "ELAPSED TIME [" + (stopTime - startTime) + "] msec: " + "SQL: Time to reset event(s) in PersistentEvent database table."); } } }
/** * Load any available events from the database up to the configured maximum. * * @param criteria An event containing the event-selection criteria. * @return The next available event on the queue. * @exception FrameworkException Thrown on errors. */ private void loadFromDatabase(Event criteria) throws FrameworkException { Debug.log(Debug.MSG_STATUS, "QUEUE OPERATION: Loading events from database into queue ..."); if (!StringUtils.hasValue(criteria.channelName)) { throw new FrameworkException( "ERROR: Event channel name is a required queue search criteria."); } Connection dbConn = null; PreparedStatement ps = null; long startTime = -1; if (Debug.isLevelEnabled(Debug.BENCHMARK)) startTime = System.currentTimeMillis(); try { dbConn = DBConnectionPool.getInstance().acquireConnection(); if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log(Debug.DB_DATA, "\n" + LINE + "\nExecuting SQL:\n" + QUERY_EVENT_SQL); if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log( Debug.DB_DATA, "Criteria used in query against database:\n" + criteria.describe()); ps = dbConn.prepareStatement(QUERY_EVENT_SQL); ps.setString(1, criteria.channelName); ResultSet rs = ps.executeQuery(); for (int counter = 0; (counter < maxDatabaseEventLoadSize) && rs.next(); counter++) { Event event = new Event(); event.channelName = rs.getString(CHANNEL_NAME_COL); event.id = rs.getInt(ID_COL); event.message = DBLOBUtils.getCLOB(rs, MESSAGE_COL); if (Debug.isLevelEnabled(Debug.MSG_LIFECYCLE)) Debug.log(Debug.MSG_LIFECYCLE, "Event contents:\n" + event.message); event.arrivalTime = rs.getTimestamp(ARRIVAL_TIME_COL); event.errorStatus = rs.getString(ERROR_STATUS_COL); event.errorCount = rs.getInt(ERROR_COUNT_COL); event.lastErrorMessage = rs.getString(LAST_ERROR_MESSAGE_COL); event.lastErrorTime = rs.getTimestamp(LAST_ERROR_TIME_COL); // Add item to in-memory buffer. if (Debug.isLevelEnabled(Debug.MSG_STATUS)) Debug.log( Debug.MSG_STATUS, "Adding event [" + event.describe() + "] to in-memory queue buffer."); queue.add(event); if (Debug.isLevelEnabled(Debug.MSG_STATUS)) Debug.log(Debug.MSG_STATUS, "In-memory queue buffer size [" + queue.size() + "]."); } if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log(Debug.DB_DATA, "\n" + LINE); } catch (SQLException sqle) { throw new DatabaseException( "ERROR: Could not execute SQL statement:\n" + DBInterface.getSQLErrorMessage(sqle)); } catch (Exception e) { throw new DatabaseException("ERROR: Could not execute SQL statement:\n" + e.toString()); } finally { releaseDatabaseResources(dbConn, ps); if (Debug.isLevelEnabled(Debug.BENCHMARK) && (startTime > 0)) { long stopTime = System.currentTimeMillis(); Debug.log( Debug.BENCHMARK, "ELAPSED TIME [" + (stopTime - startTime) + "] msec: " + "SQL: Time to load event(s) from PersistentEvent database table."); } } }
/** * This gets a String to be split in the message object.It splits the string into substrings and * then stores them in the message object to be apssed to the next processors individually. This * class expects at least a single next processor hence it return a null if there are no next * processors. * * @param msgObj The MesageObject containg the string. * @return NVPair[] Name-Value pair array of next processor name and the MessageObject * @exception ProcessingException Thrown if processing fails */ public NVPair[] process(MessageProcessorContext context, MessageObject msgObj) throws MessageException, ProcessingException { if (Debug.isLevelEnabled(Debug.BENCHMARK)) Debug.log(Debug.BENCHMARK, "Reached Splitter process method.."); // Debug.log(null, Debug.UNIT_TEST,"MESSAGE OBJECT RECEIVED:--->"+msgObj.describe()); if (msgObj == null) { return null; } else if (toProcessorNames == null) { Debug.log(Debug.ALL_WARNINGS, "Splitter: No next processors available. Hence exiting."); } else if (!(msgObj.get() instanceof String)) { if (Debug.isLevelEnabled(Debug.UNIT_TEST)) Debug.log(Debug.UNIT_TEST, "SPLITTER : UNIT_TEST: " + ((msgObj.get()).getClass())); throw new ProcessingException("ERROR: Splitter: " + "The msg Object must be a String."); } if (Debug.isLevelEnabled(Debug.UNIT_TEST)) Debug.log(Debug.UNIT_TEST, "MESSAGE OBJECT RECEIVED:--->" + msgObj.describe()); String batchedRecords = msgObj.getString(); List singleRecord; String subStr = ""; // to take care empty batch files that are valid files in some cases if (!StringUtils.hasValue(batchedRecords)) { Debug.log(Debug.ALL_WARNINGS, "MESSAGE CONTENT IS NULL"); return null; } if (!StringUtils.hasValue(fileSeparator)) // if fileseparator is false... { if (batchedRecords.length() < splitLength) { throw new MessageException( "ERROR: Splitter: " + "Batched String length is less than " + splitLength + "bytes."); } float tempSize = (float) (batchedRecords.length()) / splitLength; int size = (batchedRecords.length()) / splitLength; // check for length of string if (size != tempSize) { throw new MessageException( "ERROR: Splitter: " + "Record received is not of correct length"); } singleRecord = new Vector(size); int i = 0; for (i = 0; i < size; i++) { subStr = batchedRecords.substring(i * splitLength, (i + 1) * splitLength); singleRecord.add(i, subStr); } } else // if fileseparator is true... { singleRecord = new Vector(); StringTokenizer st = new StringTokenizer(batchedRecords, fileSeparator); while (st.hasMoreTokens()) { subStr = st.nextToken(); if (subStr.length() != splitLength) { throw new MessageException( "ERROR: Splitter: Record " + "received after removing the fileseparator is not of correct length ."); } singleRecord.add(subStr); if (Debug.isLevelEnabled(Debug.UNIT_TEST)) Debug.log( Debug.UNIT_TEST, "\nDATA\n" + "********************************************" + subStr); } } if (getBoolean(truncHeaderFooter)) // if truncHeaderFooter is true... { singleRecord.remove((singleRecord.size() - 1)); singleRecord.remove(0); } // else continue... int batchedSize = singleRecord.size(); if (Debug.isLevelEnabled(Debug.UNIT_TEST)) Debug.log(Debug.UNIT_TEST, "BATCHED SIZE--->" + batchedSize); int processorsNo = toProcessorNames.length; NVPair[] contents = new NVPair[batchedSize * processorsNo]; int i = 0; for (i = 0; i < batchedSize; i++) { MessageObject mObj = new MessageObject(); mObj.set(singleRecord.get(i)); // Sending the message objects to the next processors. for (int j = 0; j < processorsNo; j++) { contents[(i * (processorsNo)) + j] = new NVPair(toProcessorNames[j], mObj); if (Debug.isLevelEnabled(Debug.UNIT_TEST)) Debug.log( Debug.UNIT_TEST, "NEXT PROCESSOR-->" + toProcessorNames[j] + "\n" + "MESSAGE OBJECT CONTENT------------>" + mObj.describe()); } } if (Debug.isLevelEnabled(Debug.UNIT_TEST)) Debug.log(Debug.UNIT_TEST, "SPLITTER : CONTEXT---->" + context.describe()); return contents; }
/** * Make the actual CORBA call. * * @param serverName Name of the server as known in the COS Naming Service. * @param reload Flag indicating whether object reference should be refreshed (true) or any * previously-cached version should be used (false). * @param header Header message to send. * @param message Body message to send. * @return Response that caller should return. * @exception Exception Thrown on any errors. */ private String makeClientCall(String serverName, boolean reload, String header, String message) throws Exception { ORB orb = null; // If the alternate ip and port are provided if (StringUtils.hasValue(orbAgentAddr) && StringUtils.hasValue(orbAgentPort)) { // Key to store the orb in a static map for access the next time around String key = orbAgentAddr + ":" + orbAgentPort; synchronized (orbStore) { orb = (ORB) orbStore.get(key); if (orb == null) { Properties props = new Properties(); props.put(ORB_AGENT_ADDR_PROP, orbAgentAddr); props.put(ORB_AGENT_PORT_PROP, orbAgentPort); orb = new CorbaPortabilityLayer(new String[0], props, null, serverName).getORB(); orbStore.put(key, orb); } else { if (Debug.isLevelEnabled(Debug.IO_STATUS)) Debug.log( Debug.IO_STATUS, "Using cached orb with properties " + "ORBagentAddr = [" + orbAgentAddr + "] ORBagentPort = [" + orbAgentPort + "]"); } } } else { if (Debug.isLevelEnabled(Debug.IO_STATUS)) Debug.log(Debug.IO_STATUS, "Using the default orb .."); orb = Supervisor.getSupervisor().getCPL().getORB(); } ObjectLocator ob_loc = new ObjectLocator(orb); if (reload) { ob_loc.removeFromCache(serverName); if (StringUtils.hasValue(orbAgentAddr) && StringUtils.hasValue(orbAgentPort)) ob_loc.removeFromCache(serverName, orbAgentAddr, orbAgentPort); } RequestHandler rh = null; // The key corresponding to secondary install object references depends on host address and port // too. if (StringUtils.hasValue(orbAgentAddr) && StringUtils.hasValue(orbAgentPort)) rh = RequestHandlerHelper.narrow(ob_loc.find(serverName, orbAgentAddr, orbAgentPort)); else rh = RequestHandlerHelper.narrow(ob_loc.find(serverName)); if (rh == null) { throw new Exception("Object named [" + serverName + "] is not of IDL type RequestHandler."); } // Make sure that the header contains any available customer context information. header = CustomerContext.getInstance().propagate(header); if (Debug.isLevelEnabled(Debug.IO_STATUS)) Debug.log(Debug.IO_STATUS, "Header value:\n" + header); ThreadMonitor.ThreadInfo tmti = ThreadMonitor.start( "Message-processor [" + getName() + "] making CORBA client call with header:\n" + header); try { if (isAsync) { rh.processAsync(header, message); return (message); } else { org.omg.CORBA.StringHolder response = new org.omg.CORBA.StringHolder(""); rh.processSync(header, message, response); return (response.value); } } finally { ThreadMonitor.stop(tmti); } }
/** * If NF_HEADER_LOCATION_PROP exists in context use as the header to forward to Gateway. If * IS_ASYNCHRONOUS_PROP exists in context then use that value to call either processAsync or * processSync * * @param input MessageObject containing the value to be processed * * @param mpcontext The context * @return Optional NVPair containing a Destination name and a MessageObject, or null if none. * @exception ProcessingException Thrown if processing fails. * @exception MessageException Thrown if bad message. */ public NVPair[] process(MessageProcessorContext ctx, MessageObject input) throws MessageException, ProcessingException { if (input == null) return null; try { serverName = getRequiredProperty(ctx, input, SERVER_NAME_PROP); } catch (MessageException me) { throw new ProcessingException(me.getMessage()); } if (StringUtils.hasValue(headerLocation)) { try { header = getString(headerLocation, ctx, input); } catch (MessageException me) { throw new ProcessingException(me.getMessage()); } } if (StringUtils.hasValue(isAsyncLocation)) { try { isAsync = StringUtils.getBoolean(getString(isAsyncLocation, ctx, input)); } catch (FrameworkException fe) { throw new ProcessingException( "Value of " + IS_ASYNCHRONOUS_LOCATION_PROP + " is not TRUE/FALSE. " + fe.getMessage()); } } // Fetch the alternate Orb Address, if one exists at the specified context location if (StringUtils.hasValue(orbAgentAddrLocation)) { try { if (exists(orbAgentAddrLocation, ctx, input, true)) { orbAgentAddr = getString(orbAgentAddrLocation, ctx, input); if (Debug.isLevelEnabled(Debug.MSG_STATUS)) Debug.log( Debug.MSG_STATUS, "RequestHandlerClient:: alternate orb exists with orb agent address [" + orbAgentAddr + "]"); } } catch (MessageException me) { throw new ProcessingException(me.getMessage()); } } // Fetch the alternate Orb Port, if one exists at the specified context location if (StringUtils.hasValue(orbAgentPortLocation)) { try { if (exists(orbAgentPortLocation, ctx, input, true)) { orbAgentPort = getString(orbAgentPortLocation, ctx, input); if (Debug.isLevelEnabled(Debug.MSG_STATUS)) Debug.log( Debug.MSG_STATUS, "RequestHandlerClient:: alternate orb exists with orb agent port [" + orbAgentPort + "]"); } } catch (MessageException me) { throw new ProcessingException(me.getMessage()); } } String msg = input.getString(); try { try { return (formatNVPair(makeClientCall(serverName, false, header, msg))); } catch (Exception e) { // Any of the following exceptions indicate that the failure might be due to // a CORBA communications issue (stale object reference) that should be retried. if ((e instanceof org.omg.CORBA.OBJECT_NOT_EXIST) || (e instanceof org.omg.CORBA.TRANSIENT) || (e instanceof org.omg.CORBA.COMM_FAILURE) || (e instanceof org.omg.CORBA.INV_OBJREF) || (e instanceof org.omg.CORBA.UNKNOWN)) { Debug.warning( "Caught the following CORBA communication error, so retrying:\n" + e.toString() + "\n" + Debug.getStackTrace(e)); return (formatNVPair(makeClientCall(serverName, true, header, msg))); } else { // It's not a communication exception indicating that retry is recommended, // so just re-throw it. throw e; } } } catch (Exception e) { if (e instanceof InvalidDataException) { Debug.error(e.toString() + "\n" + Debug.getStackTrace(e)); throw new MessageException(((InvalidDataException) e).errorMessage); } else { Debug.error(e.toString() + "\n" + Debug.getStackTrace(e)); throw new ProcessingException(e.toString()); } } }