This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 4926422fcd5db784bb43ff08e02c988558095a50 Author: Andrus Adamchik <[email protected]> AuthorDate: Sun Jul 26 17:04:19 2026 +0300 CAY-2985 DataDomain init and structure cleanup --- .../java/org/apache/cayenne/access/DataDomain.java | 170 +++-------- .../configuration/runtime/DataDomainProvider.java | 108 ++++--- .../cayenne/access/DataContextQueryCachingIT.java | 36 +-- .../org/apache/cayenne/access/DataDomainIT.java | 72 ++--- .../cayenne/access/DataDomainQueryActionIT.java | 58 ++-- .../access/DefaultDataRowStoreFactoryIT.java | 109 +------- .../DefaultDataRowStoreFactory_CacheSizeIT.java | 48 ++++ .../DefaultDataRowStoreFactory_EventBridgeIT.java | 46 +++ .../runtime/DataContextFactoryTest.java | 155 ----------- .../DataContextFactory_DedicatedCacheIT.java | 52 ++++ .../runtime/DataContextFactory_ValidationIT.java | 52 ++++ .../runtime/DataDomainProviderIT.java | 187 +++++++++++++ .../runtime/DataDomainProviderTest.java | 310 --------------------- .../cayenne/event/MockEventBridgeProvider.java | 11 +- .../org/apache/cayenne/unit/CayenneProjects.java | 1 + .../src/test/resources/cayenne-domain-provider.xml | 18 ++ .../editor/datadomain/main/DataDomainMainView.java | 24 +- 17 files changed, 587 insertions(+), 870 deletions(-) diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataDomain.java b/cayenne/src/main/java/org/apache/cayenne/access/DataDomain.java index 6bba60781..2e2cd7fc9 100644 --- a/cayenne/src/main/java/org/apache/cayenne/access/DataDomain.java +++ b/cayenne/src/main/java/org/apache/cayenne/access/DataDomain.java @@ -33,7 +33,6 @@ import org.apache.cayenne.cache.QueryCache; import org.apache.cayenne.configuration.Constants; import org.apache.cayenne.di.AdhocObjectFactory; import org.apache.cayenne.di.BeforeScopeEnd; -import org.apache.cayenne.di.Inject; import org.apache.cayenne.event.EventManager; import org.apache.cayenne.graph.CompoundDiff; import org.apache.cayenne.graph.GraphDiff; @@ -61,57 +60,57 @@ import java.util.concurrent.CopyOnWriteArrayList; * transparently routed to an appropriate DataNode. */ public class DataDomain implements DataChannel { + + protected final String name; + protected final TransactionManager transactionManager; + protected final TransactionFactory transactionFactory; + protected final DataDomainFlushActionFactory flushActionFactory; + protected final AdhocObjectFactory objectFactory; + protected final EventManager eventManager; + protected final EntitySorter entitySorter; + protected final QueryCache queryCache; + + protected final EntityResolver entityResolver; - public static final String SHARED_CACHE_ENABLED_PROPERTY = "cayenne.DataDomain.sharedCache"; - public static final boolean SHARED_CACHE_ENABLED_DEFAULT = true; - - public static final String VALIDATING_OBJECTS_ON_COMMIT_PROPERTY = "cayenne.DataDomain.validatingObjectsOnCommit"; - public static final boolean VALIDATING_OBJECTS_ON_COMMIT_DEFAULT = true; - - @Inject - protected TransactionManager transactionManager; - @Inject - protected TransactionFactory transactionFactory; - @Inject - protected DataDomainFlushActionFactory flushActionFactory; - @Inject - protected AdhocObjectFactory objectFactory; - - protected DataRowStoreFactory dataRowStoreFactory; protected int maxIdQualifierSize; protected List<DataChannelQueryFilter> queryFilters; protected List<DataChannelSyncFilter> syncFilters; protected Map<String, DataNode> nodes; protected Map<String, DataNode> nodesByDataMapName; protected DataNode defaultNode; - protected EntityResolver entityResolver; protected DataRowStore sharedSnapshotCache; - protected String name; - protected QueryCache queryCache; - protected EventManager eventManager; - protected EntitySorter entitySorter; - protected boolean stopped; - // these are initialized from properties... - protected boolean sharedCacheEnabled; protected boolean validatingObjectsOnCommit; + protected boolean stopped; - /** - * Creates a DataDomain and assigns it a name. - */ - public DataDomain(String name) { - init(name); - resetProperties(); - } + public DataDomain( + String name, + TransactionManager transactionManager, + TransactionFactory transactionFactory, + DataDomainFlushActionFactory flushActionFactory, + AdhocObjectFactory objectFactory, + EventManager eventManager, + EntitySorter entitySorter, + QueryCache queryCache, + EntityResolver entityResolver + ) { - private void init(String name) { + this.name = name; + this.transactionManager = transactionManager; + this.transactionFactory = transactionFactory; + this.flushActionFactory = flushActionFactory; + this.objectFactory = objectFactory; + this.eventManager = eventManager; + this.entitySorter = entitySorter; + this.queryCache = queryCache; + this.entityResolver = entityResolver; this.queryFilters = new CopyOnWriteArrayList<>(); this.syncFilters = new CopyOnWriteArrayList<>(); this.nodesByDataMapName = new ConcurrentHashMap<>(); this.nodes = new ConcurrentHashMap<>(); - setName(name); + refreshEntitySorter(); } /** @@ -134,23 +133,6 @@ public class DataDomain implements DataChannel { return entitySorter; } - /** - * @since 3.1 - */ - public void setEntitySorter(EntitySorter entitySorter) { - this.entitySorter = entitySorter; - } - - /** - * Resets the domain's behavioral flags to their defaults. - * - * @since 1.1 - */ - protected void resetProperties() { - sharedCacheEnabled = SHARED_CACHE_ENABLED_DEFAULT; - validatingObjectsOnCommit = VALIDATING_OBJECTS_ON_COMMIT_DEFAULT; - } - /** * Returns EventManager used by this DataDomain. * @@ -160,19 +142,6 @@ public class DataDomain implements DataChannel { return eventManager; } - /** - * Sets EventManager used by this DataDomain. - * - * @since 1.2 - */ - public void setEventManager(EventManager eventManager) { - this.eventManager = eventManager; - - if (sharedSnapshotCache != null) { - sharedSnapshotCache.setEventManager(eventManager); - } - } - /** * Returns "name" property value. */ @@ -180,16 +149,6 @@ public class DataDomain implements DataChannel { return name; } - /** - * Sets "name" property to a new value. - */ - public synchronized void setName(String name) { - this.name = name; - if (sharedSnapshotCache != null) { - this.sharedSnapshotCache.setName(name); - } - } - /** * Returns <code>true</code> if DataContexts produced by this DataDomain are * using shared DataRowStore. Returns <code>false</code> if each DataContext @@ -197,11 +156,7 @@ public class DataDomain implements DataChannel { * overwritten per DataContext. */ public boolean isSharedCacheEnabled() { - return sharedCacheEnabled; - } - - public void setSharedCacheEnabled(boolean sharedCacheEnabled) { - this.sharedCacheEnabled = sharedCacheEnabled; + return sharedSnapshotCache != null; } /** @@ -229,22 +184,6 @@ public class DataDomain implements DataChannel { * the first call if 'sharedCacheEnabled' flag is true. */ public DataRowStore getSharedSnapshotCache() { - if (sharedSnapshotCache == null && sharedCacheEnabled) { - this.sharedSnapshotCache = nonNullSharedSnapshotCache(); - } - - return sharedSnapshotCache; - } - - /** - * Returns a guaranteed non-null shared snapshot cache regardless of the - * 'sharedCacheEnabled' flag setting. - */ - synchronized DataRowStore nonNullSharedSnapshotCache() { - if (sharedSnapshotCache == null) { - this.sharedSnapshotCache = dataRowStoreFactory.createDataRowStore(name); - } - return sharedSnapshotCache; } @@ -400,25 +339,6 @@ public class DataDomain implements DataChannel { return node; } - /** - * Sets EntityResolver. If not set explicitly, DataDomain creates a default - * EntityResolver internally on demand. - * - * @since 1.1 - */ - public void setEntityResolver(EntityResolver entityResolver) { - this.entityResolver = entityResolver; - } - - // creates default entity resolver if there is none set yet - private synchronized void createEntityResolver() { - if (entityResolver == null) { - // entity resolver will be self-indexing as we add all our maps - // to it as they are added to the DataDomain - entityResolver = new EntityResolver(); - } - } - /** * Shutdowns all owned data nodes and marks this domain as stopped. */ @@ -467,10 +387,6 @@ public class DataDomain implements DataChannel { */ @Override public EntityResolver getEntityResolver() { - if (entityResolver == null) { - createEntityResolver(); - } - return entityResolver; } @@ -534,24 +450,6 @@ public class DataDomain implements DataChannel { return queryCache; } - public void setQueryCache(QueryCache queryCache) { - this.queryCache = queryCache; - } - - /** - * @since 4.0 - */ - public DataRowStoreFactory getDataRowStoreFactory() { - return dataRowStoreFactory; - } - - /** - * @since 4.0 - */ - public void setDataRowStoreFactory(DataRowStoreFactory dataRowStoreFactory) { - this.dataRowStoreFactory = dataRowStoreFactory; - } - void refreshEntitySorter() { if (entitySorter != null) { entitySorter.setEntityResolver(getEntityResolver()); diff --git a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DataDomainProvider.java b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DataDomainProvider.java index cf8582d0c..6c5758b2d 100644 --- a/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DataDomainProvider.java +++ b/cayenne/src/main/java/org/apache/cayenne/configuration/runtime/DataDomainProvider.java @@ -24,7 +24,9 @@ import org.apache.cayenne.DataChannelQueryFilter; import org.apache.cayenne.DataChannelSyncFilter; import org.apache.cayenne.access.DataDomain; import org.apache.cayenne.access.DataNode; +import org.apache.cayenne.access.DataRowStore; import org.apache.cayenne.access.DataRowStoreFactory; +import org.apache.cayenne.access.flush.DataDomainFlushActionFactory; import org.apache.cayenne.access.types.ValueObjectTypeRegistry; import org.apache.cayenne.cache.NestedQueryCache; import org.apache.cayenne.cache.QueryCache; @@ -41,10 +43,13 @@ import org.apache.cayenne.di.Injector; import org.apache.cayenne.di.Provider; import org.apache.cayenne.event.EventManager; import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.map.EntityResolver; import org.apache.cayenne.map.EntitySorter; import org.apache.cayenne.reflect.generic.ValueComparisonStrategyFactory; import org.apache.cayenne.resource.Resource; import org.apache.cayenne.resource.ResourceLocator; +import org.apache.cayenne.tx.TransactionFactory; +import org.apache.cayenne.tx.TransactionManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -61,6 +66,11 @@ import java.util.Map; */ public class DataDomainProvider implements Provider<DataDomain> { + public static final String SHARED_CACHE_ENABLED_PROPERTY = "cayenne.DataDomain.sharedCache"; + public static final String SHARED_CACHE_ENABLED_DEFAULT = "true"; + public static final String VALIDATING_OBJECTS_ON_COMMIT_PROPERTY = "cayenne.DataDomain.validatingObjectsOnCommit"; + public static final String VALIDATING_OBJECTS_ON_COMMIT_DEFAULT = "true"; + private static final Logger LOGGER = LoggerFactory.getLogger(DataDomainProvider.class); @Inject @@ -102,6 +112,24 @@ public class DataDomainProvider implements Provider<DataDomain> { @Inject protected DataNodeFactory dataNodeFactory; + @Inject + protected TransactionManager transactionManager; + + @Inject + protected TransactionFactory transactionFactory; + + @Inject + protected DataDomainFlushActionFactory flushActionFactory; + + @Inject + protected AdhocObjectFactory objectFactory; + + @Inject + protected EventManager eventManager; + + @Inject + protected EntitySorter entitySorter; + @Override public DataDomain get() throws ConfigurationException { @@ -116,54 +144,49 @@ public class DataDomainProvider implements Provider<DataDomain> { } } - protected DataDomain createDataDomain(String name) { - return new DataDomain(name); - } - protected DataDomain createAndInitDataDomain() throws Exception { DataChannelDescriptor descriptor = loadDescriptor(); - DataDomain dataDomain = createDataDomain(descriptor.getName()); + DataDomain domain = new DataDomain( + descriptor.getName(), + transactionManager, + transactionFactory, + flushActionFactory, + objectFactory, + eventManager, + entitySorter, + new NestedQueryCache(queryCache), + createEntityResolver(descriptor)); - dataDomain.setMaxIdQualifierSize(runtimeProperties.getInt(Constants.MAX_ID_QUALIFIER_SIZE_PROPERTY, -1)); + domain.setMaxIdQualifierSize(runtimeProperties.getInt(Constants.MAX_ID_QUALIFIER_SIZE_PROPERTY, -1)); - dataDomain.setQueryCache(new NestedQueryCache(queryCache)); - dataDomain.setEntitySorter(injector.getInstance(EntitySorter.class)); - dataDomain.setEventManager(injector.getInstance(EventManager.class)); - dataDomain.setDataRowStoreFactory(injector.getInstance(DataRowStoreFactory.class)); Map<String, String> properties = descriptor.getProperties(); - if ("true".equalsIgnoreCase(properties.get(DataDomain.SHARED_CACHE_ENABLED_PROPERTY))) { - dataDomain.setSharedCacheEnabled(true); - } - - if ("true".equalsIgnoreCase(properties.get(DataDomain.VALIDATING_OBJECTS_ON_COMMIT_PROPERTY))) { - dataDomain.setValidatingObjectsOnCommit(true); - } - for (DataMap dataMap : descriptor.getDataMaps()) { - dataDomain.addDataMap(dataMap); + boolean sharedCache = "true".equals(properties.getOrDefault(SHARED_CACHE_ENABLED_PROPERTY, SHARED_CACHE_ENABLED_DEFAULT)); + if (sharedCache) { + DataRowStore cache = injector.getInstance(DataRowStoreFactory.class).createDataRowStore(descriptor.getName()); + // TODO: setSharedSnapshotCache mutates cache internally; also DataDomain.setName() does + domain.setSharedSnapshotCache(cache); } - dataDomain.getEntityResolver().applyDBLayerDefaults(); - dataDomain.getEntityResolver().setValueObjectTypeRegistry(injector.getInstance(ValueObjectTypeRegistry.class)); - dataDomain.getEntityResolver().setValueComparisonStrategyFactory(injector.getInstance(ValueComparisonStrategyFactory.class)); - dataDomain.getEntityResolver().setObjectFactory(injector.getInstance(AdhocObjectFactory.class)); + boolean validatingOnCommit = "true".equals(properties.getOrDefault(VALIDATING_OBJECTS_ON_COMMIT_PROPERTY, VALIDATING_OBJECTS_ON_COMMIT_DEFAULT)); + domain.setValidatingObjectsOnCommit(validatingOnCommit); for (DataNodeDescriptor nodeDescriptor : descriptor.getNodeDescriptors()) { - addDataNode(dataDomain, nodeDescriptor); + addDataNode(domain, nodeDescriptor); } // init default node DataNode defaultNode = null; if (descriptor.getDefaultNodeName() != null) { - defaultNode = dataDomain.getDataNode(descriptor.getDefaultNodeName()); + defaultNode = domain.getDataNode(descriptor.getDefaultNodeName()); } if (defaultNode == null) { - Collection<DataNode> allNodes = dataDomain.getDataNodes(); + Collection<DataNode> allNodes = domain.getDataNodes(); if (allNodes.size() == 1) { defaultNode = allNodes.iterator().next(); } @@ -172,22 +195,45 @@ public class DataDomainProvider implements Provider<DataDomain> { if (defaultNode != null) { LOGGER.info("setting DataNode '{}' as default, used by all unlinked DataMaps", defaultNode.getName()); - dataDomain.setDefaultNode(defaultNode); + domain.setDefaultNode(defaultNode); } for (DataChannelQueryFilter filter : queryFilters) { - dataDomain.addQueryFilter(filter); + domain.addQueryFilter(filter); } for (DataChannelSyncFilter filter : syncFilters) { - dataDomain.addSyncFilter(filter); + domain.addSyncFilter(filter); } for (Object listener : listeners) { - dataDomain.addListener(listener); + domain.addListener(listener); + } + + return domain; + } + + /** + * Creates an EntityResolver fully configured off the descriptor, so that the DataDomain can take it as a + * constructor argument. + * + * @since 5.0 + */ + protected EntityResolver createEntityResolver(DataChannelDescriptor descriptor) { + + EntityResolver entityResolver = new EntityResolver(); + + // must go through "addDataMap" - unlike the Collection constructor, it sets the map namespace + for (DataMap dataMap : descriptor.getDataMaps()) { + entityResolver.addDataMap(dataMap); } - return dataDomain; + entityResolver.applyDBLayerDefaults(); + entityResolver.setValueObjectTypeRegistry(injector.getInstance(ValueObjectTypeRegistry.class)); + entityResolver.setValueComparisonStrategyFactory(injector.getInstance(ValueComparisonStrategyFactory.class)); + entityResolver.setObjectFactory(objectFactory); + + return entityResolver; } /** diff --git a/cayenne/src/test/java/org/apache/cayenne/access/DataContextQueryCachingIT.java b/cayenne/src/test/java/org/apache/cayenne/access/DataContextQueryCachingIT.java index df3e9bdb2..608f06efc 100644 --- a/cayenne/src/test/java/org/apache/cayenne/access/DataContextQueryCachingIT.java +++ b/cayenne/src/test/java/org/apache/cayenne/access/DataContextQueryCachingIT.java @@ -21,8 +21,6 @@ package org.apache.cayenne.access; import org.apache.cayenne.DataRow; import org.apache.cayenne.Persistent; -import org.apache.cayenne.cache.MapQueryCache; -import org.apache.cayenne.cache.QueryCache; import org.apache.cayenne.query.ObjectSelect; import org.apache.cayenne.query.QueryCacheStrategy; import org.apache.cayenne.query.QueryMetadata; @@ -30,38 +28,30 @@ import org.apache.cayenne.test.jdbc.TableHelper; import org.apache.cayenne.testdo.testmap.Artist; import org.apache.cayenne.unit.CayenneProjects; import org.apache.cayenne.unit.CayenneTestsEnv; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import java.util.ArrayList; import java.util.List; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; -public class DataContextQueryCachingIT { +public class DataContextQueryCachingIT { @RegisterExtension static final CayenneTestsEnv env = CayenneTestsEnv.forProject(CayenneProjects.TESTMAP_PROJECT); - protected DataContext context; - - protected TableHelper tArtist; protected TableHelper tPainting; - protected QueryCache oldCache; + protected DataContext context; protected DataDomain domain; protected DataNode getNode() { return this.domain.getDataNodes().iterator().next(); } - @BeforeEach public void setUp() throws Exception { context = env.context(); @@ -73,15 +63,6 @@ public class DataContextQueryCachingIT { "ESTIMATED_PRICE"); domain = context.getParentDataDomain(); - oldCache = domain.getQueryCache(); - domain.setQueryCache(new MapQueryCache(50)); - context.setQueryCache(new MapQueryCache(50)); - } - - - @AfterEach - public void tearDown() throws Exception { - domain.setQueryCache(oldCache); } protected void createInsertDataSet() throws Exception { @@ -128,8 +109,7 @@ public class DataContextQueryCachingIT { assertEquals(rows2, freshResultRows); assertNull(context.getParentDataDomain().getQueryCache().get(cacheKey)); assertEquals(rows2, context.getQueryCache().get(cacheKey)); - } - finally { + } finally { engine.stopInterceptNode(); } } @@ -168,8 +148,7 @@ public class DataContextQueryCachingIT { assertEquals(rows2, context.getParentDataDomain().getQueryCache().get( cacheKey)); assertNull(context.getQueryCache().get(cacheKey)); - } - finally { + } finally { engine.stopInterceptNode(); } } @@ -207,8 +186,7 @@ public class DataContextQueryCachingIT { assertTrue(resultRows.get(0) instanceof Persistent); assertNull(context.getParentDataDomain().getQueryCache().get(cacheKey)); assertEquals(freshResultRows, context.getQueryCache().get(cacheKey)); - } - finally { + } finally { engine.stopInterceptNode(); } } diff --git a/cayenne/src/test/java/org/apache/cayenne/access/DataDomainIT.java b/cayenne/src/test/java/org/apache/cayenne/access/DataDomainIT.java index 7ac546804..c6b334568 100644 --- a/cayenne/src/test/java/org/apache/cayenne/access/DataDomainIT.java +++ b/cayenne/src/test/java/org/apache/cayenne/access/DataDomainIT.java @@ -26,6 +26,7 @@ import org.apache.cayenne.annotation.PostAdd; import org.apache.cayenne.configuration.DefaultRuntimeProperties; import org.apache.cayenne.event.DefaultEventManager; import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.map.EntityResolver; import org.apache.cayenne.map.ObjEntity; import org.apache.cayenne.testdo.testmap.Artist; import org.apache.cayenne.testdo.testmap.Exhibit; @@ -44,20 +45,15 @@ import static org.junit.jupiter.api.Assertions.*; public class DataDomainIT { @RegisterExtension - static final CayenneTestsEnv env = CayenneTestsEnv.forProject(CayenneProjects.TESTMAP_PROJECT); - - @Test - public void name() throws Exception { - DataDomain domain = new DataDomain("some name"); - assertEquals("some name", domain.getName()); - domain.setName("tst_name"); - assertEquals("tst_name", domain.getName()); - } + final CayenneTestsEnv env = CayenneTestsEnv.forProject(CayenneProjects.TESTMAP_PROJECT); @Test public void lookupDataNode() { - DataDomain domain = new DataDomain("test"); + DataDomain domain = env.runtime().getDataDomain(); + + // an unmapped DataMap falls back to the default node, so drop it to test the "no node" case below + domain.setDefaultNode(null); DataMap m1 = new DataMap("m1"); DataNode n1 = new DataNode("n1"); @@ -78,7 +74,7 @@ public class DataDomainIT { @Test public void lookupDataNode_Default() { - DataDomain domain = new DataDomain("test"); + DataDomain domain = env.runtime().getDataDomain(); DataMap m1 = new DataMap("m1"); DataNode n1 = new DataNode("n1"); @@ -99,19 +95,19 @@ public class DataDomainIT { @Test public void nodes() throws Exception { - DataDomain domain = new DataDomain("dom1"); - assertEquals(0, domain.getDataNodes().size()); + DataDomain domain = env.runtime().getDataDomain(); + assertEquals(1, domain.getDataNodes().size()); DataNode node = new DataNode("1"); domain.addNode(node); - assertEquals(1, domain.getDataNodes().size()); + assertEquals(2, domain.getDataNodes().size()); node = new DataNode("2"); domain.addNode(node); - assertEquals(2, domain.getDataNodes().size()); + assertEquals(3, domain.getDataNodes().size()); } @Test - public void nodeMaps() throws Exception { - DataDomain domain = new DataDomain("dom1"); + public void nodeMaps() { + DataDomain domain = env.runtime().getDataDomain(); assertNull(domain.getDataMap("map")); DataNode node = new DataNode("1"); @@ -123,7 +119,7 @@ public class DataDomainIT { @Test public void maps() throws Exception { - DataDomain d1 = new DataDomain("dom1"); + DataDomain d1 = env.runtime().getDataDomain(); DataMap m1 = new DataMap("m1"); d1.addDataMap(m1); @@ -135,8 +131,8 @@ public class DataDomainIT { @Test public void entityResolverRefresh() throws Exception { - DataDomain domain = new DataDomain("dom1"); - org.apache.cayenne.map.EntityResolver resolver = domain.getEntityResolver(); + DataDomain domain = env.runtime().getDataDomain(); + EntityResolver resolver = domain.getEntityResolver(); assertNotNull(resolver); DataMap map = new DataMap("map"); @@ -148,41 +144,9 @@ public class DataDomainIT { assertSame(entity, resolver.getObjEntity("TestEntity")); } - @Test - public void entityResolver() { - assertNotNull(env.runtime().getDataDomain().getEntityResolver()); - - DataDomain domain = new DataDomain("dom1"); - assertNotNull(domain.getEntityResolver()); - } - - @Test - public void sharedCacheEnabledDefault() { - assertTrue(new DataDomain("d1").isSharedCacheEnabled()); - } - - @Test - public void sharedCacheEnabled() { - DataDomain domain = new DataDomain("d1"); - domain.setSharedCacheEnabled(false); - assertFalse(domain.isSharedCacheEnabled()); - } - - @Test - public void validatingObjectsOnCommitDefault() { - assertTrue(new DataDomain("d1").isValidatingObjectsOnCommit()); - } - - @Test - public void validatingObjectsOnCommit() { - DataDomain domain = new DataDomain("d1"); - domain.setValidatingObjectsOnCommit(false); - assertFalse(domain.isValidatingObjectsOnCommit()); - } - @Test public void shutdownCache() { - DataDomain domain = new DataDomain("X"); + DataDomain domain = env.runtime().getDataDomain(); final boolean[] cacheShutdown = new boolean[1]; @@ -232,7 +196,7 @@ public class DataDomainIT { StringBuilder callbackBuffer = new StringBuilder(); - @PostAdd({ Gallery.class, Painting.class }) + @PostAdd({Gallery.class, Painting.class}) void postAddEntities(Persistent object) { callbackBuffer.append("e:").append(object.getObjectId().getEntityName()).append(";"); } diff --git a/cayenne/src/test/java/org/apache/cayenne/access/DataDomainQueryActionIT.java b/cayenne/src/test/java/org/apache/cayenne/access/DataDomainQueryActionIT.java index c46582a70..f101a3773 100644 --- a/cayenne/src/test/java/org/apache/cayenne/access/DataDomainQueryActionIT.java +++ b/cayenne/src/test/java/org/apache/cayenne/access/DataDomainQueryActionIT.java @@ -18,9 +18,6 @@ ****************************************************************/ package org.apache.cayenne.access; -import java.io.Serializable; -import java.util.List; - import org.apache.cayenne.cache.MockQueryCache; import org.apache.cayenne.cache.QueryCache; import org.apache.cayenne.cache.QueryCacheEntryFactory; @@ -30,21 +27,37 @@ import org.apache.cayenne.query.QueryMetadata; import org.apache.cayenne.testdo.testmap.Painting; import org.apache.cayenne.unit.CayenneProjects; import org.apache.cayenne.unit.CayenneTestsEnv; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import java.io.Serializable; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertTrue; public class DataDomainQueryActionIT { - @RegisterExtension - static final CayenneTestsEnv env = CayenneTestsEnv.forProject(CayenneProjects.TESTMAP_PROJECT); + static QueryCache testQQ = new MockQueryCache() { - @AfterEach - public void tearDown() { - env.runtime().getDataDomain().resetProperties(); - } + @Override + public List<?> get(QueryMetadata metadata, QueryCacheEntryFactory factory) { + Object results = factory.createObject(); + assertInstanceOf(Serializable.class, results, "Query cache is not serializable."); + + return null; + } + + @SuppressWarnings("all") + @Override + public void put(QueryMetadata metadata, List results) { + assertTrue(results instanceof Serializable, "Query cache is not serializable."); + } + }; + + @RegisterExtension + static final CayenneTestsEnv env = CayenneTestsEnv.forProject(CayenneProjects.TESTMAP_PROJECT) + .withExtraModules(b -> b.bind(QueryCache.class).toInstance(testQQ)); @Test public void cachedQuery() { @@ -61,29 +74,8 @@ public class DataDomainQueryActionIT { .cacheStrategy(QueryCacheStrategy.SHARED_CACHE) .pageSize(5); - QueryCache cache = domain.queryCache; - - domain.queryCache = new MockQueryCache() { - - @Override - public List<?> get(QueryMetadata metadata, QueryCacheEntryFactory factory) { - Object results = factory.createObject(); - assertTrue(results instanceof Serializable, "Query cache is not serializable."); - - return null; - } - - @SuppressWarnings("all") - @Override - public void put(QueryMetadata metadata, List results) { - assertTrue(results instanceof Serializable, "Query cache is not serializable."); - } - }; - - DataDomainQueryAction action = new DataDomainQueryAction(env.context(), domain, query); - action.execute(); - domain.queryCache = cache; + new DataDomainQueryAction(env.context(), domain, query).execute(); } } diff --git a/cayenne/src/test/java/org/apache/cayenne/access/DefaultDataRowStoreFactoryIT.java b/cayenne/src/test/java/org/apache/cayenne/access/DefaultDataRowStoreFactoryIT.java index c38b2f5d9..fd76e64a5 100644 --- a/cayenne/src/test/java/org/apache/cayenne/access/DefaultDataRowStoreFactoryIT.java +++ b/cayenne/src/test/java/org/apache/cayenne/access/DefaultDataRowStoreFactoryIT.java @@ -19,126 +19,27 @@ package org.apache.cayenne.access; -import org.apache.cayenne.access.flush.DataDomainFlushActionFactory; -import org.apache.cayenne.access.flush.operation.DbRowOpSorter; -import org.apache.cayenne.access.flush.DefaultDataDomainFlushActionFactory; -import org.apache.cayenne.access.flush.operation.DefaultDbRowOpSorter; -import org.apache.cayenne.access.flush.operation.HardDeleteDbRowOpFactory; -import org.apache.cayenne.access.flush.operation.DeleteDbRowOpFactory; -import org.apache.cayenne.configuration.DefaultRuntimeProperties; -import org.apache.cayenne.configuration.RuntimeProperties; -import org.apache.cayenne.configuration.runtime.CoreModule; -import org.apache.cayenne.configuration.runtime.CoreModuleExtender; -import org.apache.cayenne.di.AdhocObjectFactory; -import org.apache.cayenne.di.Binder; -import org.apache.cayenne.di.ClassLoaderManager; -import org.apache.cayenne.di.DIBootstrap; -import org.apache.cayenne.di.Injector; -import org.apache.cayenne.di.Module; -import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory; -import org.apache.cayenne.di.spi.DefaultClassLoaderManager; -import org.apache.cayenne.event.DefaultEventManager; -import org.apache.cayenne.event.EventBridge; -import org.apache.cayenne.event.EventManager; -import org.apache.cayenne.event.MockEventBridge; -import org.apache.cayenne.event.MockEventBridgeProvider; -import org.apache.cayenne.event.NoopEventBridgeProvider; -import org.apache.cayenne.log.SQLLogger; -import org.apache.cayenne.log.Slf4jSQLLogger; import org.apache.cayenne.runtime.CayenneRuntime; -import org.apache.cayenne.tx.DefaultTransactionFactory; -import org.apache.cayenne.tx.DefaultTransactionManager; -import org.apache.cayenne.tx.TransactionFactory; -import org.apache.cayenne.tx.TransactionManager; import org.apache.cayenne.unit.CayenneProjects; import org.apache.cayenne.unit.CayenneTestsEnv; -import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; -import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; public class DefaultDataRowStoreFactoryIT { @RegisterExtension static final CayenneTestsEnv env = CayenneTestsEnv.forProject(CayenneProjects.MULTI_TIER_PROJECT); - @Test - public void getDataRowStore() { + public void createDataRowStore() { CayenneRuntime runtime = env.runtime(); - DataRowStore dataStore = runtime.getInjector().getInstance(DataRowStoreFactory.class) - .createDataRowStore("test"); - - assertNotNull(dataStore); - } - - @Test - public void getDataRowStoreWithParameters() { - final DataDomain DOMAIN = new DataDomain("test"); - final EventManager EVENT_MANAGER = new DefaultEventManager(); - final int CACHE_SIZE = 500; - - Module testModule = binder -> { - binder.bind(DataDomain.class).toInstance(DOMAIN); - binder.bind(EventManager.class).toInstance(EVENT_MANAGER); - binder.bind(TransactionManager.class).to(DefaultTransactionManager.class); - binder.bind(TransactionFactory.class).to(DefaultTransactionFactory.class); - binder.bind(SQLLogger.class).to(Slf4jSQLLogger.class); - binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class); - binder.bind(EventBridge.class).toProvider(NoopEventBridgeProvider.class); - binder.bind(DataRowStoreFactory.class).to(DefaultDataRowStoreFactory.class); - CoreModule.extend(binder).snapshotCacheSize(CACHE_SIZE); - }; - - Injector injector = DIBootstrap.createInjector(testModule); - DataRowStore dataStore = injector.getInstance(DataRowStoreFactory.class) + DataRowStore dataStore = runtime + .getInjector() + .getInstance(DataRowStoreFactory.class) .createDataRowStore("test"); assertNotNull(dataStore); - assertEquals(dataStore.maximumSize(), CACHE_SIZE); - assertNull(dataStore.getEventBridge()); } - - @Test - public void getDataRowStoreWithBridge() { - final DataDomain DOMAIN = new DataDomain("test"); - final EventManager EVENT_MANAGER = new DefaultEventManager(); - - Module testModule = binder -> { - binder.bind(DataDomain.class).toInstance(DOMAIN); - binder.bind(EventManager.class).toInstance(EVENT_MANAGER); - binder.bind(TransactionManager.class).to(DefaultTransactionManager.class); - binder.bind(TransactionFactory.class).to(DefaultTransactionFactory.class); - binder.bind(SQLLogger.class).to(Slf4jSQLLogger.class); - binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class); - binder.bind(EventBridge.class).toProvider(MockEventBridgeProvider.class); - binder.bind(DataRowStoreFactory.class).to(DefaultDataRowStoreFactory.class); - binder.bind(DataDomainFlushActionFactory.class).to(DefaultDataDomainFlushActionFactory.class); - binder.bind(DbRowOpSorter.class).to(DefaultDbRowOpSorter.class); - binder.bind(DeleteDbRowOpFactory.class).to(HardDeleteDbRowOpFactory.class); - binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class); - binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class); - new TestExtender(binder).initAllExtensions(); - }; - - Injector injector = DIBootstrap.createInjector(testModule); - DataRowStore dataStore = injector.getInstance(DataRowStoreFactory.class) - .createDataRowStore("test"); - - assertEquals(dataStore.getEventBridge().getClass(), MockEventBridge.class); - } - - static class TestExtender extends CoreModuleExtender { - public TestExtender(Binder binder) { - super(binder); - } - - @Override - protected CoreModuleExtender initAllExtensions() { - return super.initAllExtensions(); - } - } - } diff --git a/cayenne/src/test/java/org/apache/cayenne/access/DefaultDataRowStoreFactory_CacheSizeIT.java b/cayenne/src/test/java/org/apache/cayenne/access/DefaultDataRowStoreFactory_CacheSizeIT.java new file mode 100644 index 000000000..0c2d57821 --- /dev/null +++ b/cayenne/src/test/java/org/apache/cayenne/access/DefaultDataRowStoreFactory_CacheSizeIT.java @@ -0,0 +1,48 @@ +/***************************************************************** + * 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 + * + * https://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.access; + +import org.apache.cayenne.configuration.runtime.CoreModule; +import org.apache.cayenne.unit.CayenneProjects; +import org.apache.cayenne.unit.CayenneTestsEnv; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.junit.jupiter.api.Assertions.*; + +public class DefaultDataRowStoreFactory_CacheSizeIT { + + static int CACHE_SIZE = 500; + + @RegisterExtension + static final CayenneTestsEnv env = CayenneTestsEnv.forProject(CayenneProjects.MULTI_TIER_PROJECT) + .withExtraModules(b -> CoreModule.extend(b).snapshotCacheSize(CACHE_SIZE)); + + @Test + public void createDataRowStore() { + DataRowStore dataStore = env.runtime().getInjector() + .getInstance(DataRowStoreFactory.class) + .createDataRowStore("test"); + + assertNotNull(dataStore); + assertEquals(dataStore.maximumSize(), CACHE_SIZE); + assertNull(dataStore.getEventBridge()); + } +} diff --git a/cayenne/src/test/java/org/apache/cayenne/access/DefaultDataRowStoreFactory_EventBridgeIT.java b/cayenne/src/test/java/org/apache/cayenne/access/DefaultDataRowStoreFactory_EventBridgeIT.java new file mode 100644 index 000000000..f627c69c5 --- /dev/null +++ b/cayenne/src/test/java/org/apache/cayenne/access/DefaultDataRowStoreFactory_EventBridgeIT.java @@ -0,0 +1,46 @@ +/***************************************************************** + * 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 + * + * https://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.access; + +import org.apache.cayenne.event.EventBridge; +import org.apache.cayenne.event.MockEventBridge; +import org.apache.cayenne.event.MockEventBridgeProvider; +import org.apache.cayenne.unit.CayenneProjects; +import org.apache.cayenne.unit.CayenneTestsEnv; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class DefaultDataRowStoreFactory_EventBridgeIT { + + @RegisterExtension + static final CayenneTestsEnv env = CayenneTestsEnv.forProject(CayenneProjects.MULTI_TIER_PROJECT) + .withExtraModules(b -> b.bind(EventBridge.class).toProvider(MockEventBridgeProvider.class)); + + @Test + public void createDataRowStore() { + DataRowStore dataStore = env.runtime().getInjector() + .getInstance(DataRowStoreFactory.class) + .createDataRowStore("test"); + + assertEquals(MockEventBridge.class, dataStore.getEventBridge().getClass()); + } +} diff --git a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataContextFactoryTest.java b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataContextFactoryTest.java deleted file mode 100644 index 82e38b2b2..000000000 --- a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataContextFactoryTest.java +++ /dev/null @@ -1,155 +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 - * - * https://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.runtime; - -import org.apache.cayenne.access.DataContext; -import org.apache.cayenne.access.DataDomain; -import org.apache.cayenne.access.DataRowStoreFactory; -import org.apache.cayenne.access.DefaultDataRowStoreFactory; -import org.apache.cayenne.access.DefaultObjectMapRetainStrategy; -import org.apache.cayenne.access.ObjectMapRetainStrategy; -import org.apache.cayenne.access.flush.DataDomainFlushActionFactory; -import org.apache.cayenne.access.flush.operation.DbRowOpSorter; -import org.apache.cayenne.access.flush.DefaultDataDomainFlushActionFactory; -import org.apache.cayenne.access.flush.operation.DefaultDbRowOpSorter; -import org.apache.cayenne.access.flush.operation.HardDeleteDbRowOpFactory; -import org.apache.cayenne.access.flush.operation.DeleteDbRowOpFactory; -import org.apache.cayenne.ashwood.AshwoodEntitySorter; -import org.apache.cayenne.cache.MapQueryCache; -import org.apache.cayenne.cache.QueryCache; -import org.apache.cayenne.configuration.DefaultObjectStoreFactory; -import org.apache.cayenne.configuration.DefaultRuntimeProperties; -import org.apache.cayenne.configuration.ObjectStoreFactory; -import org.apache.cayenne.configuration.RuntimeProperties; -import org.apache.cayenne.di.AdhocObjectFactory; -import org.apache.cayenne.di.ClassLoaderManager; -import org.apache.cayenne.di.DIBootstrap; -import org.apache.cayenne.di.Injector; -import org.apache.cayenne.di.Module; -import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory; -import org.apache.cayenne.di.spi.DefaultClassLoaderManager; -import org.apache.cayenne.event.EventBridge; -import org.apache.cayenne.event.EventManager; -import org.apache.cayenne.event.MockEventManager; -import org.apache.cayenne.event.NoopEventBridgeProvider; -import org.apache.cayenne.log.SQLLogger; -import org.apache.cayenne.log.Slf4jSQLLogger; -import org.apache.cayenne.map.EntitySorter; -import org.apache.cayenne.tx.DefaultTransactionFactory; -import org.apache.cayenne.tx.DefaultTransactionManager; -import org.apache.cayenne.tx.TransactionFactory; -import org.apache.cayenne.tx.TransactionManager; -import org.junit.jupiter.api.Test; - -import java.util.Collections; - -import static org.junit.jupiter.api.Assertions.*; - -public class DataContextFactoryTest { - - @Test - public void createDataContextWithDedicatedCache() throws Exception { - - final EventManager eventManager = new MockEventManager(); - final DataDomain domain = new DataDomain("d1"); - - domain.setSharedCacheEnabled(false); - - Module testModule = binder -> { - binder.bind(SQLLogger.class).to(Slf4jSQLLogger.class); - binder.bind(DataDomain.class).toInstance(domain); - binder.bind(EventManager.class).toInstance(eventManager); - binder.bind(QueryCache.class).toInstance(new MapQueryCache(5)); - binder.bind(RuntimeProperties.class).toInstance( - new DefaultRuntimeProperties(Collections.<String, String>emptyMap())); - binder.bind(ObjectMapRetainStrategy.class).to( - DefaultObjectMapRetainStrategy.class); - binder.bind(ObjectStoreFactory.class).to(DefaultObjectStoreFactory.class); - binder.bind(TransactionFactory.class).to(DefaultTransactionFactory.class); - binder.bind(TransactionManager.class).to(DefaultTransactionManager.class); - binder.bind(DataRowStoreFactory.class).to(DefaultDataRowStoreFactory.class); - binder.bind(EventBridge.class).toProvider(NoopEventBridgeProvider.class); - binder.bind(DataRowStoreFactory.class).to(DefaultDataRowStoreFactory.class); - binder.bind(DataDomainFlushActionFactory.class).to(DefaultDataDomainFlushActionFactory.class); - binder.bind(DbRowOpSorter.class).to(DefaultDbRowOpSorter.class); - binder.bind(DeleteDbRowOpFactory.class).to(HardDeleteDbRowOpFactory.class); - binder.bind(EntitySorter.class).to(AshwoodEntitySorter.class); - binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class); - binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class); - }; - - Injector injector = DIBootstrap.createInjector(testModule); - - DataContextFactory factory = new DataContextFactory(); - injector.injectMembers(factory); - - DataContext c3 = (DataContext) factory.createContext(); - assertNotNull(c3.getObjectStore().getDataRowCache()); - assertNull(domain.getSharedSnapshotCache()); - assertNotSame( - c3.getObjectStore().getDataRowCache(), - domain.getSharedSnapshotCache()); - } - - @Test - public void createDataContextValidation() throws Exception { - final EventManager eventManager = new MockEventManager(); - final DataDomain domain = new DataDomain("d1"); - - domain.setValidatingObjectsOnCommit(true); - - Module testModule = binder -> { - binder.bind(SQLLogger.class).to(Slf4jSQLLogger.class); - binder.bind(DataDomain.class).toInstance(domain); - binder.bind(EventManager.class).toInstance(eventManager); - binder.bind(QueryCache.class).toInstance(new MapQueryCache(5)); - binder.bind(RuntimeProperties.class).toInstance( - new DefaultRuntimeProperties(Collections.<String, String>emptyMap())); - binder.bind(ObjectMapRetainStrategy.class).to( - DefaultObjectMapRetainStrategy.class); - binder.bind(ObjectStoreFactory.class).to(DefaultObjectStoreFactory.class); - binder.bind(TransactionFactory.class).to(DefaultTransactionFactory.class); - binder.bind(TransactionManager.class).to(DefaultTransactionManager.class); - binder.bind(EventBridge.class).toProvider(NoopEventBridgeProvider.class); - binder.bind(DataRowStoreFactory.class).to(DefaultDataRowStoreFactory.class); - binder.bind(DataDomainFlushActionFactory.class).to(DefaultDataDomainFlushActionFactory.class); - binder.bind(DbRowOpSorter.class).to(DefaultDbRowOpSorter.class); - binder.bind(DeleteDbRowOpFactory.class).to(HardDeleteDbRowOpFactory.class); - binder.bind(EntitySorter.class).to(AshwoodEntitySorter.class); - binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class); - binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class); - }; - - Injector injector = DIBootstrap.createInjector(testModule); - - domain.setDataRowStoreFactory(injector.getInstance(DataRowStoreFactory.class)); - - DataContextFactory factory = new DataContextFactory(); - injector.injectMembers(factory); - - DataContext c1 = (DataContext) factory.createContext(); - assertTrue(c1.isValidatingObjectsOnCommit()); - - domain.setValidatingObjectsOnCommit(false); - - DataContext c2 = (DataContext) factory.createContext(); - assertFalse(c2.isValidatingObjectsOnCommit()); - } - -} diff --git a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataContextFactory_DedicatedCacheIT.java b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataContextFactory_DedicatedCacheIT.java new file mode 100644 index 000000000..2be76e9d9 --- /dev/null +++ b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataContextFactory_DedicatedCacheIT.java @@ -0,0 +1,52 @@ +/***************************************************************** + * 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 + * + * https://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.runtime; + +import org.apache.cayenne.access.DataContext; +import org.apache.cayenne.access.DataDomain; +import org.apache.cayenne.configuration.ObjectContextFactory; +import org.apache.cayenne.unit.CayenneProjects; +import org.apache.cayenne.unit.CayenneTestsEnv; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.junit.jupiter.api.Assertions.*; + +public class DataContextFactory_DedicatedCacheIT { + + @RegisterExtension + static final CayenneTestsEnv env = CayenneTestsEnv.forProject(CayenneProjects.MULTI_TIER_PROJECT); + + @Test + public void createDataContextWithDedicatedCache() { + + DataDomain domain = env.runtime().getDataDomain(); + domain.setSharedSnapshotCache(null); + + DataContext c3 = (DataContext) env.runtime().getInjector() + .getInstance(ObjectContextFactory.class) + .createContext(); + + assertNotNull(c3.getObjectStore().getDataRowCache()); + assertNull(domain.getSharedSnapshotCache()); + assertNotSame( + c3.getObjectStore().getDataRowCache(), + domain.getSharedSnapshotCache()); + } +} diff --git a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataContextFactory_ValidationIT.java b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataContextFactory_ValidationIT.java new file mode 100644 index 000000000..66a735141 --- /dev/null +++ b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataContextFactory_ValidationIT.java @@ -0,0 +1,52 @@ +/***************************************************************** + * 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 + * + * https://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.runtime; + +import org.apache.cayenne.access.DataContext; +import org.apache.cayenne.access.DataDomain; +import org.apache.cayenne.configuration.ObjectContextFactory; +import org.apache.cayenne.unit.CayenneProjects; +import org.apache.cayenne.unit.CayenneTestsEnv; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class DataContextFactory_ValidationIT { + + @RegisterExtension + static final CayenneTestsEnv env = CayenneTestsEnv.forProject(CayenneProjects.MULTI_TIER_PROJECT); + + @Test + public void createDataContextValidation() { + DataDomain domain = env.runtime().getDataDomain(); + domain.setValidatingObjectsOnCommit(true); + + ObjectContextFactory factory = env.runtime().getInjector().getInstance(ObjectContextFactory.class); + DataContext c1 = (DataContext) factory.createContext(); + assertTrue(c1.isValidatingObjectsOnCommit()); + + domain.setValidatingObjectsOnCommit(false); + + DataContext c2 = (DataContext) factory.createContext(); + assertFalse(c2.isValidatingObjectsOnCommit()); + } + +} diff --git a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderIT.java b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderIT.java new file mode 100644 index 000000000..08889e730 --- /dev/null +++ b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderIT.java @@ -0,0 +1,187 @@ +/***************************************************************** + * 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 + * + * https://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.runtime; + +import org.apache.cayenne.DataChannelQueryFilter; +import org.apache.cayenne.DataChannelQueryFilterChain; +import org.apache.cayenne.DataChannelSyncFilter; +import org.apache.cayenne.DataChannelSyncFilterChain; +import org.apache.cayenne.ObjectContext; +import org.apache.cayenne.QueryResponse; +import org.apache.cayenne.access.DataDomain; +import org.apache.cayenne.access.DataNode; +import org.apache.cayenne.access.dbsync.SkipSchemaUpdateStrategy; +import org.apache.cayenne.access.dbsync.ThrowOnPartialOrCreateSchemaStrategy; +import org.apache.cayenne.annotation.PostLoad; +import org.apache.cayenne.event.EventManager; +import org.apache.cayenne.graph.GraphDiff; +import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.map.LifecycleEvent; +import org.apache.cayenne.query.Query; +import org.apache.cayenne.testdo.db1.CrossdbM1E1; +import org.apache.cayenne.unit.CayenneProjects; +import org.apache.cayenne.unit.CayenneTestsEnv; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Tests a fully DI-initialized {@link DataDomain} produced by {@link DataDomainProvider} off a two-node project. + */ +public class DataDomainProviderIT { + + static final TestListener LISTENER = new TestListener(); + static final NoopQueryFilter QUERY_FILTER = new NoopQueryFilter(); + static final NoopSyncFilter SYNC_FILTER = new NoopSyncFilter(); + + @RegisterExtension + static final CayenneTestsEnv env = CayenneTestsEnv.forProject(CayenneProjects.DOMAIN_PROVIDER_PROJECT) + .withExtraModules(b -> CoreModule.extend(b) + .addListener(LISTENER) + .addQueryFilter(QUERY_FILTER) + .addSyncFilter(SYNC_FILTER)); + + @Test + public void dataMaps() { + DataDomain domain = env.runtime().getDataDomain(); + + assertEquals("domain-provider", domain.getName()); + assertEquals(2, domain.getDataMaps().size()); + assertNotNull(domain.getDataMap("map-db1")); + assertNotNull(domain.getDataMap("map-db2")); + } + + @Test + public void eventManagerFromDI() { + DataDomain domain = env.runtime().getDataDomain(); + + assertSame(env.runtime().getInjector().getInstance(EventManager.class), domain.getEventManager()); + } + + @Test + public void dataNodes() { + DataDomain domain = env.runtime().getDataDomain(); + assertEquals(2, domain.getDataNodes().size()); + + DataMap map1 = domain.getDataMap("map-db1"); + DataNode node1 = domain.getDataNode("node1"); + assertNotNull(node1); + assertEquals(1, node1.getDataMaps().size()); + assertSame(map1, node1.getDataMaps().iterator().next()); + assertSame(node1, domain.lookupDataNode(map1)); + + DataMap map2 = domain.getDataMap("map-db2"); + DataNode node2 = domain.getDataNode("node2"); + assertNotNull(node2); + assertEquals(1, node2.getDataMaps().size()); + assertSame(map2, node2.getDataMaps().iterator().next()); + assertSame(node2, domain.lookupDataNode(map2)); + } + + @Test + public void dataNodeConfig() { + DataDomain domain = env.runtime().getDataDomain(); + + for (DataNode node : domain.getDataNodes()) { + assertEquals(XMLPoolingDataSourceFactory.class.getName(), node.getDataSourceFactory()); + assertNotNull(node.getDataSource()); + assertNotNull(node.getAdapter()); + } + + // "node1" declares an explicit strategy, "node2" gets the default + assertEquals( + ThrowOnPartialOrCreateSchemaStrategy.class, + domain.getDataNode("node1").getSchemaUpdateStrategy().getClass()); + assertEquals( + SkipSchemaUpdateStrategy.class, + domain.getDataNode("node2").getSchemaUpdateStrategy().getClass()); + } + + @Test + public void noDefaultNodeWithMultipleNodes() { + // a default node is only inferred when the project declares exactly one node + assertNull(env.runtime().getDataDomain().getDefaultNode()); + } + + @Test + public void domainProperties() { + DataDomain domain = env.runtime().getDataDomain(); + + // "validatingObjectsOnCommit" is turned off by a <property> in the project file, shared cache is left at its + // default + assertFalse(domain.isValidatingObjectsOnCommit()); + assertTrue(domain.isSharedCacheEnabled()); + assertNotNull(domain.getSharedSnapshotCache()); + } + + @Test + public void listenersFromDI() { + DataDomain domain = env.runtime().getDataDomain(); + + int before = LISTENER.counter.get(); + domain.getEntityResolver().getCallbackRegistry() + .performCallbacks(LifecycleEvent.POST_LOAD, env.context().newObject(CrossdbM1E1.class)); + + assertEquals(before + 1, LISTENER.counter.get(), "Should call postLoadCallback()"); + } + + @Test + public void filtersFromDI() { + DataDomain domain = env.runtime().getDataDomain(); + + assertTrue(domain.getQueryFilters().contains(QUERY_FILTER)); + assertTrue(domain.getSyncFilters().contains(SYNC_FILTER)); + } + + static class TestListener { + + final AtomicInteger counter = new AtomicInteger(); + + @PostLoad + public void postLoadCallback(Object object) { + counter.incrementAndGet(); + } + } + + static class NoopQueryFilter implements DataChannelQueryFilter { + + @Override + public QueryResponse onQuery(ObjectContext originatingContext, Query query, + DataChannelQueryFilterChain filterChain) { + return filterChain.onQuery(originatingContext, query); + } + } + + static class NoopSyncFilter implements DataChannelSyncFilter { + + @Override + public GraphDiff onSync(ObjectContext originatingContext, GraphDiff changes, int syncType, + DataChannelSyncFilterChain filterChain) { + return filterChain.onSync(originatingContext, changes, syncType); + } + } +} diff --git a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java b/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java deleted file mode 100644 index 2d74d35d8..000000000 --- a/cayenne/src/test/java/org/apache/cayenne/configuration/runtime/DataDomainProviderTest.java +++ /dev/null @@ -1,310 +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 - * - * https://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.runtime; - -import org.apache.cayenne.ConfigurationException; -import org.apache.cayenne.DataChannel; -import org.apache.cayenne.ObjectId; -import org.apache.cayenne.Persistent; -import org.apache.cayenne.access.DataDomain; -import org.apache.cayenne.access.DataNode; -import org.apache.cayenne.access.DataRowStoreFactory; -import org.apache.cayenne.access.DefaultDataRowStoreFactory; -import org.apache.cayenne.access.dbsync.DefaultSchemaUpdateStrategyFactory; -import org.apache.cayenne.access.dbsync.SchemaUpdateStrategyFactory; -import org.apache.cayenne.access.dbsync.SkipSchemaUpdateStrategy; -import org.apache.cayenne.access.dbsync.ThrowOnPartialOrCreateSchemaStrategy; -import org.apache.cayenne.access.translator.SQLTemplateTranslator; -import org.apache.cayenne.access.jdbc.reader.RowReaderFactory; -import org.apache.cayenne.access.translator.BatchTranslator; -import org.apache.cayenne.access.translator.batch.DeleteBatchTranslator; -import org.apache.cayenne.access.translator.batch.InsertBatchTranslator; -import org.apache.cayenne.access.translator.batch.UpdateBatchTranslator; -import org.apache.cayenne.access.translator.procedure.DbAdapterDelegatedProcedureTranslator; -import org.apache.cayenne.access.translator.ProcedureTranslator; -import org.apache.cayenne.access.translator.ejbql.DbAdapterDelegatedEJBQLTranslator; -import org.apache.cayenne.access.translator.EJBQLTranslator; -import org.apache.cayenne.access.translator.select.DbAdapterDelegatedSelectTranslator; -import org.apache.cayenne.access.translator.SelectTranslator; -import org.apache.cayenne.access.types.DefaultValueObjectTypeRegistry; -import org.apache.cayenne.access.types.ValueObjectTypeRegistry; -import org.apache.cayenne.annotation.PostLoad; -import org.apache.cayenne.ashwood.AshwoodEntitySorter; -import org.apache.cayenne.cache.QueryCache; -import org.apache.cayenne.configuration.ConfigurationNameMapper; -import org.apache.cayenne.configuration.ConfigurationTree; -import org.apache.cayenne.configuration.Constants; -import org.apache.cayenne.configuration.DataChannelDescriptor; -import org.apache.cayenne.configuration.DataChannelDescriptorLoader; -import org.apache.cayenne.configuration.DataChannelDescriptorMerger; -import org.apache.cayenne.configuration.DataNodeDescriptor; -import org.apache.cayenne.configuration.DefaultConfigurationNameMapper; -import org.apache.cayenne.configuration.DefaultDataChannelDescriptorMerger; -import org.apache.cayenne.configuration.DefaultRuntimeProperties; -import org.apache.cayenne.configuration.RuntimeProperties; -import org.apache.cayenne.configuration.mock.MockDataSourceFactory; -import org.apache.cayenne.dba.JdbcPkGenerator; -import org.apache.cayenne.dba.PkGenerator; -import org.apache.cayenne.dba.db2.DB2Adapter; -import org.apache.cayenne.dba.db2.DB2PkGenerator; -import org.apache.cayenne.dba.db2.DB2Sniffer; -import org.apache.cayenne.dba.derby.DerbyAdapter; -import org.apache.cayenne.dba.derby.DerbyPkGenerator; -import org.apache.cayenne.dba.derby.DerbySniffer; -import org.apache.cayenne.dba.firebird.FirebirdSniffer; -import org.apache.cayenne.dba.frontbase.FrontBaseAdapter; -import org.apache.cayenne.dba.frontbase.FrontBasePkGenerator; -import org.apache.cayenne.dba.frontbase.FrontBaseSniffer; -import org.apache.cayenne.dba.h2.H2Adapter; -import org.apache.cayenne.dba.h2.H2PkGenerator; -import org.apache.cayenne.dba.h2.H2Sniffer; -import org.apache.cayenne.dba.hsqldb.HSQLDBSniffer; -import org.apache.cayenne.dba.ingres.IngresAdapter; -import org.apache.cayenne.dba.ingres.IngresPkGenerator; -import org.apache.cayenne.dba.ingres.IngresSniffer; -import org.apache.cayenne.dba.mariadb.MariaDBSniffer; -import org.apache.cayenne.dba.mysql.MySQLAdapter; -import org.apache.cayenne.dba.mysql.MySQLPkGenerator; -import org.apache.cayenne.dba.mysql.MySQLSniffer; -import org.apache.cayenne.dba.oracle.OracleAdapter; -import org.apache.cayenne.dba.oracle.OraclePkGenerator; -import org.apache.cayenne.dba.oracle.OracleSniffer; -import org.apache.cayenne.dba.postgres.PostgresAdapter; -import org.apache.cayenne.dba.postgres.PostgresPkGenerator; -import org.apache.cayenne.dba.postgres.PostgresSniffer; -import org.apache.cayenne.dba.sqlite.SQLiteSniffer; -import org.apache.cayenne.dba.sqlserver.SQLServerAdapter; -import org.apache.cayenne.dba.sqlserver.SQLServerSniffer; -import org.apache.cayenne.dba.sybase.SybaseAdapter; -import org.apache.cayenne.dba.sybase.SybasePkGenerator; -import org.apache.cayenne.dba.sybase.SybaseSniffer; -import org.apache.cayenne.di.AdhocObjectFactory; -import org.apache.cayenne.di.ClassLoaderManager; -import org.apache.cayenne.di.DIBootstrap; -import org.apache.cayenne.di.Injector; -import org.apache.cayenne.di.Key; -import org.apache.cayenne.di.Module; -import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory; -import org.apache.cayenne.di.spi.DefaultClassLoaderManager; -import org.apache.cayenne.event.EventBridge; -import org.apache.cayenne.event.EventManager; -import org.apache.cayenne.event.MockEventManager; -import org.apache.cayenne.event.NoopEventBridgeProvider; -import org.apache.cayenne.log.SQLLogger; -import org.apache.cayenne.log.Slf4jSQLLogger; -import org.apache.cayenne.map.DataMap; -import org.apache.cayenne.map.EntitySorter; -import org.apache.cayenne.map.LifecycleEvent; -import org.apache.cayenne.reflect.generic.DefaultValueComparisonStrategyFactory; -import org.apache.cayenne.reflect.generic.ValueComparisonStrategyFactory; -import org.apache.cayenne.resource.ClassLoaderResourceLocator; -import org.apache.cayenne.resource.Resource; -import org.apache.cayenne.resource.ResourceLocator; -import org.apache.cayenne.resource.mock.MockResource; -import org.junit.jupiter.api.Test; - -import java.util.Collection; -import java.util.Collections; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class DataDomainProviderTest { - - @Test - public void get() { - - // create dependencies - final String testConfigName = "testConfig"; - final DataChannelDescriptor testDescriptor = new DataChannelDescriptor(); - - DataMap map1 = new DataMap("map1"); - testDescriptor.getDataMaps().add(map1); - - DataMap map2 = new DataMap("map2"); - testDescriptor.getDataMaps().add(map2); - - DataNodeDescriptor nodeDescriptor1 = new DataNodeDescriptor(); - nodeDescriptor1.setName("node1"); - nodeDescriptor1.getDataMapNames().add("map1"); - nodeDescriptor1.setAdapterType(OracleAdapter.class.getName()); - nodeDescriptor1.setDataSourceFactoryType(MockDataSourceFactory.class.getName()); - nodeDescriptor1.setParameters("jdbc/testDataNode1"); - nodeDescriptor1.setSchemaUpdateStrategyType(ThrowOnPartialOrCreateSchemaStrategy.class.getName()); - testDescriptor.getNodeDescriptors().add(nodeDescriptor1); - - DataNodeDescriptor nodeDescriptor2 = new DataNodeDescriptor(); - nodeDescriptor2.setName("node2"); - nodeDescriptor2.getDataMapNames().add("map2"); - nodeDescriptor2.setParameters("testDataNode2.driver.xml"); - testDescriptor.getNodeDescriptors().add(nodeDescriptor2); - - final DataChannelDescriptorLoader testLoader = new DataChannelDescriptorLoader() { - - @Override - public ConfigurationTree<DataChannelDescriptor> load(Resource configurationResource) - throws ConfigurationException { - return new ConfigurationTree<>(testDescriptor, null); - } - }; - - final EventManager eventManager = new MockEventManager(); - final TestListener mockListener = new TestListener(); - - Module testModule = b -> { - - ClassLoaderManager classLoaderManager = new DefaultClassLoaderManager(); - b.bind(ClassLoaderManager.class).toInstance(classLoaderManager); - b.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class); - b.bind(PkGenerator.class).to(JdbcPkGenerator.class); - b.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class); - - CoreModule.extend(b) - .initAllExtensions() - - .addAdapterDetector(FirebirdSniffer.class) - .addAdapterDetector(FrontBaseSniffer.class).addAdapterDetector(IngresSniffer.class) - .addAdapterDetector(SQLiteSniffer.class).addAdapterDetector(DB2Sniffer.class) - .addAdapterDetector(H2Sniffer.class).addAdapterDetector(HSQLDBSniffer.class) - .addAdapterDetector(SybaseSniffer.class).addAdapterDetector(DerbySniffer.class) - .addAdapterDetector(SQLServerSniffer.class).addAdapterDetector(OracleSniffer.class) - .addAdapterDetector(PostgresSniffer.class).addAdapterDetector(MySQLSniffer.class) - .addAdapterDetector(MariaDBSniffer.class) - - .addListener(mockListener) - .addProjectLocation(testConfigName) - - .addPkGenerator(DB2Adapter.class, DB2PkGenerator.class) - .addPkGenerator(DerbyAdapter.class, DerbyPkGenerator.class) - .addPkGenerator(FrontBaseAdapter.class, FrontBasePkGenerator.class) - .addPkGenerator(H2Adapter.class, H2PkGenerator.class) - .addPkGenerator(IngresAdapter.class, IngresPkGenerator.class) - .addPkGenerator(MySQLAdapter.class, MySQLPkGenerator.class) - .addPkGenerator(OracleAdapter.class, OraclePkGenerator.class) - .addPkGenerator(PostgresAdapter.class, PostgresPkGenerator.class) - .addPkGenerator(SQLServerAdapter.class, SybasePkGenerator.class) - .addPkGenerator(SybaseAdapter.class, SybasePkGenerator.class); - - b.bind(EventManager.class).toInstance(eventManager); - b.bind(EntitySorter.class).toInstance(new AshwoodEntitySorter()); - b.bind(SchemaUpdateStrategyFactory.class).to(DefaultSchemaUpdateStrategyFactory.class); - - final ResourceLocator locator = new ClassLoaderResourceLocator(classLoaderManager) { - - public Collection<Resource> findResources(String name) { - assertEquals(testConfigName, name); - return Collections.<Resource>singleton(new MockResource()); - } - }; - - b.bind(ResourceLocator.class).toInstance(locator); - b.bind(Key.get(ResourceLocator.class, Constants.RESOURCE_LOCATOR)).toInstance(locator); - b.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class); - b.bind(DataChannelDescriptorMerger.class).to(DefaultDataChannelDescriptorMerger.class); - b.bind(DataChannelDescriptorLoader.class).toInstance(testLoader); - b.bind(DbAdapterFactory.class).to(DefaultDbAdapterFactory.class); - b.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class); - b.bind(Key.get(BatchTranslator.class, BatchTranslator.INSERT)).to(InsertBatchTranslator.class); - b.bind(Key.get(BatchTranslator.class, BatchTranslator.UPDATE)).to(UpdateBatchTranslator.class); - b.bind(Key.get(BatchTranslator.class, BatchTranslator.DELETE)).to(DeleteBatchTranslator.class); - b.bind(SelectTranslator.class).to(DbAdapterDelegatedSelectTranslator.class); - b.bind(ProcedureTranslator.class).to(DbAdapterDelegatedProcedureTranslator.class); - b.bind(EJBQLTranslator.class).to(DbAdapterDelegatedEJBQLTranslator.class); - - b.bind(DataSourceFactory.class).toInstance(new MockDataSourceFactory()); - b.bind(SQLLogger.class).to(Slf4jSQLLogger.class); - b.bind(QueryCache.class).toInstance(mock(QueryCache.class)); - b.bind(RowReaderFactory.class).toInstance(mock(RowReaderFactory.class)); - b.bind(DataNodeFactory.class).to(DefaultDataNodeFactory.class); - b.bind(SQLTemplateTranslator.class).toInstance(mock(SQLTemplateTranslator.class)); - - b.bind(EventBridge.class).toProvider(NoopEventBridgeProvider.class); - b.bind(DataRowStoreFactory.class).to(DefaultDataRowStoreFactory.class); - - b.bind(ValueObjectTypeRegistry.class).to(DefaultValueObjectTypeRegistry.class); - b.bind(ValueComparisonStrategyFactory.class).to(DefaultValueComparisonStrategyFactory.class); - }; - - Injector injector = DIBootstrap.createInjector(testModule); - - // create and initialize provide instance to test - DataDomainProvider provider = new DataDomainProvider(); - injector.injectMembers(provider); - - DataChannel channel = provider.get(); - assertNotNull(channel); - - assertTrue(channel instanceof DataDomain); - - DataDomain domain = (DataDomain) channel; - assertSame(eventManager, domain.getEventManager()); - assertEquals(2, domain.getDataMaps().size()); - assertTrue(domain.getDataMaps().contains(map1)); - assertTrue(domain.getDataMaps().contains(map2)); - - assertEquals(2, domain.getDataNodes().size()); - DataNode node1 = domain.getDataNode("node1"); - assertNotNull(node1); - assertEquals(1, node1.getDataMaps().size()); - assertSame(map1, node1.getDataMaps().iterator().next()); - assertSame(node1, domain.lookupDataNode(map1)); - assertEquals(nodeDescriptor1.getDataSourceFactoryType(), node1.getDataSourceFactory()); - assertNotNull(node1.getDataSource()); - - assertNotNull(node1.getSchemaUpdateStrategy()); - assertEquals(nodeDescriptor1.getSchemaUpdateStrategyType(), node1.getSchemaUpdateStrategy().getClass() - .getName()); - - assertNotNull(node1.getAdapter()); - assertEquals(OracleAdapter.class, node1.getAdapter().getClass()); - - DataNode node2 = domain.getDataNode("node2"); - assertNotNull(node2); - assertEquals(1, node2.getDataMaps().size()); - assertSame(map2, node2.getDataMaps().iterator().next()); - assertSame(node2, domain.lookupDataNode(map2)); - assertNull(node2.getDataSourceFactory()); - assertNotNull(node2.getDataSource()); - assertNotNull(node2.getSchemaUpdateStrategy()); - assertEquals(SkipSchemaUpdateStrategy.class.getName(), node2.getSchemaUpdateStrategy().getClass().getName()); - - assertNotNull(node2.getAdapter()); - - // check that we have mock listener passed correctly - Persistent mockPersistent = mock(Persistent.class); - ObjectId mockObjectId = mock(ObjectId.class); - when(mockObjectId.getEntityName()).thenReturn("mock-entity-name"); - when(mockPersistent.getObjectId()).thenReturn(mockObjectId); - domain.getEntityResolver().getCallbackRegistry().performCallbacks(LifecycleEvent.POST_LOAD, mockPersistent); - - assertEquals(1, TestListener.counter.get(), "Should call postLoadCallback() method"); - } - - static class TestListener { - - static private AtomicInteger counter = new AtomicInteger(); - - @PostLoad - public void postLoadCallback(Object object) { - counter.incrementAndGet(); - } - } -} diff --git a/cayenne/src/test/java/org/apache/cayenne/event/MockEventBridgeProvider.java b/cayenne/src/test/java/org/apache/cayenne/event/MockEventBridgeProvider.java index ad9cc21c2..34ae3a895 100644 --- a/cayenne/src/test/java/org/apache/cayenne/event/MockEventBridgeProvider.java +++ b/cayenne/src/test/java/org/apache/cayenne/event/MockEventBridgeProvider.java @@ -19,21 +19,20 @@ package org.apache.cayenne.event; -import org.apache.cayenne.access.DataDomain; import org.apache.cayenne.di.DIRuntimeException; -import org.apache.cayenne.di.Inject; import org.apache.cayenne.di.Provider; import java.util.Collections; +/** + * Note that this provider can't depend on the DataDomain: the shared snapshot cache, and hence the EventBridge, is + * created while the DataDomain itself is being assembled. + */ public class MockEventBridgeProvider implements Provider<EventBridge> { - @Inject - protected DataDomain dataDomain; - @Override public EventBridge get() throws DIRuntimeException { - EventSubject snapshotEventSubject = EventSubject.getSubject(this.getClass(), dataDomain.getName());; + EventSubject snapshotEventSubject = EventSubject.getSubject(this.getClass(), "mock-snapshot-events"); return new MockEventBridge( Collections.singleton(snapshotEventSubject), diff --git a/cayenne/src/test/java/org/apache/cayenne/unit/CayenneProjects.java b/cayenne/src/test/java/org/apache/cayenne/unit/CayenneProjects.java index 1d6bc3c4e..b7648d003 100644 --- a/cayenne/src/test/java/org/apache/cayenne/unit/CayenneProjects.java +++ b/cayenne/src/test/java/org/apache/cayenne/unit/CayenneProjects.java @@ -26,6 +26,7 @@ public class CayenneProjects { public static final String CAY_2032 = "cayenne-cay-2032.xml"; public static final String COMPOUND_PROJECT = "cayenne-compound.xml"; public static final String DATE_TIME_PROJECT = "cayenne-date-time.xml"; + public static final String DOMAIN_PROVIDER_PROJECT = "cayenne-domain-provider.xml"; public static final String EMBEDDABLE_PROJECT = "cayenne-embeddable.xml"; public static final String EMPTY_PROJECT = "cayenne-empty.xml"; public static final String ENUM_PROJECT = "cayenne-enum.xml"; diff --git a/cayenne/src/test/resources/cayenne-domain-provider.xml b/cayenne/src/test/resources/cayenne-domain-provider.xml new file mode 100644 index 000000000..ff9fb537b --- /dev/null +++ b/cayenne/src/test/resources/cayenne-domain-provider.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<domain xmlns="http://cayenne.apache.org/schema/12/domain" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://cayenne.apache.org/schema/12/domain https://cayenne.apache.org/schema/12/domain.xsd" + project-version="12"> + <property name="cayenne.DataDomain.validatingObjectsOnCommit" value="false"/> + <map name="map-db1"/> + <map name="map-db2"/> + <node name="node1" + factory="org.apache.cayenne.configuration.runtime.XMLPoolingDataSourceFactory" + schema-update-strategy="org.apache.cayenne.access.dbsync.ThrowOnPartialOrCreateSchemaStrategy"> + <map-ref name="map-db1"/> + </node> + <node name="node2" + factory="org.apache.cayenne.configuration.runtime.XMLPoolingDataSourceFactory"> + <map-ref name="map-db2"/> + </node> +</domain> diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/main/DataDomainMainView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/main/DataDomainMainView.java index 0e35fff37..488dd39a5 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/main/DataDomainMainView.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/main/DataDomainMainView.java @@ -22,21 +22,21 @@ package org.apache.cayenne.modeler.ui.project.editor.datadomain.main; import com.jgoodies.forms.builder.PanelBuilder; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; -import org.apache.cayenne.access.DataDomain; import org.apache.cayenne.configuration.DataChannelDescriptor; +import org.apache.cayenne.configuration.runtime.DataDomainProvider; import org.apache.cayenne.modeler.event.display.DomainDisplayEvent; import org.apache.cayenne.modeler.event.display.DomainDisplayListener; import org.apache.cayenne.modeler.event.model.DomainEvent; +import org.apache.cayenne.modeler.project.ProjectSession; +import org.apache.cayenne.modeler.toolkit.ProjectPanel; import org.apache.cayenne.modeler.toolkit.checkbox.CMCheckBox; import org.apache.cayenne.modeler.toolkit.text.CMUndoableTextField; -import org.apache.cayenne.modeler.toolkit.ProjectPanel; -import org.apache.cayenne.modeler.project.ProjectSession; -import java.util.Objects; import org.apache.cayenne.validation.ValidationException; import javax.swing.*; import java.awt.*; import java.util.Map; +import java.util.Objects; /** * Panel for editing DataDomain. @@ -96,17 +96,17 @@ public class DataDomainMainView extends ProjectPanel implements DomainDisplayLis objectValidation.addItemListener(e -> { String value = objectValidation.isSelected() ? "true" : "false"; setDomainProperty( - DataDomain.VALIDATING_OBJECTS_ON_COMMIT_PROPERTY, + DataDomainProvider.VALIDATING_OBJECTS_ON_COMMIT_PROPERTY, value, - Boolean.toString(DataDomain.VALIDATING_OBJECTS_ON_COMMIT_DEFAULT)); + DataDomainProvider.VALIDATING_OBJECTS_ON_COMMIT_DEFAULT); }); sharedCache.addItemListener(e -> { String value = sharedCache.isSelected() ? "true" : "false"; setDomainProperty( - DataDomain.SHARED_CACHE_ENABLED_PROPERTY, + DataDomainProvider.SHARED_CACHE_ENABLED_PROPERTY, value, - Boolean.toString(DataDomain.SHARED_CACHE_ENABLED_DEFAULT)); + DataDomainProvider.SHARED_CACHE_ENABLED_DEFAULT); }); } @@ -177,12 +177,12 @@ public class DataDomainMainView extends ProjectPanel implements DomainDisplayLis name.setText(domain.getName()); objectValidation.setSelected(getDomainBooleanProperty( - DataDomain.VALIDATING_OBJECTS_ON_COMMIT_PROPERTY, - Boolean.toString(DataDomain.VALIDATING_OBJECTS_ON_COMMIT_DEFAULT))); + DataDomainProvider.VALIDATING_OBJECTS_ON_COMMIT_PROPERTY, + DataDomainProvider.VALIDATING_OBJECTS_ON_COMMIT_DEFAULT)); sharedCache.setSelected(getDomainBooleanProperty( - DataDomain.SHARED_CACHE_ENABLED_PROPERTY, - Boolean.toString(DataDomain.SHARED_CACHE_ENABLED_DEFAULT))); + DataDomainProvider.SHARED_CACHE_ENABLED_PROPERTY, + DataDomainProvider.SHARED_CACHE_ENABLED_DEFAULT)); } void setDomainName(String newName) {
