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

ahuber pushed a commit to branch dev/2.0.0/ISIS-1767-jee-7
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/dev/2.0.0/ISIS-1767-jee-7 by 
this push:
     new 4805392  ISIS-1756 on shutdown purge any state associated with the 
current web-app classloader
4805392 is described below

commit 48053925364871ce30cf832360ee9b6855f1ee95
Author: Andi Huber <ahu...@apache.org>
AuthorDate: Fri Dec 8 04:23:58 2017 +0100

    ISIS-1756 on shutdown purge any state associated with the current
    web-app classloader
---
 core/pom.xml                                       |   6 +-
 .../core/runtime/system/context/IsisContext.java   |   3 +-
 .../DataNucleusApplicationComponents.java          |  22 ++++
 .../persistence/PersistenceSessionFactory.java     |   6 +-
 .../datanucleus/DataNucleusLifeCycleHelper.java    | 125 +++++++++++++++++++++
 5 files changed, 157 insertions(+), 5 deletions(-)

diff --git a/core/pom.xml b/core/pom.xml
index 47e117a..becc447 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -86,10 +86,10 @@
         <!-- Datanucleus Objectstore -->
         <jdo-api.version>3.2.0-m7</jdo-api.version>
 
-        <datanucleus-core.version>5.1.2</datanucleus-core.version>
-        <datanucleus-api-jdo.version>5.1.2</datanucleus-api-jdo.version>
+        <datanucleus-core.version>5.1.5-SNAPSHOT</datanucleus-core.version>
+        
<datanucleus-api-jdo.version>5.1.5-SNAPSHOT</datanucleus-api-jdo.version>
         <datanucleus-jdo-query.version>5.0.2</datanucleus-jdo-query.version>
-        <datanucleus-rdbms.version>5.1.2</datanucleus-rdbms.version>
+        <datanucleus-rdbms.version>5.1.5-SNAPSHOT</datanucleus-rdbms.version>
         
<datanucleus-jodatime.version>5.1.0-release</datanucleus-jodatime.version>
        <!--
            ISIS-1288: seen integration tests to fail;
diff --git 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContext.java
 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContext.java
index 9aaf71b..059914b 100644
--- 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContext.java
+++ 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContext.java
@@ -127,7 +127,7 @@ public final class IsisContext {
 
        /**
         * TODO [andi-huber] not sure if required, initial idea was to force 
log4j
-        * re-configuration on a undeply/deploy cycle
+        * re-configuration on a undeploy/deploy cycle
         */
        private static void resetLogging() {
                org.apache.log4j.Logger.getRootLogger().removeAllAppenders();
@@ -136,4 +136,5 @@ public final class IsisContext {
 
 
 
+
 }
diff --git 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/DataNucleusApplicationComponents.java
 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/DataNucleusApplicationComponents.java
index 8fafca8..986e649 100644
--- 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/DataNucleusApplicationComponents.java
+++ 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/DataNucleusApplicationComponents.java
@@ -18,6 +18,9 @@
  */
 package org.apache.isis.core.runtime.system.persistence;
 
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
@@ -32,15 +35,19 @@ import 
org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import 
org.apache.isis.objectstore.jdo.datanucleus.CreateSchemaObjectFromClassMetadata;
+import org.apache.isis.objectstore.jdo.datanucleus.DataNucleusLifeCycleHelper;
 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 org.datanucleus.ClassLoaderResolver;
 import org.datanucleus.PersistenceNucleusContext;
 import org.datanucleus.PropertyNames;
 import org.datanucleus.api.jdo.JDOPersistenceManagerFactory;
 import org.datanucleus.metadata.MetaDataListener;
 import org.datanucleus.metadata.MetaDataManager;
+import org.datanucleus.store.AbstractStoreManager;
 import org.datanucleus.store.StoreManager;
+import org.datanucleus.store.autostart.AutoStartMechanism;
 import org.datanucleus.store.schema.SchemaAwareStoreManager;
 
 import com.google.common.base.Joiner;
@@ -109,6 +116,21 @@ public class DataNucleusApplicationComponents implements 
ApplicationScopedCompon
 
         namedQueryByName = catalogNamedQueries(persistableClassNameSet);
     }
+    
+    /** 
+     * Marks the end of DataNucleus' life-cycle. Purges any state associated 
with DN. 
+     * Subsequent calls have no effect.  
+     * 
+     * @author ahu...@apache.org
+     * @since 2.0.0
+     */
+    public void shutdown() {
+       instance = null;
+       if(persistenceManagerFactory != null) {
+               DataNucleusLifeCycleHelper.cleanUp(persistenceManagerFactory);
+               persistenceManagerFactory = null;
+       }
+    }
 
     private static boolean isSchemaAwareStoreManager(Map<String,String> 
datanucleusProps) {
 
diff --git 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionFactory.java
 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionFactory.java
index 4be046c..989c989 100644
--- 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionFactory.java
+++ 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionFactory.java
@@ -164,7 +164,11 @@ public class PersistenceSessionFactory implements 
ApplicationScopedComponent, Fi
     //region > shutdown
     @Programmatic
     public final void shutdown() {
-        // no-op
+       //XXX ISIS-1756 purge any DataNucleus State
+       if(applicationComponents != null) {
+               applicationComponents.shutdown();
+               applicationComponents = null;
+       }
     }
 
     //endregion
diff --git 
a/core/runtime/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/DataNucleusLifeCycleHelper.java
 
b/core/runtime/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/DataNucleusLifeCycleHelper.java
new file mode 100644
index 0000000..93ba482
--- /dev/null
+++ 
b/core/runtime/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/DataNucleusLifeCycleHelper.java
@@ -0,0 +1,125 @@
+/*
+ *  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.objectstore.jdo.datanucleus;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Field;
+import java.util.Map;
+import java.util.function.Consumer;
+
+import javax.jdo.PersistenceManagerFactory;
+
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.datanucleus.ClassLoaderResolver;
+import org.datanucleus.PersistenceNucleusContext;
+import org.datanucleus.api.jdo.JDOPersistenceManagerFactory;
+import org.datanucleus.enhancer.EnhancementHelper;
+import org.datanucleus.store.AbstractStoreManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 
+ * Purges any state associated with DataNucleus.
+ * 
+ * @author ahu...@apache.org
+ * @since 2.0.0
+ *
+ */
+public class DataNucleusLifeCycleHelper {
+       
+    private static final Logger LOG = 
LoggerFactory.getLogger(DataNucleusLifeCycleHelper.class);
+
+       public static void cleanUp(PersistenceManagerFactory 
persistenceManagerFactory) {
+               
+               try {
+                       
+                       final ClassLoader cl = IsisContext.getClassLoader();
+                       
+                       if(persistenceManagerFactory instanceof 
JDOPersistenceManagerFactory) {
+                               
+                               final JDOPersistenceManagerFactory jdoPMF = 
+                                               (JDOPersistenceManagerFactory) 
persistenceManagerFactory;
+                               final PersistenceNucleusContext nucleusContext 
= jdoPMF.getNucleusContext();
+                               final AbstractStoreManager storeManager = 
+                                               
(AbstractStoreManager)nucleusContext.getStoreManager();
+                               
+                       
+                               persistenceManagerFactory.getManagedClasses()
+                               .forEach(clazz->{
+                               final ClassLoaderResolver clr = 
nucleusContext.getClassLoaderResolver(cl);
+                                                       
+                               // Un-manage from the store
+                               storeManager.unmanageClass(clr, 
clazz.getName(), false);
+                               
+                                        // Unload the meta-data for this class
+                               
nucleusContext.getMetaDataManager().unloadMetaDataForClass(clazz.getName());
+                               });
+                       }
+                       
+                       persistenceManagerFactory.close();
+                       dnUnregisterClassesManagedBy(cl);
+                       
+                       
+               } catch (Exception e) {
+                       // ignore, since it only affects re-deploy-ability, 
which is nice to have but not critical
+               }
+
+       }
+    
+    // -- HELPER
+    
+    private static void dnUnregisterClassesManagedBy(ClassLoader cl) {
+       if(cl==null)
+               return;
+               visitDNRegisteredClasses(map->
+                       map.entrySet()
+                       
.removeIf(entry->cl.equals(entry.getKey().getClassLoader()))
+               );
+       }
+    
+    // -- LOW LEVEL REFLECTION
+    
+       private final static MethodHandle getRegisteredClassesMH;
+       static {
+               MethodHandle mh;                
+               try {
+                       Field registeredClasses = 
EnhancementHelper.class.getDeclaredField("registeredClasses");
+                       registeredClasses.setAccessible(true);
+                       mh = 
MethodHandles.lookup().unreflectGetter(registeredClasses);
+                       registeredClasses.setAccessible(false);
+               } catch (Exception e) {
+                       mh = null;
+                       e.printStackTrace();
+               }
+               getRegisteredClassesMH = mh;
+       }
+       
+       private static void visitDNRegisteredClasses(Consumer<Map<Class<?>, ?>> 
visitor){
+               try {
+                       visitor.accept( (Map<Class<?>, ?>) 
getRegisteredClassesMH.invoke() );
+               } catch (Throwable e) {
+                       LOG.warn("Failed to access DataNucleus' 
EnhancementHelper via reflection.", e);
+               }
+       }
+
+
+
+}

-- 
To stop receiving notification emails like this one, please contact
['"commits@isis.apache.org" <commits@isis.apache.org>'].

Reply via email to