Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/workeffort/webapp/workeffort/WEB-INF/actions/calendar/Upcoming.groovy
URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/workeffort/webapp/workeffort/WEB-INF/actions/calendar/Upcoming.groovy?rev=1623295&r1=1623294&r2=1623295&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/workeffort/webapp/workeffort/WEB-INF/actions/calendar/Upcoming.groovy (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/workeffort/webapp/workeffort/WEB-INF/actions/calendar/Upcoming.groovy Mon Sep 8 06:04:39 2014 @@ -18,11 +18,7 @@ */ import java.util.*; -import org.ofbiz.security.*; -import org.ofbiz.entity.*; import org.ofbiz.base.util.*; -import org.ofbiz.webapp.pseudotag.*; -import org.ofbiz.workeffort.workeffort.*; facilityId = parameters.get("facilityId"); fixedAssetId = parameters.get("fixedAssetId"); Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/base/config/log4j2.xml URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/base/config/log4j2.xml?rev=1623295&r1=1623294&r2=1623295&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/base/config/log4j2.xml (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/base/config/log4j2.xml Mon Sep 8 06:04:39 2014 @@ -2,11 +2,11 @@ <Configuration monitorInterval="60"> <Appenders> <Console name="stdout" target="SYSTEM_OUT"> - <PatternLayout pattern="%date{COMPACT} |%-20.20thread |%-20.20logger{1}|%level{length=1}| %message%n"/> + <PatternLayout pattern="%date{COMPACT} |%-20.20thread |%-30.30logger{1}|%level{length=1}| %message%n"/> </Console> <RollingFile name="ofbiz" fileName="runtime/logs/ofbiz.log" filePattern="runtime/logs/ofbiz-%d{yyyy-MM-dd}-%i.log.zip"> - <PatternLayout pattern="%date{COMPACT} |%-20.20thread |%-20.20logger{1}|%level{length=1}| %message%n"/> + <PatternLayout pattern="%date{COMPACT} |%-20.20thread |%-30.30logger{1}|%level{length=1}| %message%n"/> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicy size="1 MB"/> @@ -15,7 +15,7 @@ </RollingFile> <RollingFile name="external" fileName="runtime/logs/external.log" filePattern="runtime/logs/external-%d{yyyy-MM-dd}-%i.log.zip"> - <PatternLayout pattern="%date{COMPACT} |%-20.20thread |%-20.20logger{1}|%level{length=1}| %message%n"/> + <PatternLayout pattern="%date{COMPACT} |%-20.20thread |%-30.30logger{1}|%level{length=1}| %message%n"/> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicy size="1 MB"/> Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/base/src/org/ofbiz/base/util/Debug.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/base/src/org/ofbiz/base/util/Debug.java?rev=1623295&r1=1623294&r2=1623295&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/base/src/org/ofbiz/base/util/Debug.java (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/base/src/org/ofbiz/base/util/Debug.java Mon Sep 8 06:04:39 2014 @@ -18,17 +18,11 @@ *******************************************************************************/ package org.ofbiz.base.util; -import java.io.PrintStream; -import java.io.PrintWriter; import java.util.Formatter; import java.util.HashMap; -import java.util.Locale; import java.util.Map; -import java.util.TimeZone; import org.apache.logging.log4j.*; -import org.ofbiz.base.conversion.ConversionException; -import org.ofbiz.base.conversion.DateTimeConverters.DateToString; /** * Configurable Debug logging wrapper class @@ -36,11 +30,9 @@ import org.ofbiz.base.conversion.DateTim */ public final class Debug { - public static final boolean useLog4J = true; - public static final String noModuleModule = "NoModule"; // set to null for previous behavior - public static final Object[] emptyParams = new Object[0]; + private static final String noModuleModule = "NoModule"; // set to null for previous behavior + private static final Object[] emptyParams = new Object[0]; - public static final String SYS_DEBUG = System.getProperty("DEBUG"); public static final int ALWAYS = 0; public static final int VERBOSE = 1; public static final int TIMING = 2; @@ -50,19 +42,14 @@ public final class Debug { public static final int ERROR = 6; public static final int FATAL = 7; - public static final String[] levels = {"Always", "Verbose", "Timing", "Info", "Important", "Warning", "Error", "Fatal"}; - public static final String[] levelProps = {"", "print.verbose", "print.timing", "print.info", "print.important", "print.warning", "print.error", "print.fatal"}; - public static final Level[] levelObjs = {Level.FATAL, Level.DEBUG, Level.TRACE, Level.INFO, Level.INFO, Level.WARN, Level.ERROR, Level.FATAL}; + private static final String[] levelProps = {"", "print.verbose", "print.timing", "print.info", "print.important", "print.warning", "print.error", "print.fatal"}; + private static final Level[] levelObjs = {Level.FATAL, Level.DEBUG, Level.TRACE, Level.INFO, Level.INFO, Level.WARN, Level.ERROR, Level.FATAL}; - protected static Map<String, Integer> levelStringMap = new HashMap<String, Integer>(); + private static final Map<String, Integer> levelStringMap = new HashMap<String, Integer>(); - protected static PrintStream printStream = System.out; - protected static PrintWriter printWriter = new PrintWriter(printStream); + private static final boolean levelOnCache[] = new boolean[8]; // this field is not thread safe - protected static boolean levelOnCache[] = new boolean[8]; - protected static final boolean useLevelOnCache = true; - - protected static Logger root = LogManager.getRootLogger(); + private static final Logger root = LogManager.getRootLogger(); static { levelStringMap.put("verbose", Debug.VERBOSE); @@ -80,19 +67,6 @@ public final class Debug { } } - public static PrintStream getPrintStream() { - return printStream; - } - - public static void setPrintStream(PrintStream printStream) { - Debug.printStream = printStream; - Debug.printWriter = new PrintWriter(printStream); - } - - public static PrintWriter getPrintWriter() { - return printWriter; - } - public static Logger getLogger(String module) { if (UtilValidate.isNotEmpty(module)) { return LogManager.getLogger(module); @@ -129,47 +103,13 @@ public final class Debug { } // log - if (useLog4J) { - Logger logger = getLogger(module); - //callingClass - logger.log(levelObjs[level], msg, t); - } else { - StringBuilder prefixBuf = new StringBuilder(); - - DateToString dateToString = new DateToString(); - try { - prefixBuf.append(dateToString.convert(new java.util.Date(), Locale.getDefault(), - TimeZone.getDefault(), UtilDateTime.DATE_TIME_FORMAT)); - } catch (ConversionException e) { - logFatal(e, Debug.class.getName()); - } - prefixBuf.append(" [OFBiz"); - if (module != null) { - prefixBuf.append(":"); - prefixBuf.append(module); - } - prefixBuf.append(":"); - prefixBuf.append(levels[level]); - prefixBuf.append("] "); - if (msg != null) { - getPrintWriter().print(prefixBuf.toString()); - getPrintWriter().println(msg); - } - if (t != null) { - getPrintWriter().print(prefixBuf.toString()); - getPrintWriter().println("Received throwable:"); - t.printStackTrace(getPrintWriter()); - } - } + Logger logger = getLogger(module); + logger.log(levelObjs[level], msg, t); } } public static boolean isOn(int level) { - if (useLevelOnCache) { - return levelOnCache[level]; - } else { - return (level == Debug.ALWAYS || UtilProperties.propertyValueEqualsIgnoreCase("debug.properties", levelProps[level], "true")); - } + return levelOnCache[level]; } // leaving these here @@ -374,14 +314,10 @@ public final class Debug { } public static void set(int level, boolean on) { - if (!useLevelOnCache) - return; levelOnCache[level] = on; } public static boolean get(int level) { - if (!useLevelOnCache) - return true; return levelOnCache[level]; } } Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/common/config/CommonEntityLabels.xml URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/common/config/CommonEntityLabels.xml?rev=1623295&r1=1623294&r2=1623295&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/common/config/CommonEntityLabels.xml (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/common/config/CommonEntityLabels.xml Mon Sep 8 06:04:39 2014 @@ -16266,7 +16266,7 @@ <value xml:lang="ru">ÐÑгани</value> <value xml:lang="th">à¸à¸±à¸à¸à¸²à¸à¸´ </value> <value xml:lang="zh">é¿å¯æ±å°¼</value> - <value xml:lang="zh_TW">é¿å¯æ±</value> + <value xml:lang="zh_TW">é¿å¯æ±å°¼</value> </property> <property key="Uom.description.ALL"> <value xml:lang="de">Lek Albanien</value> @@ -20653,7 +20653,7 @@ <value xml:lang="th">สà¸à¸¸à¸¥à¹à¸à¸´à¸</value> <value xml:lang="vi">Tiá»n tá»</value> <value xml:lang="zh">å¸ç§</value> - <value xml:lang="zh_TW">å¹£å¥</value> + <value xml:lang="zh_TW">度éå®ä½</value> </property> <property key="UomType.description.DATASPD_MEASURE"> <value xml:lang="de">Daten Geschwindigkeit</value> Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/common/config/CommonUiLabels.xml URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/common/config/CommonUiLabels.xml?rev=1623295&r1=1623294&r2=1623295&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/common/config/CommonUiLabels.xml (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/common/config/CommonUiLabels.xml Mon Sep 8 06:04:39 2014 @@ -118,7 +118,7 @@ <value xml:lang="th">CMS Site</value> <value xml:lang="vi">Trang thông tin CMS</value> <value xml:lang="zh">å 容管çç³»ç»ç«ç¹</value> - <value xml:lang="zh_TW">å §å®¹ç®¡ç系統</value> + <value xml:lang="zh_TW">å §å®¹ç®¡ç系統ç«å°</value> </property> <property key="Catalog"> <value xml:lang="ar">ÙØ§ØªØ§ÙÙØ¬</value> @@ -2421,7 +2421,7 @@ <value xml:lang="vi">Tiá»n tá»</value> <value xml:lang="zh">å¸ç§</value> <value xml:lang="zh-CN">è´§å¸</value> - <value xml:lang="zh_TW">å¹£å¥</value> + <value xml:lang="zh_TW">度éå®ä½</value> </property> <property key="CommonCurrent"> <value xml:lang="ar">جارÙ</value> @@ -8118,7 +8118,6 @@ <value xml:lang="es">Ejecutar</value> <value xml:lang="fr">Exécuter</value> <value xml:lang="hi-IN">पà¥à¤°à¤°à¥à¤¦à¤¶à¤¿à¤¤ à¤à¤°à¥</value> - <value xml:lang="zh_TW">PDF</value> <value xml:lang="it">Esegui</value> <value xml:lang="ja">å®è¡</value> <value xml:lang="nl">Uitvoeren</value> @@ -10962,7 +10961,7 @@ <value xml:lang="th">à¸à¸µà¹</value> <value xml:lang="vi">Cái</value> <value xml:lang="zh"> </value> - <value xml:lang="zh">æ¤</value> + <value xml:lang="zh_TW">æ¤</value> </property> <property key="CommonTheFollowingRequiredFieldsWhereFoundEmpty"> <value xml:lang="cs">NásledujÃcà povinná pole byla prázdná</value> @@ -13143,7 +13142,7 @@ <value xml:lang="th">สà¸à¸¸à¸¥à¹à¸à¸´à¸</value> <value xml:lang="vi">Tiá»n tá»</value> <value xml:lang="zh">å¸ç§</value> - <value xml:lang="zh_TW">å¹£å¥</value> + <value xml:lang="zh_TW">度éå®ä½</value> </property> <property key="FormFieldTitle_currentRecurrenceCount"> <value xml:lang="cs">SouÄasná hloubka zanoÅenÃ</value> @@ -13834,7 +13833,7 @@ <value xml:lang="th">หà¸à¹à¸§à¸¢à¸§à¸±à¸</value> <value xml:lang="vi">ÄÆ¡n vá» tÃnh</value> <value xml:lang="zh">å¸å¼</value> - <value xml:lang="zh_TW">å¹£å¥</value> + <value xml:lang="zh_TW">度éå®ä½</value> </property> <property key="FormFieldTitle_updateButton"> <value xml:lang="ar">ØªØØ¯ÙØ«</value> @@ -13870,7 +13869,6 @@ <value xml:lang="en">HR</value> <value xml:lang="es">RR.HH.</value> <value xml:lang="fr">Ress. hum.</value> - <value xml:lang="zh_TW">Google Base</value> <value xml:lang="hi-IN">मानव सà¤à¤¸à¤¾à¤§à¤¨(HR)</value> <value xml:lang="it">Risorse umane</value> <value xml:lang="ja">人äº(HR)</value> @@ -14011,7 +14009,6 @@ <value xml:lang="fr">Commandes</value> <value xml:lang="hi-IN">à¤à¤¦à¥à¤¶</value> <value xml:lang="it">Ordini</value> - <value xml:lang="zh_TW">Oagis</value> <value xml:lang="ja">注æ</value> <value xml:lang="nl">Bestelling</value> <value xml:lang="pt">Encomenda</value> Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/entity/src/org/ofbiz/entity/test/EntityTestSuite.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/entity/src/org/ofbiz/entity/test/EntityTestSuite.java?rev=1623295&r1=1623294&r2=1623295&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/entity/src/org/ofbiz/entity/test/EntityTestSuite.java (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/entity/src/org/ofbiz/entity/test/EntityTestSuite.java Mon Sep 8 06:04:39 2014 @@ -45,7 +45,6 @@ import org.ofbiz.base.util.UtilMisc; import org.ofbiz.base.util.UtilXml; import org.ofbiz.entity.Delegator; import org.ofbiz.entity.DelegatorFactory; -import org.ofbiz.entity.GenericDelegator; import org.ofbiz.entity.GenericEntity; import org.ofbiz.entity.GenericEntityException; import org.ofbiz.entity.GenericPK; @@ -1152,6 +1151,64 @@ public class EntityTestSuite extends Ent assertFalse("Duplicate sequence id returned", duplicateFound.get()); } + /* + This test is useful to confirm that the default setting of use-transaction="true" for screen definitions is + the best one for performance. + With this setting one database transaction is started by the framework before rendering the screen. + Most screens usually have multiple Delegator calls to find records. + In most of the GenericDelegator's find methods, a transaction is created if one does not already exist, + the statement is performed, and the transaction is committed. + So, by making that attribute "false" - a screen will have many individual transactions instead of just one. + + This test assess that running the same number of sql statements withing one transaction is faster than running + them with individual transactions. + */ + public void testOneBigTransactionIsFasterThanSeveralSmallOnes() { + boolean transactionStarted = false; + long startTime = System.currentTimeMillis(); + int totalNumberOfRows = 0; + int numberOfQueries = 500; + boolean noErrors = true; + try { + transactionStarted = TransactionUtil.begin(); + for (int i = 1; i <= numberOfQueries; i++) { + List rows = delegator.findAll("SequenceValueItem", false); + totalNumberOfRows = totalNumberOfRows + rows.size(); + } + TransactionUtil.commit(transactionStarted); + } catch (Exception e) { + try { + TransactionUtil.rollback(transactionStarted, "", e); + } catch (Exception e2) {} + noErrors = false; + } + long endTime = System.currentTimeMillis(); + long totalTimeOneTransaction = endTime - startTime; + Debug.logInfo("Selected " + totalNumberOfRows + " rows with " + numberOfQueries + " queries (all contained in one big transaction) in " + totalTimeOneTransaction + " ms", module); + assertTrue("Errors detected executing the big transaction", noErrors); + + totalNumberOfRows = 0; + noErrors = true; + try { + for (int i = 1; i <= numberOfQueries; i++) { + transactionStarted = TransactionUtil.begin(); + List rows = delegator.findAll("SequenceValueItem", false); + totalNumberOfRows = totalNumberOfRows + rows.size(); + TransactionUtil.commit(transactionStarted); + } + } catch (Exception e) { + try { + TransactionUtil.rollback(transactionStarted, "", e); + } catch (Exception e2) {} + noErrors = false; + } + endTime = System.currentTimeMillis(); + long totalTimeSeveralSmallTransactions = endTime - startTime; + Debug.logInfo("Selected " + totalNumberOfRows + " rows with " + numberOfQueries + " queries (each in its own transaction) in " + totalTimeSeveralSmallTransactions + " ms", module); + assertTrue("Errors detected executing the small transactions", noErrors); + assertTrue("One big transaction was not faster than several small ones", totalTimeOneTransaction < totalTimeSeveralSmallTransactions); + } + private final class TestObserver implements Observer { private Observable observable; private Object arg; Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/entity/src/org/ofbiz/entity/util/SequenceUtil.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/entity/src/org/ofbiz/entity/util/SequenceUtil.java?rev=1623295&r1=1623294&r2=1623295&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/entity/src/org/ofbiz/entity/util/SequenceUtil.java (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/entity/src/org/ofbiz/entity/util/SequenceUtil.java Mon Sep 8 06:04:39 2014 @@ -155,9 +155,19 @@ public class SequenceUtil { this.fillBank(staggerMax); } + /* + The algorithm to get the new sequence id in a thread safe way is the following: + 1 - run an update with no changes to get a lock on the record + 1bis - if no record is found, try to create and update it to get the lock + 2 - select the record (now locked) to get the curSeqId + 3 - increment the sequence + The three steps are executed in one dedicated database transaction. + */ private void fillBank(long stagger) { // no need to get a new bank, SeqIds available - if ((curSeqId + stagger) <= maxSeqId) return; + if ((curSeqId + stagger) <= maxSeqId) { + return; + } long bankSize = this.bankSize; if (stagger > 1) { @@ -165,7 +175,9 @@ public class SequenceUtil { bankSize = stagger * defaultBankSize; } - if (bankSize > maxBankSize) bankSize = maxBankSize; + if (bankSize > maxBankSize) { + bankSize = maxBankSize; + } Transaction suspendedTransaction = null; try { @@ -192,34 +204,35 @@ public class SequenceUtil { throw new GenericEntityException("Unable to esablish a connection with the database, connection was null..."); } - String sql = null; try { stmt = connection.createStatement(); - - // run an update with no changes to get a lock on the record + String sql = null; + // 1 - run an update with no changes to get a lock on the record if (stmt.executeUpdate(updateForLockStatement) <= 0) { - Debug.logWarning("First select failed: will try to add new row, result set was empty for sequence [" + seqName + "] \nUsed SQL: " + sql + " \n ", module); + Debug.logWarning("Lock failed; no sequence row was found, will try to add a new one for sequence: " + seqName, module); sql = "INSERT INTO " + SequenceUtil.this.tableName + " (" + SequenceUtil.this.nameColName + ", " + SequenceUtil.this.idColName + ") VALUES ('" + this.seqName + "', " + startSeqId + ")"; - if (stmt.executeUpdate(sql) <= 0) { + try { + stmt.executeUpdate(sql); + } catch (SQLException sqle) { // insert failed: this means that another thread inserted the record; then retry to run an update with no changes to get a lock on the record if (stmt.executeUpdate(updateForLockStatement) <= 0) { // This should never happen - throw new GenericEntityException("No rows changed when trying insert new sequence row with this SQL: " + sql); + throw new GenericEntityException("No rows changed when trying insert new sequence: " + seqName); } + } } - // select the record (now locked) to get the curSeqId + // 2 - select the record (now locked) to get the curSeqId rs = stmt.executeQuery(selectSequenceStatement); - boolean gotVal = false; - if (rs.next()) { + boolean sequenceFound = rs.next(); + if (sequenceFound) { curSeqId = rs.getLong(SequenceUtil.this.idColName); - gotVal = true; } rs.close(); - if (!gotVal) { - throw new GenericEntityException("Failed to find the sequence record: " + sql); + if (!sequenceFound) { + throw new GenericEntityException("Failed to find the sequence record for sequence: " + seqName); } - // increment the sequence + // 3 - increment the sequence sql = "UPDATE " + SequenceUtil.this.tableName + " SET " + SequenceUtil.this.idColName + "=" + SequenceUtil.this.idColName + "+" + bankSize + " WHERE " + SequenceUtil.this.nameColName + "='" + this.seqName + "'"; if (stmt.executeUpdate(sql) <= 0) { throw new GenericEntityException("Update failed, no rows changes for seqName: " + seqName); Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/entityext/src/org/ofbiz/entityext/eca/EntityEcaUtil.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/entityext/src/org/ofbiz/entityext/eca/EntityEcaUtil.java?rev=1623295&r1=1623294&r2=1623295&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/entityext/src/org/ofbiz/entityext/eca/EntityEcaUtil.java (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/entityext/src/org/ofbiz/entityext/eca/EntityEcaUtil.java Mon Sep 8 06:04:39 2014 @@ -24,7 +24,6 @@ import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.Future; -import freemarker.template.utility.StringUtil; import javolution.util.FastList; import javolution.util.FastMap; @@ -135,7 +134,7 @@ public class EntityEcaUtil { rules.add(new EntityEcaRule(e)); } try { - Debug.logInfo("Loaded [" + StringUtil.leftPad(Integer.toString(rules.size()), 3) + "] Entity ECA definitions from " + handler.getFullLocation() + " in loader " + handler.getLoaderName(), module); + Debug.logInfo("Loaded [" + rules.size() + "] Entity ECA definitions from " + handler.getFullLocation() + " in loader " + handler.getLoaderName(), module); } catch (GenericConfigException e) { Debug.logError(e, module); } Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/DispatchContext.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/DispatchContext.java?rev=1623295&r1=1623294&r2=1623295&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/DispatchContext.java (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/DispatchContext.java Mon Sep 8 06:04:39 2014 @@ -19,86 +19,28 @@ package org.ofbiz.service; import java.io.Serializable; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; import java.util.Map; import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.Callable; -import java.util.concurrent.Future; import javax.wsdl.WSDLException; -import org.ofbiz.base.component.ComponentConfig; -import org.ofbiz.base.concurrent.ExecutionPool; -import org.ofbiz.base.config.GenericConfigException; -import org.ofbiz.base.config.MainResourceHandler; -import org.ofbiz.base.config.ResourceHandler; -import org.ofbiz.base.util.Debug; -import org.ofbiz.base.util.cache.UtilCache; import org.ofbiz.entity.Delegator; -import org.ofbiz.entity.GenericEntityConfException; -import org.ofbiz.entity.config.model.DelegatorElement; -import org.ofbiz.entity.config.model.EntityConfig; import org.ofbiz.security.Security; -import org.ofbiz.service.config.ServiceConfigUtil; -import org.ofbiz.service.config.model.GlobalServices; -import org.ofbiz.service.eca.ServiceEcaUtil; import org.w3c.dom.Document; /** - * Dispatcher Context + * Service dispatch context. A collection of objects and convenience methods + * to be used by service implementations. */ @SuppressWarnings("serial") -public class DispatchContext implements Serializable { +public final class DispatchContext implements Serializable { public static final String module = DispatchContext.class.getName(); - private static final UtilCache<String, Map<String, ModelService>> modelServiceMapByModel = UtilCache.createUtilCache("service.ModelServiceMapByModel", 0, 0, false); + private final LocalDispatcher dispatcher; - // these four fields represent the immutable state of a DispatchContext object - private final String name; - private final transient ClassLoader loader; - private final transient LocalDispatcher dispatcher; - private final String model; - - /** - * Creates new DispatchContext as an immutable object. - * The "dispatcher" argument can be null if the "name" argument matches the name of a valid entity model reader. - * The thread safety of a DispatchContext object is a consequence of its immutability. - * - * @param name The immutable name of the DispatchContext - * @param loader The immutable class loader - * @param dispatcher The immutable dispatcher associated to the DispatchContext - * - */ - public DispatchContext(String name, ClassLoader loader, LocalDispatcher dispatcher) { - this.name = name; - this.loader = loader; + DispatchContext(LocalDispatcher dispatcher) { this.dispatcher = dispatcher; - String modelName = null; - if (this.dispatcher != null) { - Delegator delegator = dispatcher.getDelegator(); - if (delegator != null) { - DelegatorElement delegatorInfo = null; - try { - delegatorInfo = EntityConfig.getInstance().getDelegator(delegator.getDelegatorBaseName()); - } catch (GenericEntityConfException e) { - Debug.logWarning(e, "Exception thrown while getting delegator config: ", module); - } - if (delegatorInfo != null) { - modelName = delegatorInfo.getEntityModelReader(); - } - } - } - if (modelName == null) { - // if a modelName is not associated to the dispatcher (e.g. dispatcher is null) then use the name - // of the DispatchContext as the model reader name - modelName = name; - } - this.model = modelName; - getGlobalServiceMap(); } /** @@ -106,7 +48,7 @@ public class DispatchContext implements * @return ClassLoader of the context */ public ClassLoader getClassLoader() { - return this.loader; + return dispatcher.getClassLoader(); } /** @@ -114,7 +56,7 @@ public class DispatchContext implements * @return String name of the LocalDispatcher object */ public String getName() { - return name; + return dispatcher.getName(); } /** @@ -122,7 +64,7 @@ public class DispatchContext implements * @return LocalDispatcher that was used to create this context */ public LocalDispatcher getDispatcher() { - return this.dispatcher; + return dispatcher; } /** @@ -199,84 +141,20 @@ public class DispatchContext implements } /** - * Gets the ModelService instance that corresponds to given the name + * Gets the ModelService instance that corresponds to the given name * @param serviceName Name of the service * @return GenericServiceModel that corresponds to the serviceName */ public ModelService getModelService(String serviceName) throws GenericServiceException { - Map<String, ModelService> serviceMap = getGlobalServiceMap(); - ModelService retVal = null; - if (serviceMap != null) { - retVal = serviceMap.get(serviceName); - if (retVal != null && !retVal.inheritedParameters()) { - retVal.interfaceUpdate(this); - } - } - if (retVal == null) { - throw new GenericServiceException("Cannot locate service by name (" + serviceName + ")"); - } - return retVal; + return dispatcher.getModelService(serviceName); } public Set<String> getAllServiceNames() { - Set<String> serviceNames = new TreeSet<String>(); - - Map<String, ModelService> globalServices = modelServiceMapByModel.get(this.model); - if (globalServices != null) { - serviceNames.addAll(globalServices.keySet()); - } - return serviceNames; + return dispatcher.getAllServiceNames(); } public Document getWSDL(String serviceName, String locationURI) throws GenericServiceException, WSDLException { ModelService model = this.getModelService(serviceName); return model.toWSDL(locationURI); } - - private Callable<Map<String, ModelService>> createServiceReaderCallable(final ResourceHandler handler) { - return new Callable<Map<String, ModelService>>() { - public Map<String, ModelService> call() throws Exception { - return ModelServiceReader.getModelServiceMap(handler, DispatchContext.this.getDelegator()); - } - }; - } - - private Map<String, ModelService> getGlobalServiceMap() { - Map<String, ModelService> serviceMap = modelServiceMapByModel.get(this.model); - if (serviceMap == null) { - serviceMap = new HashMap<String, ModelService>(); - - List<Future<Map<String, ModelService>>> futures = new LinkedList<Future<Map<String, ModelService>>>(); - List<GlobalServices> globalServicesList = null; - try { - globalServicesList = ServiceConfigUtil.getServiceEngine().getGlobalServices(); - } catch (GenericConfigException e) { - // FIXME: Refactor API so exceptions can be thrown and caught. - Debug.logError(e, module); - throw new RuntimeException(e.getMessage()); - } - for (GlobalServices globalServices : globalServicesList) { - ResourceHandler handler = new MainResourceHandler(ServiceConfigUtil.SERVICE_ENGINE_XML_FILENAME, globalServices.getLoader(), globalServices.getLocation()); - futures.add(ExecutionPool.GLOBAL_FORK_JOIN.submit(createServiceReaderCallable(handler))); - } - - // get all of the component resource model stuff, ie specified in each ofbiz-component.xml file - for (ComponentConfig.ServiceResourceInfo componentResourceInfo: ComponentConfig.getAllServiceResourceInfos("model")) { - futures.add(ExecutionPool.GLOBAL_FORK_JOIN.submit(createServiceReaderCallable(componentResourceInfo.createResourceHandler()))); - } - for (Map<String, ModelService> servicesMap: ExecutionPool.getAllFutures(futures)) { - if (servicesMap != null) { - serviceMap.putAll(servicesMap); - } - } - - if (serviceMap != null) { - Map<String, ModelService> cachedServiceMap = modelServiceMapByModel.putIfAbsentAndGet(this.model, serviceMap); - if (cachedServiceMap == serviceMap) { // same object: this means that the object created by this thread was actually added to the cache - ServiceEcaUtil.reloadConfig(); - } - } - } - return serviceMap; - } } Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/GenericAbstractDispatcher.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/GenericAbstractDispatcher.java?rev=1623295&r1=1623294&r2=1623295&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/GenericAbstractDispatcher.java (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/GenericAbstractDispatcher.java Mon Sep 8 06:04:39 2014 @@ -40,8 +40,7 @@ public abstract class GenericAbstractDis public static final String module = GenericAbstractDispatcher.class.getName(); - protected DispatchContext ctx = null; - protected ServiceDispatcher dispatcher = null; + protected ServiceDispatcher globalDispatcher = null; protected String name = null; public GenericAbstractDispatcher() {} @@ -135,7 +134,7 @@ public abstract class GenericAbstractDis * @see org.ofbiz.service.LocalDispatcher#schedule(java.lang.String, java.util.Map, long, int, int, int, long) */ public void schedule(String serviceName, Map<String, ? extends Object> context, long startTime, int frequency, int interval, int count, long endTime) throws GenericServiceException { - ModelService model = ctx.getModelService(serviceName); + ModelService model = getModelService(serviceName); schedule(null, serviceName, context, startTime, frequency, interval, count, endTime, model.maxRetry); } @@ -180,28 +179,28 @@ public abstract class GenericAbstractDis * @see org.ofbiz.service.LocalDispatcher#getJobManager() */ public JobManager getJobManager() { - return dispatcher.getJobManager(); + return globalDispatcher.getJobManager(); } /** * @see org.ofbiz.service.LocalDispatcher#getJMSListeneFactory() */ public JmsListenerFactory getJMSListeneFactory() { - return dispatcher.getJMSListenerFactory(); + return globalDispatcher.getJMSListenerFactory(); } /** * @see org.ofbiz.service.LocalDispatcher#getDelegator() */ public Delegator getDelegator() { - return dispatcher.getDelegator(); + return globalDispatcher.getDelegator(); } /** * @see org.ofbiz.service.LocalDispatcher#getSecurity() */ public Security getSecurity() { - return dispatcher.getSecurity(); + return globalDispatcher.getSecurity(); } /** @@ -212,25 +211,18 @@ public abstract class GenericAbstractDis } /** - * @see org.ofbiz.service.LocalDispatcher#getDispatchContext() - */ - public DispatchContext getDispatchContext() { - return ctx; - } - - /** * @see org.ofbiz.service.LocalDispatcher#deregister() */ public void deregister() { ServiceContainer.removeFromCache(getName()); - dispatcher.deregister(this); + globalDispatcher.deregister(this); } /** * @see org.ofbiz.service.LocalDispatcher#registerCallback(String, GenericServiceCallback) */ public void registerCallback(String serviceName, GenericServiceCallback cb) { - dispatcher.registerCallback(serviceName, cb); + globalDispatcher.registerCallback(serviceName, cb); } } Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/GenericDispatcherFactory.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/GenericDispatcherFactory.java?rev=1623295&r1=1623294&r2=1623295&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/GenericDispatcherFactory.java (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/GenericDispatcherFactory.java Mon Sep 8 06:04:39 2014 @@ -19,16 +19,22 @@ package org.ofbiz.service; import java.util.Map; +import java.util.Set; +import java.util.TreeSet; import org.ofbiz.base.util.Debug; import org.ofbiz.base.util.UtilValidate; import org.ofbiz.entity.Delegator; +import org.ofbiz.entity.GenericEntityConfException; +import org.ofbiz.entity.config.model.DelegatorElement; +import org.ofbiz.entity.config.model.EntityConfig; /** * A default {@link LocalDispatcherFactory} implementation. */ public class GenericDispatcherFactory implements LocalDispatcherFactory { + public static final String module = GenericDispatcherFactory.class.getName(); protected static boolean ecasDisabled = false; @Override @@ -36,11 +42,25 @@ public class GenericDispatcherFactory im if (UtilValidate.isEmpty(name)) { throw new IllegalArgumentException("The name of a LocalDispatcher cannot be a null or empty String"); } - // attempts to retrieve an already registered DispatchContext with the name "name" + // attempts to retrieve an already registered LocalDispatcher with the name "name" LocalDispatcher dispatcher = ServiceDispatcher.getLocalDispatcher(name, delegator); - // if not found then create a new GenericDispatcher object; the constructor will also register a new DispatchContext in the ServiceDispatcher with name "dispatcherName" + // if not found then create a new GenericDispatcher object if (dispatcher == null) { - dispatcher = new GenericDispatcher(name, delegator); + ServiceDispatcher globalDispatcher = ServiceDispatcher.getInstance(delegator); + String modelName = name; + if (delegator != null) { + DelegatorElement delegatorInfo = null; + try { + delegatorInfo = EntityConfig.getInstance().getDelegator(delegator.getDelegatorBaseName()); + } catch (GenericEntityConfException e) { + Debug.logWarning(e, "Exception thrown while getting delegator config: ", module); + } + if (delegatorInfo != null) { + modelName = delegatorInfo.getEntityModelReader(); + } + } + Map<String, ModelService> serviceMap = globalDispatcher.getGlobalServiceMap(modelName); + dispatcher = globalDispatcher.register(new GenericDispatcher(name, globalDispatcher, serviceMap)); } return dispatcher; } @@ -48,23 +68,23 @@ public class GenericDispatcherFactory im // The default LocalDispatcher implementation. private class GenericDispatcher extends GenericAbstractDispatcher { - private GenericDispatcher(String name, Delegator delegator) { + private final ClassLoader loader; + private final Map<String, ModelService> serviceMap; + + private GenericDispatcher(String name, ServiceDispatcher globalDispatcher, Map<String, ModelService> serviceMap) { ClassLoader loader; try { loader = Thread.currentThread().getContextClassLoader(); } catch (SecurityException e) { loader = this.getClass().getClassLoader(); } + this.loader = loader; this.name = name; - this.dispatcher = ServiceDispatcher.getInstance(delegator); - /* - * FIXME: "this" reference escape. DispatchContext constructor uses - * this object before it is fully constructed. - */ - DispatchContext ctx = new DispatchContext(name, loader, this); - this.dispatcher.register(ctx); - this.ctx = ctx; - if (Debug.verboseOn()) Debug.logVerbose("[GenericDispatcher] : Created Dispatcher for: " + name, module); + this.globalDispatcher = globalDispatcher; + this.serviceMap = serviceMap; + if (Debug.verboseOn()) { + Debug.logVerbose("Created Dispatcher for: " + name, module); + } } @Override @@ -83,14 +103,16 @@ public class GenericDispatcherFactory im } @Override - public Map<String, Object> runSync(String serviceName, Map<String, ? extends Object> context) throws ServiceValidationException, GenericServiceException { - ModelService service = ctx.getModelService(serviceName); - return dispatcher.runSync(this.name, service, context); + public Map<String, Object> runSync(String serviceName, Map<String, ? extends Object> context) + throws ServiceValidationException, GenericServiceException { + ModelService service = getModelService(serviceName); + return globalDispatcher.runSync(this.name, service, context); } @Override - public Map<String, Object> runSync(String serviceName, Map<String, ? extends Object> context, int transactionTimeout, boolean requireNewTransaction) throws ServiceAuthException, ServiceValidationException, GenericServiceException { - ModelService service = ctx.getModelService(serviceName); + public Map<String, Object> runSync(String serviceName, Map<String, ? extends Object> context, int transactionTimeout, + boolean requireNewTransaction) throws ServiceAuthException, ServiceValidationException, GenericServiceException { + ModelService service = getModelService(serviceName); // clone the model service for updates ModelService cloned = new ModelService(service); cloned.requireNewTransaction = requireNewTransaction; @@ -100,23 +122,25 @@ public class GenericDispatcherFactory im if (transactionTimeout != -1) { cloned.transactionTimeout = transactionTimeout; } - return dispatcher.runSync(this.name, cloned, context); + return globalDispatcher.runSync(this.name, cloned, context); } @Override - public Map<String, Object> runSync(String serviceName, int transactionTimeout, boolean requireNewTransaction, Object... context) throws ServiceAuthException, ServiceValidationException, GenericServiceException { + public Map<String, Object> runSync(String serviceName, int transactionTimeout, boolean requireNewTransaction, + Object... context) throws ServiceAuthException, ServiceValidationException, GenericServiceException { return runSync(serviceName, ServiceUtil.makeContext(context), transactionTimeout, requireNewTransaction); } @Override public void runSyncIgnore(String serviceName, Map<String, ? extends Object> context) throws GenericServiceException { - ModelService service = ctx.getModelService(serviceName); - dispatcher.runSyncIgnore(this.name, service, context); + ModelService service = getModelService(serviceName); + globalDispatcher.runSyncIgnore(this.name, service, context); } @Override - public void runSyncIgnore(String serviceName, Map<String, ? extends Object> context, int transactionTimeout, boolean requireNewTransaction) throws ServiceAuthException, ServiceValidationException, GenericServiceException { - ModelService service = ctx.getModelService(serviceName); + public void runSyncIgnore(String serviceName, Map<String, ? extends Object> context, int transactionTimeout, + boolean requireNewTransaction) throws ServiceAuthException, ServiceValidationException, GenericServiceException { + ModelService service = getModelService(serviceName); // clone the model service for updates ModelService cloned = new ModelService(service); cloned.requireNewTransaction = requireNewTransaction; @@ -126,17 +150,20 @@ public class GenericDispatcherFactory im if (transactionTimeout != -1) { cloned.transactionTimeout = transactionTimeout; } - dispatcher.runSyncIgnore(this.name, cloned, context); + globalDispatcher.runSyncIgnore(this.name, cloned, context); } @Override - public void runSyncIgnore(String serviceName, int transactionTimeout, boolean requireNewTransaction, Object... context) throws ServiceAuthException, ServiceValidationException, GenericServiceException { + public void runSyncIgnore(String serviceName, int transactionTimeout, boolean requireNewTransaction, Object... context) + throws ServiceAuthException, ServiceValidationException, GenericServiceException { runSyncIgnore(serviceName, ServiceUtil.makeContext(context), transactionTimeout, requireNewTransaction); } @Override - public void runAsync(String serviceName, Map<String, ? extends Object> context, GenericRequester requester, boolean persist, int transactionTimeout, boolean requireNewTransaction) throws ServiceAuthException, ServiceValidationException, GenericServiceException { - ModelService service = ctx.getModelService(serviceName); + public void runAsync(String serviceName, Map<String, ? extends Object> context, GenericRequester requester, + boolean persist, int transactionTimeout, boolean requireNewTransaction) throws ServiceAuthException, + ServiceValidationException, GenericServiceException { + ModelService service = getModelService(serviceName); // clone the model service for updates ModelService cloned = new ModelService(service); cloned.requireNewTransaction = requireNewTransaction; @@ -146,67 +173,104 @@ public class GenericDispatcherFactory im if (transactionTimeout != -1) { cloned.transactionTimeout = transactionTimeout; } - dispatcher.runAsync(this.name, cloned, context, requester, persist); + globalDispatcher.runAsync(this.name, cloned, context, requester, persist); } @Override - public void runAsync(String serviceName, GenericRequester requester, boolean persist, int transactionTimeout, boolean requireNewTransaction, Object... context) throws ServiceAuthException, ServiceValidationException, GenericServiceException { + public void runAsync(String serviceName, GenericRequester requester, boolean persist, int transactionTimeout, + boolean requireNewTransaction, Object... context) throws ServiceAuthException, ServiceValidationException, + GenericServiceException { runAsync(serviceName, ServiceUtil.makeContext(context), requester, persist, transactionTimeout, requireNewTransaction); } @Override - public void runAsync(String serviceName, Map<String, ? extends Object> context, GenericRequester requester, boolean persist) throws ServiceAuthException, ServiceValidationException, GenericServiceException { - ModelService service = ctx.getModelService(serviceName); - dispatcher.runAsync(this.name, service, context, requester, persist); + public void runAsync(String serviceName, Map<String, ? extends Object> context, GenericRequester requester, + boolean persist) throws ServiceAuthException, ServiceValidationException, GenericServiceException { + ModelService service = getModelService(serviceName); + globalDispatcher.runAsync(this.name, service, context, requester, persist); } @Override - public void runAsync(String serviceName, GenericRequester requester, boolean persist, Object... context) throws ServiceAuthException, ServiceValidationException, GenericServiceException { + public void runAsync(String serviceName, GenericRequester requester, boolean persist, Object... context) + throws ServiceAuthException, ServiceValidationException, GenericServiceException { runAsync(serviceName, ServiceUtil.makeContext(context), requester, persist); } @Override - public void runAsync(String serviceName, Map<String, ? extends Object> context, GenericRequester requester) throws ServiceAuthException, ServiceValidationException, GenericServiceException { + public void runAsync(String serviceName, Map<String, ? extends Object> context, GenericRequester requester) + throws ServiceAuthException, ServiceValidationException, GenericServiceException { runAsync(serviceName, context, requester, true); } @Override - public void runAsync(String serviceName, GenericRequester requester, Object... context) throws ServiceAuthException, ServiceValidationException, GenericServiceException { + public void runAsync(String serviceName, GenericRequester requester, Object... context) throws ServiceAuthException, + ServiceValidationException, GenericServiceException { runAsync(serviceName, ServiceUtil.makeContext(context), requester); } @Override - public void runAsync(String serviceName, Map<String, ? extends Object> context, boolean persist) throws ServiceAuthException, ServiceValidationException, GenericServiceException { - ModelService service = ctx.getModelService(serviceName); - dispatcher.runAsync(this.name, service, context, persist); + public void runAsync(String serviceName, Map<String, ? extends Object> context, boolean persist) + throws ServiceAuthException, ServiceValidationException, GenericServiceException { + ModelService service = getModelService(serviceName); + globalDispatcher.runAsync(this.name, service, context, persist); } @Override - public void runAsync(String serviceName, boolean persist, Object... context) throws ServiceAuthException, ServiceValidationException, GenericServiceException { + public void runAsync(String serviceName, boolean persist, Object... context) throws ServiceAuthException, + ServiceValidationException, GenericServiceException { runAsync(serviceName, ServiceUtil.makeContext(context), persist); } @Override - public void runAsync(String serviceName, Map<String, ? extends Object> context) throws ServiceAuthException, ServiceValidationException, GenericServiceException { + public void runAsync(String serviceName, Map<String, ? extends Object> context) throws ServiceAuthException, + ServiceValidationException, GenericServiceException { runAsync(serviceName, context, true); } @Override - public GenericResultWaiter runAsyncWait(String serviceName, Map<String, ? extends Object> context, boolean persist) throws ServiceAuthException, ServiceValidationException, GenericServiceException { + public GenericResultWaiter runAsyncWait(String serviceName, Map<String, ? extends Object> context, boolean persist) + throws ServiceAuthException, ServiceValidationException, GenericServiceException { GenericResultWaiter waiter = new GenericResultWaiter(); this.runAsync(serviceName, context, waiter, persist); return waiter; } @Override - public GenericResultWaiter runAsyncWait(String serviceName, boolean persist, Object... context) throws ServiceAuthException, ServiceValidationException, GenericServiceException { + public GenericResultWaiter runAsyncWait(String serviceName, boolean persist, Object... context) + throws ServiceAuthException, ServiceValidationException, GenericServiceException { return runAsyncWait(serviceName, ServiceUtil.makeContext(context), persist); } @Override - public GenericResultWaiter runAsyncWait(String serviceName, Map<String, ? extends Object> context) throws ServiceAuthException, ServiceValidationException, GenericServiceException { + public GenericResultWaiter runAsyncWait(String serviceName, Map<String, ? extends Object> context) + throws ServiceAuthException, ServiceValidationException, GenericServiceException { return runAsyncWait(serviceName, context, true); } - } + @Override + public DispatchContext getDispatchContext() { + return new DispatchContext(this); + } + + @Override + public Set<String> getAllServiceNames() { + Set<String> serviceNames = new TreeSet<String>(); + serviceNames.addAll(serviceMap.keySet()); + return serviceNames; + } + + @Override + public ModelService getModelService(String serviceName) throws GenericServiceException { + ModelService modelService = serviceMap.get(serviceName); + if (modelService == null) { + throw new GenericServiceException("ModelService not found for name: " + serviceName); + } + return modelService; + } + + @Override + public ClassLoader getClassLoader() { + return loader; + } + } } Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/LocalDispatcher.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/LocalDispatcher.java?rev=1623295&r1=1623294&r2=1623295&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/LocalDispatcher.java (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/LocalDispatcher.java Mon Sep 8 06:04:39 2014 @@ -19,6 +19,7 @@ package org.ofbiz.service; import java.util.Map; +import java.util.Set; import org.ofbiz.entity.Delegator; import org.ofbiz.security.Security; @@ -26,11 +27,11 @@ import org.ofbiz.service.jms.JmsListener import org.ofbiz.service.job.JobManager; /** - * A local service dispatcher. This is the main API for the service engine. - * <p>Instances of <code>LocalDispatcher</code> are based on a {@link org.ofbiz.entity.Delegator} - * instance and an entity model reader name. You can get a <code>LocalDispatcher</code> instance - * by calling the {@link org.ofbiz.service.ServiceDispatcher#getLocalDispatcher(String, Delegator)} - * factory method.</p> + * A local service dispatcher. + * <p> A LocalDispatcher is associated with an application. Applications never talk directly to the ServiceDispatcher. + * The LocalDispatcher contains an API for invoking services, which are routed through the ServiceDispatcher. + * However, applications may be running in different threads than the actual ServiceDispatcher, so it is left to the + * LocalDispatcher to keep a reference to the application's classloader.</p> */ public interface LocalDispatcher { @@ -345,5 +346,11 @@ public interface LocalDispatcher { * De-Registers this LocalDispatcher */ void deregister(); + + ModelService getModelService(String serviceName) throws GenericServiceException; + + Set<String> getAllServiceNames(); + + ClassLoader getClassLoader(); } Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/ModelService.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/ModelService.java?rev=1623295&r1=1623294&r2=1623295&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/ModelService.java (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/ModelService.java Mon Sep 8 06:04:39 2014 @@ -1092,9 +1092,9 @@ public class ModelService extends Abstra /** * Run the interface update and inherit all interface parameters - * @param dctx The DispatchContext to use for service lookups + * @param serviceMap The Map to use for service lookups */ - public synchronized void interfaceUpdate(DispatchContext dctx) throws GenericServiceException { + public synchronized void interfaceUpdate(Map<String, ModelService> serviceMap) throws GenericServiceException { if (!inheritedParameters) { // services w/ engine 'group' auto-implement the grouped services if (this.engineName.equals("group") && implServices.size() == 0) { @@ -1111,13 +1111,15 @@ public class ModelService extends Abstra } // handle interfaces - if (UtilValidate.isNotEmpty(implServices) && dctx != null) { + if (UtilValidate.isNotEmpty(implServices) && serviceMap != null) { for (ModelServiceIface iface: implServices) { String serviceName = iface.getService(); boolean optional = iface.isOptional(); - - ModelService model = dctx.getModelService(serviceName); + ModelService model = serviceMap.get(serviceName); if (model != null) { + if (!model.inheritedParameters()) { + model.interfaceUpdate(serviceMap); + } for (ModelParam newParam: model.contextParamList) { ModelParam existingParam = this.contextInfo.get(newParam.name); if (existingParam != null) { Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/ModelServiceReader.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/ModelServiceReader.java?rev=1623295&r1=1623294&r2=1623295&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/ModelServiceReader.java (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/ModelServiceReader.java Mon Sep 8 06:04:39 2014 @@ -51,8 +51,6 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; -import freemarker.template.utility.StringUtil; - /** * Generic Service - Service Definition Reader */ @@ -182,11 +180,11 @@ public class ModelServiceReader implemen } if (this.isFromURL) { utilTimer.timerString("Finished file " + readerURL + " - Total Services: " + i + " FINISHED"); - Debug.logInfo("Loaded [" + StringUtil.leftPad(Integer.toString(i), 3) + "] Services from " + readerURL, module); + Debug.logInfo("Loaded [" + i + "] Services from " + readerURL, module); } else { utilTimer.timerString("Finished document in " + handler + " - Total Services: " + i + " FINISHED"); if (Debug.infoOn()) { - Debug.logInfo("Loaded [" + StringUtil.leftPad(Integer.toString(i), 3) + "] Services from " + resourceLocation, module); + Debug.logInfo("Loaded [" + i + "] Services from " + resourceLocation, module); } } return modelServices; Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/ServiceDispatcher.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/ServiceDispatcher.java?rev=1623295&r1=1623294&r2=1623295&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/ServiceDispatcher.java (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/ServiceDispatcher.java Mon Sep 8 06:04:39 2014 @@ -18,22 +18,30 @@ *******************************************************************************/ package org.ofbiz.service; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Future; import javax.transaction.Transaction; +import org.ofbiz.base.component.ComponentConfig; +import org.ofbiz.base.concurrent.ExecutionPool; import org.ofbiz.base.config.GenericConfigException; +import org.ofbiz.base.config.MainResourceHandler; +import org.ofbiz.base.config.ResourceHandler; import org.ofbiz.base.util.Debug; import org.ofbiz.base.util.GeneralRuntimeException; import org.ofbiz.base.util.UtilMisc; import org.ofbiz.base.util.UtilProperties; import org.ofbiz.base.util.UtilTimer; import org.ofbiz.base.util.UtilValidate; +import org.ofbiz.base.util.cache.UtilCache; import org.ofbiz.entity.Delegator; import org.ofbiz.entity.DelegatorFactory; import org.ofbiz.entity.GenericDelegator; @@ -46,6 +54,7 @@ import org.ofbiz.security.Security; import org.ofbiz.security.SecurityConfigurationException; import org.ofbiz.security.SecurityFactory; import org.ofbiz.service.config.ServiceConfigUtil; +import org.ofbiz.service.config.model.GlobalServices; import org.ofbiz.service.config.model.StartupService; import org.ofbiz.service.eca.ServiceEcaRule; import org.ofbiz.service.eca.ServiceEcaUtil; @@ -60,8 +69,12 @@ import org.ofbiz.service.semaphore.Servi import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap; /** - * The global service dispatcher. This is the "engine" part of the - * Service Engine. + * The global service dispatcher. + * <p>The Service Dispatcher handles dispatching services to the appropriate Service Engine where it is then invoked. + * There is exactly one ServiceDispatcher for each Entity Delegator. If there are multiple delegators in an application + * there will also be multiple dispatchers. The ServiceDispatcher is accessed via a LocalDispatcher. There can be many + * LocalDispatchers associated with a ServiceDispatcher. Each LocalDispatcher is uniquely named and contains its own + * list of service definitions.</p> */ public class ServiceDispatcher { @@ -69,6 +82,7 @@ public class ServiceDispatcher { public static final int lruLogSize = 200; public static final int LOCK_RETRIES = 3; + private static final UtilCache<String, Map<String, ModelService>> modelServiceMapByModel = UtilCache.createUtilCache("service.ModelServiceMapByModel", 0, 0, false); protected static final Map<RunningService, ServiceDispatcher> runLog = new ConcurrentLinkedHashMap.Builder<RunningService, ServiceDispatcher>().maximumWeightedCapacity(lruLogSize).build(); protected static ConcurrentHashMap<String, ServiceDispatcher> dispatchers = new ConcurrentHashMap<String, ServiceDispatcher>(); // FIXME: These fields are not thread-safe. They are modified by EntityDataLoadContainer. @@ -80,7 +94,7 @@ public class ServiceDispatcher { protected Delegator delegator = null; protected GenericEngineFactory factory = null; protected Security security = null; - protected Map<String, DispatchContext> localContext = new HashMap<String, DispatchContext>(); + protected ConcurrentHashMap<String, LocalDispatcher> localDispatchers = new ConcurrentHashMap<String, LocalDispatcher>(); protected Map<String, List<GenericServiceCallback>> callbacks = new HashMap<String, List<GenericServiceCallback>>(); protected JobManager jm = null; protected JmsListenerFactory jlf = null; @@ -174,21 +188,25 @@ public class ServiceDispatcher { } /** - * Registers the loader with this ServiceDispatcher - * @param context the context of the local dispatcher + * Registers the LocalDispatcher with this ServiceDispatcher + * @param local */ - public void register(DispatchContext context) { - if (Debug.infoOn()) Debug.logInfo("Registering dispatcher: " + context.getName(), module); - this.localContext.put(context.getName(), context); + public LocalDispatcher register(LocalDispatcher local) { + if (Debug.infoOn()) { + Debug.logInfo("Registering dispatcher: " + local.getName(), module); + } + localDispatchers.putIfAbsent(local.getName(), local); + return localDispatchers.get(local.getName()); } + /** * De-Registers the loader with this ServiceDispatcher * @param local the LocalDispatcher to de-register */ public void deregister(LocalDispatcher local) { if (Debug.infoOn()) Debug.logInfo("De-Registering dispatcher: " + local.getName(), module); - localContext.remove(local.getName()); - if (localContext.size() == 0) { + localDispatchers.remove(local.getName()); + if (localDispatchers.size() == 0) { try { this.shutdown(); } catch (GenericServiceException e) { @@ -255,7 +273,7 @@ public class ServiceDispatcher { Map<String, List<ServiceEcaRule>> eventMap = null; Map<String, Object> ecaContext = null; RunningService rs = null; - DispatchContext ctx = localContext.get(localName); + DispatchContext ctx = getLocalContext(localName); GenericEngine engine = null; Transaction parentTransaction = null; boolean isFailure = false; @@ -641,7 +659,7 @@ public class ServiceDispatcher { Locale locale = this.checkLocale(context); // setup the engine and context - DispatchContext ctx = localContext.get(localName); + DispatchContext ctx = getLocalContext(localName); GenericEngine engine = this.getGenericEngine(service.engineName); // for isolated transactions @@ -822,7 +840,11 @@ public class ServiceDispatcher { * @param name of the context to find. */ public DispatchContext getLocalContext(String name) { - return localContext.get(name); + LocalDispatcher local = localDispatchers.get(name); + if (local != null) { + return new DispatchContext(local); + } + return null; } /** @@ -831,7 +853,7 @@ public class ServiceDispatcher { * @return LocalDispatcher matching the loader name */ public LocalDispatcher getLocalDispatcher(String name) { - return localContext.get(name).getDispatcher(); + return localDispatchers.get(name); } /** @@ -840,7 +862,7 @@ public class ServiceDispatcher { * @return true if the local context is found in this dispatcher. */ public boolean containsContext(String name) { - return localContext.containsKey(name); + return localDispatchers.containsKey(name); } protected void shutdown() throws GenericServiceException { @@ -1053,4 +1075,58 @@ public class ServiceDispatcher { return runLog; } + private Callable<Map<String, ModelService>> createServiceReaderCallable(final ResourceHandler handler) { + return new Callable<Map<String, ModelService>>() { + public Map<String, ModelService> call() throws Exception { + return ModelServiceReader.getModelServiceMap(handler, delegator); + } + }; + } + + Map<String, ModelService> getGlobalServiceMap(String model) { + Map<String, ModelService> serviceMap = modelServiceMapByModel.get(model); + if (serviceMap == null) { + serviceMap = new HashMap<String, ModelService>(); + List<Future<Map<String, ModelService>>> futures = new LinkedList<Future<Map<String, ModelService>>>(); + List<GlobalServices> globalServicesList = null; + try { + globalServicesList = ServiceConfigUtil.getServiceEngine().getGlobalServices(); + } catch (GenericConfigException e) { + // FIXME: Refactor API so exceptions can be thrown and caught. + Debug.logError(e, module); + throw new RuntimeException(e.getMessage()); + } + for (GlobalServices globalServices : globalServicesList) { + ResourceHandler handler = new MainResourceHandler(ServiceConfigUtil.SERVICE_ENGINE_XML_FILENAME, globalServices.getLoader(), globalServices.getLocation()); + futures.add(ExecutionPool.GLOBAL_FORK_JOIN.submit(createServiceReaderCallable(handler))); + } + + // get all of the component resource model stuff, ie specified in each ofbiz-component.xml file + for (ComponentConfig.ServiceResourceInfo componentResourceInfo: ComponentConfig.getAllServiceResourceInfos("model")) { + futures.add(ExecutionPool.GLOBAL_FORK_JOIN.submit(createServiceReaderCallable(componentResourceInfo.createResourceHandler()))); + } + for (Map<String, ModelService> servicesMap: ExecutionPool.getAllFutures(futures)) { + if (servicesMap != null) { + serviceMap.putAll(servicesMap); + } + } + for (ModelService modelService : serviceMap.values()) { + if (!modelService.inheritedParameters()) { + try { + modelService.interfaceUpdate(serviceMap); + } catch (GenericServiceException e) { + Debug.logError(e, module); + throw new RuntimeException(e.getMessage()); + } + } + } + serviceMap = Collections.unmodifiableMap(serviceMap); + Map<String, ModelService> cachedServiceMap = modelServiceMapByModel.putIfAbsentAndGet(model, serviceMap); + if (cachedServiceMap == serviceMap) { // same object: this means that the object created by this thread was actually added to the cache + ServiceEcaUtil.reloadConfig(); + } + } + return serviceMap; + } + } Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/eca/ServiceEcaUtil.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/eca/ServiceEcaUtil.java?rev=1623295&r1=1623294&r2=1623295&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/eca/ServiceEcaUtil.java (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/eca/ServiceEcaUtil.java Mon Sep 8 06:04:39 2014 @@ -43,8 +43,6 @@ import org.ofbiz.service.config.ServiceC import org.ofbiz.service.config.model.ServiceEcas; import org.w3c.dom.Element; -import freemarker.template.utility.StringUtil; - /** * ServiceEcaUtil */ @@ -123,7 +121,7 @@ public class ServiceEcaUtil { handlerRules.add(new ServiceEcaRule(e, resourceLocation)); } if (Debug.infoOn()) { - Debug.logInfo("Loaded [" + StringUtil.leftPad(Integer.toString(handlerRules.size()), 3) + "] Service ECA Rules from " + resourceLocation, module); + Debug.logInfo("Loaded [" + handlerRules.size() + "] Service ECA Rules from " + resourceLocation, module); } return handlerRules; } Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/group/ServiceGroupReader.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/group/ServiceGroupReader.java?rev=1623295&r1=1623294&r2=1623295&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/group/ServiceGroupReader.java (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/service/src/org/ofbiz/service/group/ServiceGroupReader.java Mon Sep 8 06:04:39 2014 @@ -33,8 +33,6 @@ import org.ofbiz.service.config.ServiceC import org.ofbiz.service.config.model.ServiceGroups; import org.w3c.dom.Element; -import freemarker.template.utility.StringUtil; - /** * ServiceGroupReader.java */ @@ -88,7 +86,7 @@ public class ServiceGroupReader { } catch (GenericConfigException e) { Debug.logError(e, "Could not get resource URL", module); } - Debug.logInfo("Loaded [" + StringUtil.leftPad(Integer.toString(numDefs), 3) + "] Group definitions from " + resourceLocation, module); + Debug.logInfo("Loaded [" + numDefs + "] Group definitions from " + resourceLocation, module); } } |
Free forum by Nabble | Edit this page |