You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2018/11/09 08:01:23 UTC

[isis] branch v2 updated: ISIS-2020: properly predict Federated Store Manager

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch v2
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/v2 by this push:
     new 44d3079  ISIS-2020: properly predict Federated Store Manager
44d3079 is described below

commit 44d30790eb139bf8f0394d5fbe7f23decbdf3f46
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Nov 9 08:49:19 2018 +0100

    ISIS-2020: properly predict Federated Store Manager
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-2020
---
 .../org/apache/isis/applib/util/JaxbAdapters.java  |   7 ++
 .../system/persistence/DNStoreManagerType.java     | 130 +++++++++++++++++++++
 .../DataNucleusApplicationComponents5.java         |  85 ++++++--------
 3 files changed, 173 insertions(+), 49 deletions(-)

diff --git a/core/applib/src/main/java/org/apache/isis/applib/util/JaxbAdapters.java b/core/applib/src/main/java/org/apache/isis/applib/util/JaxbAdapters.java
index dcbe8a6..ace6f9c 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/util/JaxbAdapters.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/util/JaxbAdapters.java
@@ -27,7 +27,14 @@ import javax.xml.bind.annotation.adapters.XmlAdapter;
 /**
  * Provides JAXB XmlAdapters for Java built-in temporal types. 
  * Others types might be added, if convenient. 
+ * <p>
  * 
+ * Example:<pre>
+ * &#64;XmlElement &#64;XmlJavaTypeAdapter(JaxbAdapters.LocalDateAdapter.class)
+ * &#64;Getter &#64;Setter private LocalDate javaLocalDate;
+ * </pre>
+ * 
+ *  
  * @since 2.0.0-M2
  */
 public final class JaxbAdapters {
diff --git a/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/DNStoreManagerType.java b/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/DNStoreManagerType.java
new file mode 100644
index 0000000..71e7447
--- /dev/null
+++ b/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/DNStoreManagerType.java
@@ -0,0 +1,130 @@
+/*
+ *  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.isis.core.runtime.system.persistence;
+
+import java.util.Map;
+import java.util.function.Function;
+
+import org.datanucleus.PersistenceNucleusContext;
+import org.datanucleus.api.jdo.JDOPersistenceManagerFactory;
+import org.datanucleus.store.StoreManager;
+import org.datanucleus.store.federation.FederatedStoreManager;
+import org.datanucleus.store.schema.SchemaAwareStoreManager;
+
+/**
+ * Given only config properties, tries to find, which kind of store manager
+ * Datanucleus is going to utilize. We do this prior to bootstrapping Datanucleus, 
+ * to allow for programmatic override of given config properties. 
+ * (eg. proper schema creation setup)  
+ * 
+ * @since 2.0.0-M2
+ */
+enum DNStoreManagerType {
+
+    SchemaAware,
+    Federated, // [ahuber] not used by now
+    Other
+    ;
+
+    public static DNStoreManagerType typeOf(Map<String,String> datanucleusProps) {
+
+        if(hasSecondaryDataStore(datanucleusProps)) {
+            return Federated; 
+        } 
+        
+        if(isKnownSchemaAwareStoreManagerIfNotFederated(datanucleusProps)) {
+            return SchemaAware;
+        }
+        
+        return probe(datanucleusProps, storeManager->{
+            
+            if(storeManager instanceof SchemaAwareStoreManager) {
+                return SchemaAware;
+            }
+            
+            if(storeManager instanceof FederatedStoreManager) {
+                return Federated;
+            }
+            
+            return Other;
+            
+        });
+
+    }
+    
+    public boolean isSchemaAware() {
+        return this == SchemaAware;
+    }
+
+    // -- HELPER
+    
+    /* not necessarily complete, just for speed up */
+    private final static String[] knownSchemaAwareIfNotFederated = {
+            "jdbc:hsqldb:",
+            "jdbc:sqlserver:",
+            "jdbc:h2:",
+            "jdbc:mysql:",
+            "jdbc:mariadb:",
+            "jdbc:postgresql:",
+            "jdbc:db2:",
+            };
+    
+    private static boolean hasSecondaryDataStore(Map<String,String> datanucleusProps) {
+        final boolean hasSecondaryDataStore = datanucleusProps.keySet().stream()
+            .anyMatch(key->key.startsWith("datanucleus.datastore."));
+        return hasSecondaryDataStore;
+    }
+
+    private static boolean isKnownSchemaAwareStoreManagerIfNotFederated(Map<String,String> datanucleusProps) {
+
+        // this saves some time, but also avoids the (still undiagnosed) issue that instantiating the
+        // PMF can cause the ClassMetadata for the entity classes to be loaded in and cached prior to
+        // registering the CreateSchemaObjectFromClassData (to invoke 'create schema' first)
+        final String connectionUrl = datanucleusProps.get("javax.jdo.option.ConnectionURL");
+        if(connectionUrl != null) {
+            for(String magic : knownSchemaAwareIfNotFederated) {
+                if (connectionUrl.startsWith(magic)) {
+                    return true;
+                }
+            }
+        }
+        
+        return false;
+    }
+    
+    private static DNStoreManagerType probe(
+            Map<String,String> datanucleusProps, 
+            Function<StoreManager, DNStoreManagerType> categorizer) {
+        
+        // we create a throw-away instance of PMF so that we can probe whether DN has
+        // been configured with a schema-aware store manager or not.
+        final JDOPersistenceManagerFactory probePmf = (JDOPersistenceManagerFactory) 
+                DataNucleusApplicationComponents5.newPersistenceManagerFactory(datanucleusProps);
+
+        try {
+            final PersistenceNucleusContext nucleusContext = probePmf.getNucleusContext();
+            final StoreManager storeManager = nucleusContext.getStoreManager();
+            
+            return categorizer.apply(storeManager);
+        } finally {
+            probePmf.close();
+        }
+    }
+
+}
diff --git a/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/DataNucleusApplicationComponents5.java b/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/DataNucleusApplicationComponents5.java
index 78b36b4..3fa3287 100644
--- a/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/DataNucleusApplicationComponents5.java
+++ b/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/DataNucleusApplicationComponents5.java
@@ -18,8 +18,6 @@
  */
 package org.apache.isis.core.runtime.system.persistence;
 
-import static org.apache.isis.commons.internal.base._NullSafe.stream;
-
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
@@ -33,7 +31,6 @@ import org.datanucleus.PropertyNames;
 import org.datanucleus.api.jdo.JDOPersistenceManagerFactory;
 import org.datanucleus.metadata.MetaDataListener;
 import org.datanucleus.metadata.MetaDataManager;
-import org.datanucleus.store.StoreManager;
 import org.datanucleus.store.schema.SchemaAwareStoreManager;
 
 import org.apache.isis.commons.internal.collections._Maps;
@@ -49,6 +46,8 @@ import org.apache.isis.objectstore.jdo.datanucleus.DataNucleusPropertiesAware;
 import org.apache.isis.objectstore.jdo.metamodel.facets.object.query.JdoNamedQuery;
 import org.apache.isis.objectstore.jdo.metamodel.facets.object.query.JdoQueryFacet;
 
+import static org.apache.isis.commons.internal.base._NullSafe.stream;
+
 public class DataNucleusApplicationComponents5 implements ApplicationScopedComponent {
 
     public static final String CLASS_METADATA_LOADED_LISTENER_KEY = "classMetadataLoadedListener";
@@ -65,7 +64,8 @@ public class DataNucleusApplicationComponents5 implements ApplicationScopedCompo
      */
     public static MetaDataManager getMetaDataManager() {
         return instance != null
-                ? ((JDOPersistenceManagerFactory)instance.persistenceManagerFactory).getNucleusContext().getMetaDataManager()
+                ? ((JDOPersistenceManagerFactory)instance.persistenceManagerFactory)
+                        .getNucleusContext().getMetaDataManager()
                         : null;
     }
 
@@ -97,7 +97,8 @@ public class DataNucleusApplicationComponents5 implements ApplicationScopedCompo
         this.persistableClassNameSet = persistableClassNameSet;
         this.jdoObjectstoreConfig = configuration;
 
-        persistenceManagerFactory = createPmfAndSchemaIfRequired(this.persistableClassNameSet, this.datanucleusProps);
+        persistenceManagerFactory = createPmfAndSchemaIfRequired(
+                this.persistableClassNameSet, this.datanucleusProps);
 
         // for JRebel plugin
         instance = this;
@@ -117,60 +118,28 @@ public class DataNucleusApplicationComponents5 implements ApplicationScopedCompo
         }
     }
 
-    private static PersistenceManagerFactory newPersistenceManagerFactory(Map<String, String> datanucleusProps) {
+    static PersistenceManagerFactory newPersistenceManagerFactory(Map<String, String> datanucleusProps) {
         return JDOHelper.getPersistenceManagerFactory(datanucleusProps, IsisContext.getClassLoader());
     }
 
-    private static boolean isSchemaAwareStoreManager(Map<String,String> datanucleusProps) {
-
-        // this saves some time, but also avoids the (still undiagnosed) issue that instantiating the
-        // PMF can cause the ClassMetadata for the entity classes to be loaded in and cached prior to
-        // registering the CreateSchemaObjectFromClassData (to invoke 'create schema' first)
-        final String connectionUrl = datanucleusProps.get("javax.jdo.option.ConnectionURL");
-        if(connectionUrl != null) {
-            if (connectionUrl.startsWith("jdbc:hsqldb")) return true;
-            if (connectionUrl.startsWith("jdbc:sqlserver")) return true;
-        }
-
-        // we create a throw-away instance of PMF so that we can probe whether DN has
-        // been configured with a schema-aware store manager or not.
-        final JDOPersistenceManagerFactory probePmf =
-                (JDOPersistenceManagerFactory) newPersistenceManagerFactory(datanucleusProps);
-
-
-        try {
-            final PersistenceNucleusContext nucleusContext = probePmf.getNucleusContext();
-            final StoreManager storeManager = nucleusContext.getStoreManager();
-            return storeManager instanceof SchemaAwareStoreManager;
-        } finally {
-            probePmf.close();
-        }
-    }
-
     // REF: http://www.datanucleus.org/products/datanucleus/jdo/schema.html
-    private PersistenceManagerFactory createPmfAndSchemaIfRequired(final Set<String> persistableClassNameSet, final Map<String, String> datanucleusProps) {
+    private PersistenceManagerFactory createPmfAndSchemaIfRequired(
+            final Set<String> persistableClassNameSet, 
+            final Map<String, String> datanucleusProps) {
 
+        final DNStoreManagerType dnStoreManagerType = DNStoreManagerType.typeOf(datanucleusProps);
+        
         PersistenceManagerFactory persistenceManagerFactory;
-        if(isSchemaAwareStoreManager(datanucleusProps)) {
+
+        if(dnStoreManagerType.isSchemaAware()) {
 
             // rather than reinvent too much of the wheel, we reuse the same property that DN would check
             // for if it were doing the auto-creation itself (read from isis.properties)
             final boolean createSchema = isSet(datanucleusProps, PropertyNames.PROPERTY_SCHEMA_AUTOCREATE_ALL);
 
             if(createSchema) {
-
-                // we *don't* use DN's eager loading (autoStart), because doing so means that it attempts to
-                // create the table before the schema (for any entities annotated @PersistenceCapable(schema=...)
-                //
-                // instead, we manually create the schema ourselves
-                // (if the configured StoreMgr supports it, and if requested in isis.properties)
-                //
-                datanucleusProps.put(PropertyNames.PROPERTY_SCHEMA_AUTOCREATE_ALL, "false"); // turn off, cos want to do the schema object ourselves...
-                datanucleusProps.put(PropertyNames.PROPERTY_SCHEMA_AUTOCREATE_DATABASE, "false");
-                datanucleusProps.put(PropertyNames.PROPERTY_SCHEMA_AUTOCREATE_TABLES, "true"); // but have DN do everything else...
-                datanucleusProps.put(PropertyNames.PROPERTY_SCHEMA_AUTOCREATE_COLUMNS, "true");
-                datanucleusProps.put(PropertyNames.PROPERTY_SCHEMA_AUTOCREATE_CONSTRAINTS, "true");
-
+                
+                configureAutoCreateSchema(datanucleusProps);
                 persistenceManagerFactory = newPersistenceManagerFactory(datanucleusProps);
                 createSchema(persistenceManagerFactory, persistableClassNameSet, datanucleusProps);
 
@@ -191,7 +160,24 @@ public class DataNucleusApplicationComponents5 implements ApplicationScopedCompo
 
     }
 
-    private void configureAutoStart(final Set<String> persistableClassNameSet, final Map<String, String> datanucleusProps) {
+    private void configureAutoCreateSchema(final Map<String, String> datanucleusProps) {
+        // we *don't* use DN's eager loading (autoStart), because doing so means that it attempts to
+        // create the table before the schema (for any entities annotated @PersistenceCapable(schema=...)
+        //
+        // instead, we manually create the schema ourselves
+        // (if the configured StoreMgr supports it, and if requested in isis.properties)
+        //
+        datanucleusProps.put(PropertyNames.PROPERTY_SCHEMA_AUTOCREATE_ALL, "false"); // turn off, cos want to do the schema object ourselves...
+        datanucleusProps.put(PropertyNames.PROPERTY_SCHEMA_AUTOCREATE_DATABASE, "false");
+        datanucleusProps.put(PropertyNames.PROPERTY_SCHEMA_AUTOCREATE_TABLES, "true"); // but have DN do everything else...
+        datanucleusProps.put(PropertyNames.PROPERTY_SCHEMA_AUTOCREATE_COLUMNS, "true");
+        datanucleusProps.put(PropertyNames.PROPERTY_SCHEMA_AUTOCREATE_CONSTRAINTS, "true");
+    }
+    
+    private void configureAutoStart(
+            final Set<String> persistableClassNameSet, 
+            final Map<String, String> datanucleusProps) {
+        
         final String persistableClassNames =
                 stream(persistableClassNameSet).collect(Collectors.joining(","));
 
@@ -208,7 +194,8 @@ public class DataNucleusApplicationComponents5 implements ApplicationScopedCompo
 
         JDOPersistenceManagerFactory jdopmf = (JDOPersistenceManagerFactory) persistenceManagerFactory;
         final PersistenceNucleusContext nucleusContext = jdopmf.getNucleusContext();
-        final SchemaAwareStoreManager schemaAwareStoreManager = (SchemaAwareStoreManager)nucleusContext.getStoreManager();
+        final SchemaAwareStoreManager schemaAwareStoreManager = 
+                (SchemaAwareStoreManager)nucleusContext.getStoreManager();
 
         final MetaDataManager metaDataManager = nucleusContext.getMetaDataManager();