You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2018/01/05 10:46:12 UTC
[isis] 13/16: ISIS-1756 on shutdown purge any state associated with
the current web-app classloader
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch ISIS-1779-jax-rs-2
in repository https://gitbox.apache.org/repos/asf/isis.git
commit 363639cfae2c6c355c4a5fc607e72e3226dddff8
Author: Andi Huber <ah...@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 87d447f..737f95c 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 ahuber@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 ahuber@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" <co...@isis.apache.org>.