You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2014/11/22 17:03:39 UTC
cayenne git commit: CAY-1972 A property to override DataSources of
multi-module projects
Repository: cayenne
Updated Branches:
refs/heads/master 3c51a773c -> 15297ccaf
CAY-1972 A property to override DataSources of multi-module projects
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/15297cca
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/15297cca
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/15297cca
Branch: refs/heads/master
Commit: 15297ccafa761bddb89eac98b35806d777cbbe74
Parents: 3c51a77
Author: aadamchik <aa...@apache.org>
Authored: Sat Nov 22 18:06:09 2014 +0300
Committer: aadamchik <aa...@apache.org>
Committed: Sat Nov 22 19:03:31 2014 +0300
----------------------------------------------------------------------
.../apache/cayenne/configuration/Constants.java | 298 ++++++++++---------
.../server/DataDomainProvider.java | 241 ++++++++-------
.../server/ServerRuntimeBuilder.java | 52 +++-
.../server/SyntheticNodeDataDomainProvider.java | 27 +-
.../server/ServerRuntimeBuilderIT.java | 109 +++++++
.../server/ServerRuntimeBuilderTest.java | 53 +++-
.../ServerRuntimeBuilder_InAction_IT.java | 88 ------
docs/doc/src/main/resources/RELEASE-NOTES.txt | 1 +
docs/doc/src/main/resources/UPGRADE.txt | 8 +
9 files changed, 491 insertions(+), 386 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/15297cca/cayenne-server/src/main/java/org/apache/cayenne/configuration/Constants.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/Constants.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/Constants.java
index 12953e6..1b0f887 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/Constants.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/Constants.java
@@ -26,151 +26,159 @@ package org.apache.cayenne.configuration;
*/
public interface Constants {
- // DI "collections"
+ // DI "collections"
+
+ /**
+ * A DI container key for the Map<String, String> storing properties
+ * used by built-in Cayenne service.
+ */
+ public static final String PROPERTIES_MAP = "cayenne.properties";
+
+ /**
+ * A DI container key for the List<DbAdapterDetector> that contains
+ * objects that can discover the type of current database and install the
+ * correct DbAdapter in runtime.
+ */
+ public static final String SERVER_ADAPTER_DETECTORS_LIST = "cayenne.server.adapter_detectors";
- /**
- * A DI container key for the Map<String, String> storing properties
- * used by built-in Cayenne service.
- */
- public static final String PROPERTIES_MAP = "cayenne.properties";
-
- /**
- * A DI container key for the List<DbAdapterDetector> that contains
- * objects that can discover the type of current database and install the
- * correct DbAdapter in runtime.
- */
- public static final String SERVER_ADAPTER_DETECTORS_LIST = "cayenne.server.adapter_detectors";
-
- /**
- * A DI container key for the List<DataChannelFilter> storing
- * DataDomain filters.
- */
- public static final String SERVER_DOMAIN_FILTERS_LIST = "cayenne.server.domain_filters";
-
- /**
- * A DI container key for the List<String> storing locations of the
- * one of more project configuration files.
- */
- public static final String SERVER_PROJECT_LOCATIONS_LIST = "cayenne.server.project_locations";
-
- /**
- * A DI container key for the List<ExtendedType> storing default
- * adapter-agnostic ExtendedTypes.
- */
- public static final String SERVER_DEFAULT_TYPES_LIST = "cayenne.server.default_types";
-
- /**
- * A DI container key for the List<ExtendedType> storing a
- * user-provided ExtendedTypes.
- */
- public static final String SERVER_USER_TYPES_LIST = "cayenne.server.user_types";
-
- /**
- * A DI container key for the List<ExtendedTypeFactory> storing
- * default and user-provided ExtendedTypeFactories.
- */
- public static final String SERVER_TYPE_FACTORIES_LIST = "cayenne.server.type_factories";
-
- /**
- * A server-side DI container key for the Map<String, String> storing
- * event bridge properties passed to the ROP client on bootstrap.
- */
- public static final String SERVER_ROP_EVENT_BRIDGE_PROPERTIES_MAP = "cayenne.server.rop_event_bridge_properties";
-
- // Runtime properties
-
- public static final String JDBC_DRIVER_PROPERTY = "cayenne.jdbc.driver";
-
- public static final String JDBC_URL_PROPERTY = "cayenne.jdbc.url";
-
- public static final String JDBC_USERNAME_PROPERTY = "cayenne.jdbc.username";
-
- public static final String JDBC_PASSWORD_PROPERTY = "cayenne.jdbc.password";
-
- public static final String JDBC_MIN_CONNECTIONS_PROPERTY = "cayenne.jdbc.min_connections";
-
- public static final String JDBC_MAX_CONNECTIONS_PROPERTY = "cayenne.jdbc.max_connections";
-
- /**
- * An integer property defining the maximum number of entries in the query
- * cache. Note that not all QueryCache providers may respect this property.
- * MapQueryCache uses it, but the rest would use alternative configuration
- * methods.
- */
- public static final String QUERY_CACHE_SIZE_PROPERTY = "cayenne.querycache.size";
-
- /**
- * A boolean property defining whether cross-contexts synchronization is
- * enabled. Possible values are "true" or "false".
- */
- public static final String SERVER_CONTEXTS_SYNC_PROPERTY = "cayenne.server.contexts_sync_strategy";
-
- /**
- * A String property that defines how ObjectContexts should retain cached
- * committed objects. Possible values are "weak", "soft", "hard".
- */
- public static final String SERVER_OBJECT_RETAIN_STRATEGY_PROPERTY = "cayenne.server.object_retain_strategy";
-
- /**
- * A boolean property that defines whether runtime should use external
- * transactions. Possible values are "true" or "false".
- */
- public static final String SERVER_EXTERNAL_TX_PROPERTY = "cayenne.server.external_tx";
-
- public static final String ROP_SERVICE_URL_PROPERTY = "cayenne.rop.service_url";
-
- public static final String ROP_SERVICE_USERNAME_PROPERTY = "cayenne.rop.service_username";
-
- public static final String ROP_SERVICE_PASSWORD_PROPERTY = "cayenne.rop.service_password";
-
- public static final String ROP_SERVICE_SHARED_SESSION_PROPERTY = "cayenne.rop.shared_session_name";
-
- public static final String ROP_SERVICE_TIMEOUT_PROPERTY = "cayenne.rop.service_timeout";
-
- public static final String ROP_CHANNEL_EVENTS_PROPERTY = "cayenne.rop.channel_events";
-
- public static final String ROP_CONTEXT_CHANGE_EVENTS_PROPERTY = "cayenne.rop.context_change_events";
-
- public static final String ROP_CONTEXT_LIFECYCLE_EVENTS_PROPERTY = "cayenne.rop.context_lifecycle_events";
-
- /**
- * The name of the {@link org.apache.cayenne.event.EventBridgeFactory} that
- * is passed from the ROP server to the client. Client would instantiate the
- * factory to receive events from the server. Note that this property is
- * stored in {@link #SERVER_ROP_EVENT_BRIDGE_PROPERTIES_MAP}, not
- * {@link #PROPERTIES_MAP}.
- */
- public static final String SERVER_ROP_EVENT_BRIDGE_FACTORY_PROPERTY = "cayenne.server.rop_event_bridge_factory";
-
- /**
- * A property that defines a maximum number of ID qualifiers in where clause
- * of queries that are generated for example in
- * {@link org.apache.cayenne.access.IncrementalFaultList} or in
- * DISJOINT_BY_ID prefetch processing. This is needed to avoid where clause
- * size limitations and memory usage efficiency.
- */
- public static final String SERVER_MAX_ID_QUALIFIER_SIZE_PROPERTY = "cayenne.server.max_id_qualifier_size";
-
- /**
- * Defines a maximum time in milliseconds that a connection request could
- * wait in the connection queue. After this period expires, an exception
- * will be thrown in the calling method. A value of zero will make the
- * thread wait until a connection is available with no time out. Defaults to
- * 20 seconds.
- */
- public static final String SERVER_MAX_QUEUE_WAIT_TIME = "cayenne.jdbc.max_wait";
-
- /** Defines if database uses case-insensitive collation */
- public final static String CI_PROPERTY = "cayenne.runtime.db.collation.assume.ci";
-
- /**
- * A integer property that enables logging for just long running queries
- * (rather than all queries). The value is the minimum number of
- * milliseconds a query must run before is logged. A value less than or
- * equal to zero (the default) disables this feature.
- *
- * @since 4.0
- * */
- public final static String QUERY_EXECUTION_TIME_LOGGING_THRESHOLD_PROPERTY = "cayenne.server.query_execution_time_logging_threshold";
+ /**
+ * A DI container key for the List<DataChannelFilter> storing
+ * DataDomain filters.
+ */
+ public static final String SERVER_DOMAIN_FILTERS_LIST = "cayenne.server.domain_filters";
+
+ /**
+ * A DI container key for the List<String> storing locations of the
+ * one of more project configuration files.
+ */
+ public static final String SERVER_PROJECT_LOCATIONS_LIST = "cayenne.server.project_locations";
+
+ /**
+ * A DI container key for the List<ExtendedType> storing default
+ * adapter-agnostic ExtendedTypes.
+ */
+ public static final String SERVER_DEFAULT_TYPES_LIST = "cayenne.server.default_types";
+
+ /**
+ * A DI container key for the List<ExtendedType> storing a
+ * user-provided ExtendedTypes.
+ */
+ public static final String SERVER_USER_TYPES_LIST = "cayenne.server.user_types";
+
+ /**
+ * A DI container key for the List<ExtendedTypeFactory> storing
+ * default and user-provided ExtendedTypeFactories.
+ */
+ public static final String SERVER_TYPE_FACTORIES_LIST = "cayenne.server.type_factories";
+
+ /**
+ * A server-side DI container key for the Map<String, String> storing
+ * event bridge properties passed to the ROP client on bootstrap.
+ */
+ public static final String SERVER_ROP_EVENT_BRIDGE_PROPERTIES_MAP = "cayenne.server.rop_event_bridge_properties";
+
+ // Runtime properties
+
+ public static final String JDBC_DRIVER_PROPERTY = "cayenne.jdbc.driver";
+
+ public static final String JDBC_URL_PROPERTY = "cayenne.jdbc.url";
+
+ public static final String JDBC_USERNAME_PROPERTY = "cayenne.jdbc.username";
+
+ public static final String JDBC_PASSWORD_PROPERTY = "cayenne.jdbc.password";
+
+ public static final String JDBC_MIN_CONNECTIONS_PROPERTY = "cayenne.jdbc.min_connections";
+
+ public static final String JDBC_MAX_CONNECTIONS_PROPERTY = "cayenne.jdbc.max_connections";
+
+ /**
+ * An integer property defining the maximum number of entries in the query
+ * cache. Note that not all QueryCache providers may respect this property.
+ * MapQueryCache uses it, but the rest would use alternative configuration
+ * methods.
+ */
+ public static final String QUERY_CACHE_SIZE_PROPERTY = "cayenne.querycache.size";
+
+ /**
+ * An optional name of the runtime DataDomain. If not specified (which is
+ * normally the case), the name is inferred from the configuration name.
+ *
+ * @since 4.0
+ */
+ public static final String SERVER_DOMAIN_NAME_PROPERTY = "cayenne.server.domain.name";
+
+ /**
+ * A boolean property defining whether cross-contexts synchronization is
+ * enabled. Possible values are "true" or "false".
+ */
+ public static final String SERVER_CONTEXTS_SYNC_PROPERTY = "cayenne.server.contexts_sync_strategy";
+
+ /**
+ * A String property that defines how ObjectContexts should retain cached
+ * committed objects. Possible values are "weak", "soft", "hard".
+ */
+ public static final String SERVER_OBJECT_RETAIN_STRATEGY_PROPERTY = "cayenne.server.object_retain_strategy";
+
+ /**
+ * A boolean property that defines whether runtime should use external
+ * transactions. Possible values are "true" or "false".
+ */
+ public static final String SERVER_EXTERNAL_TX_PROPERTY = "cayenne.server.external_tx";
+
+ public static final String ROP_SERVICE_URL_PROPERTY = "cayenne.rop.service_url";
+
+ public static final String ROP_SERVICE_USERNAME_PROPERTY = "cayenne.rop.service_username";
+
+ public static final String ROP_SERVICE_PASSWORD_PROPERTY = "cayenne.rop.service_password";
+
+ public static final String ROP_SERVICE_SHARED_SESSION_PROPERTY = "cayenne.rop.shared_session_name";
+
+ public static final String ROP_SERVICE_TIMEOUT_PROPERTY = "cayenne.rop.service_timeout";
+
+ public static final String ROP_CHANNEL_EVENTS_PROPERTY = "cayenne.rop.channel_events";
+
+ public static final String ROP_CONTEXT_CHANGE_EVENTS_PROPERTY = "cayenne.rop.context_change_events";
+
+ public static final String ROP_CONTEXT_LIFECYCLE_EVENTS_PROPERTY = "cayenne.rop.context_lifecycle_events";
+
+ /**
+ * The name of the {@link org.apache.cayenne.event.EventBridgeFactory} that
+ * is passed from the ROP server to the client. Client would instantiate the
+ * factory to receive events from the server. Note that this property is
+ * stored in {@link #SERVER_ROP_EVENT_BRIDGE_PROPERTIES_MAP}, not
+ * {@link #PROPERTIES_MAP}.
+ */
+ public static final String SERVER_ROP_EVENT_BRIDGE_FACTORY_PROPERTY = "cayenne.server.rop_event_bridge_factory";
+
+ /**
+ * A property that defines a maximum number of ID qualifiers in where clause
+ * of queries that are generated for example in
+ * {@link org.apache.cayenne.access.IncrementalFaultList} or in
+ * DISJOINT_BY_ID prefetch processing. This is needed to avoid where clause
+ * size limitations and memory usage efficiency.
+ */
+ public static final String SERVER_MAX_ID_QUALIFIER_SIZE_PROPERTY = "cayenne.server.max_id_qualifier_size";
+
+ /**
+ * Defines a maximum time in milliseconds that a connection request could
+ * wait in the connection queue. After this period expires, an exception
+ * will be thrown in the calling method. A value of zero will make the
+ * thread wait until a connection is available with no time out. Defaults to
+ * 20 seconds.
+ */
+ public static final String SERVER_MAX_QUEUE_WAIT_TIME = "cayenne.jdbc.max_wait";
+
+ /** Defines if database uses case-insensitive collation */
+ public final static String CI_PROPERTY = "cayenne.runtime.db.collation.assume.ci";
+
+ /**
+ * A integer property that enables logging for just long running queries
+ * (rather than all queries). The value is the minimum number of
+ * milliseconds a query must run before is logged. A value less than or
+ * equal to zero (the default) disables this feature.
+ *
+ * @since 4.0
+ * */
+ public final static String QUERY_EXECUTION_TIME_LOGGING_THRESHOLD_PROPERTY = "cayenne.server.query_execution_time_logging_threshold";
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/15297cca/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DataDomainProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DataDomainProvider.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DataDomainProvider.java
index f1a8d57..4815fe4 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DataDomainProvider.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DataDomainProvider.java
@@ -55,173 +55,172 @@ import org.apache.commons.logging.LogFactory;
*/
public class DataDomainProvider implements Provider<DataDomain> {
- /**
- * @since 4.0
- */
- static final String DEFAULT_NAME = "cayenne";
+ private static Log logger = LogFactory.getLog(DataDomainProvider.class);
- private static Log logger = LogFactory.getLog(DataDomainProvider.class);
+ @Inject
+ protected ResourceLocator resourceLocator;
- @Inject
- protected ResourceLocator resourceLocator;
+ @Inject
+ protected DataChannelDescriptorMerger descriptorMerger;
- @Inject
- protected DataChannelDescriptorMerger descriptorMerger;
+ @Inject
+ protected DataChannelDescriptorLoader loader;
- @Inject
- protected DataChannelDescriptorLoader loader;
+ @Inject(Constants.SERVER_DOMAIN_FILTERS_LIST)
+ protected List<DataChannelFilter> filters;
- @Inject(Constants.SERVER_DOMAIN_FILTERS_LIST)
- protected List<DataChannelFilter> filters;
+ @Inject(Constants.SERVER_PROJECT_LOCATIONS_LIST)
+ protected List<String> locations;
- @Inject(Constants.SERVER_PROJECT_LOCATIONS_LIST)
- protected List<String> locations;
+ @Inject
+ protected Injector injector;
- @Inject
- protected Injector injector;
+ @Inject
+ protected QueryCache queryCache;
- @Inject
- protected QueryCache queryCache;
+ @Inject
+ protected RuntimeProperties runtimeProperties;
- @Inject
- protected RuntimeProperties runtimeProperties;
+ @Inject
+ protected DataNodeFactory dataNodeFactory;
- @Inject
- protected DataNodeFactory dataNodeFactory;
+ @Override
+ public DataDomain get() throws ConfigurationException {
- @Override
- public DataDomain get() throws ConfigurationException {
+ try {
+ return createAndInitDataDomain();
+ } catch (ConfigurationException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new DataDomainLoadException("Error loading DataChannel: '%s'", e, e.getMessage());
+ }
+ }
- try {
- return createAndInitDataDomain();
- } catch (ConfigurationException e) {
- throw e;
- } catch (Exception e) {
- throw new DataDomainLoadException("Error loading DataChannel: '%s'", e, e.getMessage());
- }
- }
+ protected DataDomain createDataDomain(String name) {
+ return new DataDomain(name);
+ }
- protected DataDomain createDataDomain(String name) {
- return new DataDomain(name);
- }
+ protected DataDomain createAndInitDataDomain() throws Exception {
- protected DataDomain createAndInitDataDomain() throws Exception {
+ DataChannelDescriptor descriptor;
- DataChannelDescriptor descriptor;
+ if (locations.isEmpty()) {
+ descriptor = new DataChannelDescriptor();
+ } else {
+ descriptor = descriptorFromConfigs();
+ }
- if (locations.isEmpty()) {
- descriptor = new DataChannelDescriptor();
- descriptor.setName(DEFAULT_NAME);
- } else {
- descriptor = descriptorFromConfigs();
- }
+ String nameOverride = runtimeProperties.get(Constants.SERVER_DOMAIN_NAME_PROPERTY);
+ if (nameOverride != null) {
+ descriptor.setName(nameOverride);
+ }
- DataDomain dataDomain = createDataDomain(descriptor.getName());
+ DataDomain dataDomain = createDataDomain(descriptor.getName());
- dataDomain.setMaxIdQualifierSize(runtimeProperties.getInt(Constants.SERVER_MAX_ID_QUALIFIER_SIZE_PROPERTY, -1));
+ dataDomain.setMaxIdQualifierSize(runtimeProperties.getInt(Constants.SERVER_MAX_ID_QUALIFIER_SIZE_PROPERTY, -1));
- dataDomain.setQueryCache(new NestedQueryCache(queryCache));
- dataDomain.setEntitySorter(injector.getInstance(EntitySorter.class));
- dataDomain.setEventManager(injector.getInstance(EventManager.class));
+ dataDomain.setQueryCache(new NestedQueryCache(queryCache));
+ dataDomain.setEntitySorter(injector.getInstance(EntitySorter.class));
+ dataDomain.setEventManager(injector.getInstance(EventManager.class));
- dataDomain.initWithProperties(descriptor.getProperties());
+ dataDomain.initWithProperties(descriptor.getProperties());
- for (DataMap dataMap : descriptor.getDataMaps()) {
- dataDomain.addDataMap(dataMap);
- }
+ for (DataMap dataMap : descriptor.getDataMaps()) {
+ dataDomain.addDataMap(dataMap);
+ }
- dataDomain.getEntityResolver().applyDBLayerDefaults();
- dataDomain.getEntityResolver().applyObjectLayerDefaults();
+ dataDomain.getEntityResolver().applyDBLayerDefaults();
+ dataDomain.getEntityResolver().applyObjectLayerDefaults();
- for (DataNodeDescriptor nodeDescriptor : descriptor.getNodeDescriptors()) {
- addDataNode(dataDomain, nodeDescriptor);
- }
+ for (DataNodeDescriptor nodeDescriptor : descriptor.getNodeDescriptors()) {
+ addDataNode(dataDomain, nodeDescriptor);
+ }
- // init default node
- DataNode defaultNode = null;
+ // init default node
+ DataNode defaultNode = null;
- if (descriptor.getDefaultNodeName() != null) {
- defaultNode = dataDomain.getDataNode(descriptor.getDefaultNodeName());
- }
+ if (descriptor.getDefaultNodeName() != null) {
+ defaultNode = dataDomain.getDataNode(descriptor.getDefaultNodeName());
+ }
- if (defaultNode == null) {
- Collection<DataNode> allNodes = dataDomain.getDataNodes();
- if (allNodes.size() == 1) {
- defaultNode = allNodes.iterator().next();
- }
- }
+ if (defaultNode == null) {
+ Collection<DataNode> allNodes = dataDomain.getDataNodes();
+ if (allNodes.size() == 1) {
+ defaultNode = allNodes.iterator().next();
+ }
+ }
- if (defaultNode != null) {
- logger.info("setting DataNode '" + defaultNode.getName() + "' as default, used by all unlinked DataMaps");
+ if (defaultNode != null) {
+ logger.info("setting DataNode '" + defaultNode.getName() + "' as default, used by all unlinked DataMaps");
- dataDomain.setDefaultNode(defaultNode);
- }
+ dataDomain.setDefaultNode(defaultNode);
+ }
- for (DataChannelFilter filter : filters) {
- dataDomain.addFilter(filter);
- }
+ for (DataChannelFilter filter : filters) {
+ dataDomain.addFilter(filter);
+ }
- return dataDomain;
- }
+ return dataDomain;
+ }
- /**
- * @since 4.0
- */
- protected DataNode addDataNode(DataDomain dataDomain, DataNodeDescriptor nodeDescriptor) throws Exception {
- DataNode dataNode = dataNodeFactory.createDataNode(nodeDescriptor);
+ /**
+ * @since 4.0
+ */
+ protected DataNode addDataNode(DataDomain dataDomain, DataNodeDescriptor nodeDescriptor) throws Exception {
+ DataNode dataNode = dataNodeFactory.createDataNode(nodeDescriptor);
- // DataMaps
- for (String dataMapName : nodeDescriptor.getDataMapNames()) {
- dataNode.addDataMap(dataDomain.getDataMap(dataMapName));
- }
+ // DataMaps
+ for (String dataMapName : nodeDescriptor.getDataMapNames()) {
+ dataNode.addDataMap(dataDomain.getDataMap(dataMapName));
+ }
- dataDomain.addNode(dataNode);
- return dataNode;
- }
+ dataDomain.addNode(dataNode);
+ return dataNode;
+ }
- private DataChannelDescriptor descriptorFromConfigs() {
+ private DataChannelDescriptor descriptorFromConfigs() {
- long t0 = System.currentTimeMillis();
+ long t0 = System.currentTimeMillis();
- if (logger.isDebugEnabled()) {
- logger.debug("starting configuration loading: " + locations);
- }
+ if (logger.isDebugEnabled()) {
+ logger.debug("starting configuration loading: " + locations);
+ }
- DataChannelDescriptor[] descriptors = new DataChannelDescriptor[locations.size()];
+ DataChannelDescriptor[] descriptors = new DataChannelDescriptor[locations.size()];
- for (int i = 0; i < locations.size(); i++) {
+ for (int i = 0; i < locations.size(); i++) {
- String location = locations.get(i);
+ String location = locations.get(i);
- Collection<Resource> configurations = resourceLocator.findResources(location);
+ Collection<Resource> configurations = resourceLocator.findResources(location);
- if (configurations.isEmpty()) {
- throw new DataDomainLoadException("Configuration resource \"%s\" is not found.", location);
- }
+ if (configurations.isEmpty()) {
+ throw new DataDomainLoadException("Configuration resource \"%s\" is not found.", location);
+ }
- Resource configurationResource = configurations.iterator().next();
+ Resource configurationResource = configurations.iterator().next();
- // no support for multiple configs yet, but this is not a hard error
- if (configurations.size() > 1) {
- logger.info("found " + configurations.size() + " configurations for " + location
- + ", will use the first one: " + configurationResource.getURL());
- }
+ // no support for multiple configs yet, but this is not a hard error
+ if (configurations.size() > 1) {
+ logger.info("found " + configurations.size() + " configurations for " + location
+ + ", will use the first one: " + configurationResource.getURL());
+ }
- ConfigurationTree<DataChannelDescriptor> tree = loader.load(configurationResource);
- if (!tree.getLoadFailures().isEmpty()) {
- // TODO: andrus 03/10/2010 - log the errors before throwing?
- throw new DataDomainLoadException(tree, "Error loading DataChannelDescriptor");
- }
+ ConfigurationTree<DataChannelDescriptor> tree = loader.load(configurationResource);
+ if (!tree.getLoadFailures().isEmpty()) {
+ // TODO: andrus 03/10/2010 - log the errors before throwing?
+ throw new DataDomainLoadException(tree, "Error loading DataChannelDescriptor");
+ }
- descriptors[i] = tree.getRootNode();
- }
+ descriptors[i] = tree.getRootNode();
+ }
- long t1 = System.currentTimeMillis();
+ long t1 = System.currentTimeMillis();
- if (logger.isDebugEnabled()) {
- logger.debug("finished configuration loading in " + (t1 - t0) + " ms.");
- }
+ if (logger.isDebugEnabled()) {
+ logger.debug("finished configuration loading in " + (t1 - t0) + " ms.");
+ }
- return descriptorMerger.merge(descriptors);
- }
+ return descriptorMerger.merge(descriptors);
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/15297cca/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerRuntimeBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerRuntimeBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerRuntimeBuilder.java
index 01115b7..33dc60e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerRuntimeBuilder.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerRuntimeBuilder.java
@@ -19,6 +19,7 @@
package org.apache.cayenne.configuration.server;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
@@ -40,6 +41,12 @@ import org.apache.cayenne.di.Module;
*/
public class ServerRuntimeBuilder {
+ /**
+ * @since 4.0
+ */
+ static final String DEFAULT_NAME = "cayenne";
+
+ private String name;
private Collection<String> configs;
private List<Module> modules;
private DataSourceFactory dataSourceFactory;
@@ -54,17 +61,18 @@ public class ServerRuntimeBuilder {
* Creates an empty builder.
*/
public ServerRuntimeBuilder() {
- this.configs = new LinkedHashSet<String>();
- this.modules = new ArrayList<Module>();
+ this(null);
}
/**
- * An equivalent to creating builder with default constructor and calling
- * {@link #addConfig(String)}.
+ * Creates a builder with a fixed name of the DataDomain of the resulting
+ * ServerRuntime. Specifying explicit name is often needed for consistency
+ * in runtimes merged from multiple configs, each having its own name.
*/
- public ServerRuntimeBuilder(String configurationLocation) {
- this();
- addConfig(configurationLocation);
+ public ServerRuntimeBuilder(String name) {
+ this.configs = new LinkedHashSet<String>();
+ this.modules = new ArrayList<Module>();
+ this.name = name;
}
/**
@@ -134,6 +142,13 @@ public class ServerRuntimeBuilder {
return this;
}
+ public ServerRuntimeBuilder addConfigs(String... configurationLocations) {
+ if (configurationLocations != null) {
+ configs.addAll(Arrays.asList(configurationLocations));
+ }
+ return this;
+ }
+
public ServerRuntimeBuilder addConfigs(Collection<String> configurationLocations) {
configs.addAll(configurationLocations);
return this;
@@ -160,6 +175,28 @@ public class ServerRuntimeBuilder {
private void buildModules() {
+ String nameOverride = name;
+
+ if (nameOverride == null) {
+ // check if we need to force the default name ... we do when no
+ // configs or multiple configs are supplied.
+ if (configs.size() != 1) {
+ nameOverride = DEFAULT_NAME;
+ }
+ }
+
+ if (nameOverride != null) {
+
+ final String finalNameOverride = nameOverride;
+ prepend(new Module() {
+ @Override
+ public void configure(Binder binder) {
+ binder.bindMap(Constants.PROPERTIES_MAP).put(Constants.SERVER_DOMAIN_NAME_PROPERTY,
+ finalNameOverride);
+ }
+ });
+ }
+
if (dataSourceFactory != null) {
prepend(new Module() {
@@ -196,6 +233,7 @@ public class ServerRuntimeBuilder {
if (jdbcMaxConnections > 0) {
props.put(Constants.JDBC_MAX_CONNECTIONS_PROPERTY, Integer.toString(jdbcMaxConnections));
}
+
}
});
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/15297cca/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/SyntheticNodeDataDomainProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/SyntheticNodeDataDomainProvider.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/SyntheticNodeDataDomainProvider.java
index 56751fe..dbd0ec2 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/SyntheticNodeDataDomainProvider.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/SyntheticNodeDataDomainProvider.java
@@ -28,24 +28,23 @@ import org.apache.cayenne.configuration.DataNodeDescriptor;
*/
class SyntheticNodeDataDomainProvider extends DataDomainProvider {
- @Override
- protected DataDomain createAndInitDataDomain() throws Exception {
+ @Override
+ protected DataDomain createAndInitDataDomain() throws Exception {
- DataDomain dataDomain = super.createAndInitDataDomain();
+ DataDomain dataDomain = super.createAndInitDataDomain();
- // no nodes... add a synthetic node... it will become the default
- if (dataDomain.getDataNodes().isEmpty()) {
+ // no nodes... add a synthetic node... it will become the default
+ if (dataDomain.getDataNodes().isEmpty()) {
- DataChannelDescriptor channelDescriptor = new DataChannelDescriptor();
- channelDescriptor.setName(DEFAULT_NAME);
+ DataChannelDescriptor channelDescriptor = new DataChannelDescriptor();
- DataNodeDescriptor nodeDescriptor = new DataNodeDescriptor(DEFAULT_NAME);
- nodeDescriptor.setDataChannelDescriptor(channelDescriptor);
+ DataNodeDescriptor nodeDescriptor = new DataNodeDescriptor(ServerRuntimeBuilder.DEFAULT_NAME);
+ nodeDescriptor.setDataChannelDescriptor(channelDescriptor);
- DataNode node = addDataNode(dataDomain, nodeDescriptor);
- dataDomain.setDefaultNode(node);
- }
- return dataDomain;
- }
+ DataNode node = addDataNode(dataDomain, nodeDescriptor);
+ dataDomain.setDefaultNode(node);
+ }
+ return dataDomain;
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/15297cca/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/ServerRuntimeBuilderIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/ServerRuntimeBuilderIT.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/ServerRuntimeBuilderIT.java
new file mode 100644
index 0000000..27b64e4
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/ServerRuntimeBuilderIT.java
@@ -0,0 +1,109 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+package org.apache.cayenne.configuration.server;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+import javax.sql.DataSource;
+
+import org.apache.cayenne.DataRow;
+import org.apache.cayenne.conn.DataSourceInfo;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.query.SQLSelect;
+import org.apache.cayenne.test.jdbc.DBHelper;
+import org.apache.cayenne.test.jdbc.TableHelper;
+import org.apache.cayenne.unit.di.server.CayenneProjects;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
+public class ServerRuntimeBuilderIT extends ServerCase {
+
+ @Inject
+ private DBHelper dbHelper;
+
+ @Inject
+ private ServerRuntime runtime;
+
+ @Inject
+ private DataSourceInfo dsi;
+
+ private ServerRuntime localRuntime;
+ private DataSource dataSource;
+
+ @After
+ public void stopLocalRuntime() {
+
+ // even though we don't supply real configs here, we sometimes access
+ // DataDomain, and this starts EventManager threads that need to be
+ // shutdown
+ if (localRuntime != null) {
+ localRuntime.shutdown();
+ }
+ }
+
+ @Before
+ public void testSetUp() throws Exception {
+ TableHelper tArtist = new TableHelper(dbHelper, "ARTIST");
+ tArtist.setColumns("ARTIST_ID", "ARTIST_NAME");
+ tArtist.insert(33001, "AA1");
+ tArtist.insert(33002, "AA2");
+
+ this.dataSource = runtime.getDataSource("testmap");
+ }
+
+ @Test
+ public void testConfigFree_WithDataSource() {
+
+ localRuntime = new ServerRuntimeBuilder().dataSource(dataSource).build();
+
+ List<DataRow> result = SQLSelect.dataRowQuery("SELECT * FROM ARTIST").select(localRuntime.newContext());
+ assertEquals(2, result.size());
+ }
+
+ @Test
+ public void testConfigFree_WithDBParams() {
+
+ localRuntime = new ServerRuntimeBuilder().jdbcDriver(dsi.getJdbcDriver()).url(dsi.getDataSourceUrl())
+ .password(dsi.getPassword()).user(dsi.getUserName()).minConnections(1).maxConnections(2).build();
+
+ List<DataRow> result = SQLSelect.dataRowQuery("SELECT * FROM ARTIST").select(localRuntime.newContext());
+ assertEquals(2, result.size());
+ }
+
+ @Test
+ public void test_UnnamedDomain_MultiLocation() {
+ localRuntime = new ServerRuntimeBuilder().addConfigs(CayenneProjects.TESTMAP_PROJECT,
+ CayenneProjects.EMBEDDABLE_PROJECT).build();
+
+ assertEquals("cayenne", localRuntime.getDataDomain().getName());
+ }
+
+ @Test
+ public void test_NamedDomain_MultiLocation() {
+ localRuntime = new ServerRuntimeBuilder("myd").addConfigs(CayenneProjects.TESTMAP_PROJECT,
+ CayenneProjects.EMBEDDABLE_PROJECT).build();
+ assertEquals("myd", localRuntime.getDataDomain().getName());
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/15297cca/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/ServerRuntimeBuilderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/ServerRuntimeBuilderTest.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/ServerRuntimeBuilderTest.java
index 19c9447..9177fac 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/ServerRuntimeBuilderTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/ServerRuntimeBuilderTest.java
@@ -18,8 +18,10 @@
****************************************************************/
package org.apache.cayenne.configuration.server;
+import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
@@ -32,15 +34,29 @@ import org.apache.cayenne.configuration.Constants;
import org.apache.cayenne.configuration.ModuleCollection;
import org.apache.cayenne.di.Key;
import org.apache.cayenne.di.Module;
+import org.junit.After;
import org.junit.Test;
public class ServerRuntimeBuilderTest {
+ private ServerRuntime runtime;
+
+ @After
+ public void stopRuntime() {
+
+ // even though we don't supply real configs here, we sometimes access
+ // DataDomain, and this starts EventManager threads that need to be
+ // shutdown
+ if (runtime != null) {
+ runtime.shutdown();
+ }
+ }
+
@Test
public void test_NoLocation() {
// this is meaningless (no DataSource), but should work...
- ServerRuntime runtime = new ServerRuntimeBuilder().build();
+ runtime = new ServerRuntimeBuilder().build();
List<?> locations = runtime.getInjector().getInstance(
Key.get(List.class, Constants.SERVER_PROJECT_LOCATIONS_LIST));
@@ -49,14 +65,14 @@ public class ServerRuntimeBuilderTest {
assertTrue(runtime.getModule() instanceof ModuleCollection);
Collection<Module> modules = ((ModuleCollection) runtime.getModule()).getModules();
- assertEquals(1, modules.size());
- assertTrue(modules.iterator().next() instanceof ServerModule);
+ assertEquals(2, modules.size());
+ assertThat(modules.iterator().next(), instanceOf(ServerModule.class));
}
@Test
public void test_SingleLocation() {
- ServerRuntime runtime = new ServerRuntimeBuilder("xxxx").build();
+ runtime = new ServerRuntimeBuilder().addConfig("xxxx").build();
List<?> locations = runtime.getInjector().getInstance(
Key.get(List.class, Constants.SERVER_PROJECT_LOCATIONS_LIST));
@@ -65,14 +81,14 @@ public class ServerRuntimeBuilderTest {
Collection<Module> modules = ((ModuleCollection) runtime.getModule()).getModules();
assertEquals(1, modules.size());
- assertTrue(modules.iterator().next() instanceof ServerModule);
+ assertThat(modules.iterator().next(), instanceOf(ServerModule.class));
}
@Test
public void test_MultipleLocations() {
- ServerRuntime runtime = new ServerRuntimeBuilder("xxxx").addConfig("yyyy").build();
+ runtime = new ServerRuntimeBuilder().addConfigs("xxxx", "yyyy").build();
List<?> locations = runtime.getInjector().getInstance(
Key.get(List.class, Constants.SERVER_PROJECT_LOCATIONS_LIST));
@@ -80,8 +96,8 @@ public class ServerRuntimeBuilderTest {
assertEquals(Arrays.asList("xxxx", "yyyy"), locations);
Collection<Module> modules = ((ModuleCollection) runtime.getModule()).getModules();
- assertEquals(1, modules.size());
- assertTrue(modules.iterator().next() instanceof ServerModule);
+ assertEquals(2, modules.size());
+ assertThat(modules.iterator().next(), instanceOf(ServerModule.class));
}
@Test
@@ -89,15 +105,30 @@ public class ServerRuntimeBuilderTest {
Module m = mock(Module.class);
- ServerRuntime runtime = new ServerRuntimeBuilder("xxxx").addModule(m).build();
+ runtime = new ServerRuntimeBuilder().addModule(m).build();
Collection<Module> modules = ((ModuleCollection) runtime.getModule()).getModules();
- assertEquals(2, modules.size());
+ assertEquals(3, modules.size());
Iterator<Module> it = modules.iterator();
- assertTrue(it.next() instanceof ServerModule);
+ assertThat(it.next(), instanceOf(ServerModule.class));
+
+ // rewind - this module is name fix module
+ it.next();
+
assertSame(m, it.next());
}
+ @Test
+ public void test_UnnamedDomain_NoLocation() {
+ runtime = new ServerRuntimeBuilder().build();
+ assertEquals("cayenne", runtime.getDataDomain().getName());
+ }
+
+ @Test
+ public void test_NamedDomain_NoLocation() {
+ runtime = new ServerRuntimeBuilder("myd").build();
+ assertEquals("myd", runtime.getDataDomain().getName());
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/15297cca/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/ServerRuntimeBuilder_InAction_IT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/ServerRuntimeBuilder_InAction_IT.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/ServerRuntimeBuilder_InAction_IT.java
deleted file mode 100644
index 25c0aa4..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/ServerRuntimeBuilder_InAction_IT.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ****************************************************************/
-package org.apache.cayenne.configuration.server;
-
-import org.apache.cayenne.DataRow;
-import org.apache.cayenne.conn.DataSourceInfo;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.query.SQLSelect;
-import org.apache.cayenne.test.jdbc.DBHelper;
-import org.apache.cayenne.test.jdbc.TableHelper;
-import org.apache.cayenne.unit.di.server.CayenneProjects;
-import org.apache.cayenne.unit.di.server.ServerCase;
-import org.apache.cayenne.unit.di.server.UseServerRuntime;
-import org.junit.Before;
-import org.junit.Test;
-
-import javax.sql.DataSource;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-
-@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
-public class ServerRuntimeBuilder_InAction_IT extends ServerCase {
-
- @Inject
- private DBHelper dbHelper;
-
- @Inject
- private ServerRuntime runtime;
-
- @Inject
- private DataSourceInfo dsi;
-
- private DataSource dataSource;
-
- @Before
- public void testSetUp() throws Exception { TableHelper tArtist = new TableHelper(dbHelper, "ARTIST");
- tArtist.setColumns("ARTIST_ID", "ARTIST_NAME");
- tArtist.insert(33001, "AA1");
- tArtist.insert(33002, "AA2");
-
- this.dataSource = runtime.getDataSource("testmap");
- }
-
- @Test
- public void testConfigFree_WithDataSource() {
-
- ServerRuntime localRuntime = new ServerRuntimeBuilder().dataSource(dataSource).build();
-
- try {
- List<DataRow> result = SQLSelect.dataRowQuery("SELECT * FROM ARTIST").select(localRuntime.newContext());
- assertEquals(2, result.size());
- } finally {
- localRuntime.shutdown();
- }
- }
-
- @Test
- public void testConfigFree_WithDBParams() {
-
- ServerRuntime localRuntime = new ServerRuntimeBuilder().jdbcDriver(dsi.getJdbcDriver())
- .url(dsi.getDataSourceUrl()).password(dsi.getPassword()).user(dsi.getUserName()).minConnections(1)
- .maxConnections(2).build();
-
- try {
- List<DataRow> result = SQLSelect.dataRowQuery("SELECT * FROM ARTIST").select(localRuntime.newContext());
- assertEquals(2, result.size());
- } finally {
- localRuntime.shutdown();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/15297cca/docs/doc/src/main/resources/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/docs/doc/src/main/resources/RELEASE-NOTES.txt b/docs/doc/src/main/resources/RELEASE-NOTES.txt
index ec297f8..ddc6f5c 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -74,6 +74,7 @@ CAY-1966 SQLTemplate/SQLSelect positional parameter binding
CAY-1967 Deprecate SQLTemplate parameter batches
CAY-1968 SQLSelect cleanup and omissions
CAY-1971 Variants of Property.like(..) : contains(..), startsWith(..), endsWith(..)
+CAY-1972 A property to override DataSources of multi-module projects
Bug Fixes:
http://git-wip-us.apache.org/repos/asf/cayenne/blob/15297cca/docs/doc/src/main/resources/UPGRADE.txt
----------------------------------------------------------------------
diff --git a/docs/doc/src/main/resources/UPGRADE.txt b/docs/doc/src/main/resources/UPGRADE.txt
index 94f8f72..c7ade60 100644
--- a/docs/doc/src/main/resources/UPGRADE.txt
+++ b/docs/doc/src/main/resources/UPGRADE.txt
@@ -35,9 +35,17 @@ UPGRADING TO 4.0.M2
* External transactions are no longer configured in the Modeler. Instead they are provided as a DI property
defined in Constants.SERVER_EXTERNAL_TX_PROPERTY.
+
* TransactionDelegate is no longer present. Similar functionality can be achieved by writing a decorator for
Transaction interface and using a custom TransactionFactory to decorate standard transactions.
+* When switching to ServerRuntimeBuilder, users of multi-config projects may erroneously assume it has the same
+ behavior as 3.1 ServerRuntime in assigning domain name to the resulting merged project. Which is to use the
+ name of the last project config. We are trying to move away from this behavior, so ServerRuntimeBuilder
+ will only use config name if there's only one config and no override. Otherwise it will use the override,
+ or if not set - "cayenne" as the default name. Reference Jira: CAY-1972
+
+
UPGRADING TO 3.1B1