modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/SubjectGWTServiceImpl.java | 11
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/authentication/LogoutAction.java | 3
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/SessionCacheListener.java | 22 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/prefs/SubjectPreferencesBase.java | 13
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/prefs/SubjectPreferencesCache.java | 139 --------
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/prefs/SubjectPreferencesCacheBean.java | 171 ++++++++++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/prefs/SubjectPreferencesCacheLocal.java | 38 ++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/ShutdownListener.java | 36 +-
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java | 31 -
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java | 8
10 files changed, 287 insertions(+), 185 deletions(-)
New commits:
commit b19c778b7fae320ed14a155602556d083af782c0
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Sep 13 12:03:20 2012 -0400
fix subject preference cache - making it a ejb singleton
also made ShutdownListener a ejb singleton with PreDestroy method
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/SubjectGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/SubjectGWTServiceImpl.java
index bbdd102..52cae1d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/SubjectGWTServiceImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/SubjectGWTServiceImpl.java
@@ -28,7 +28,7 @@ import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.gwt.SubjectGWTService;
import org.rhq.enterprise.gui.coregui.server.util.SerialUtility;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
-import org.rhq.enterprise.server.auth.prefs.SubjectPreferencesCache;
+import org.rhq.enterprise.server.auth.prefs.SubjectPreferencesCacheLocal;
import org.rhq.enterprise.server.exception.LoginException;
import org.rhq.enterprise.server.util.LookupUtil;
@@ -40,6 +40,7 @@ public class SubjectGWTServiceImpl extends AbstractGWTServiceImpl implements Sub
private static final long serialVersionUID = 1L;
private SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+ private SubjectPreferencesCacheLocal prefsCache = LookupUtil.getSubjectPreferencesCache();
private Object subjectLock = new Object(); // used to lock out concurrent subject updates
public void createPrincipal(String username, String password) throws RuntimeException {
@@ -106,7 +107,7 @@ public class SubjectGWTServiceImpl extends AbstractGWTServiceImpl implements Sub
Subject subject = SerialUtility.prepare(modifiedSubject, "SubjectManager.updateSubjectPW");
// Clear the prefs for this subject from the user prefs cache that portal-war uses, in case we just
// changed any prefs; otherwise the cache would contain stale prefs.
- SubjectPreferencesCache.getInstance().clearConfiguration(subject.getId());
+ LookupUtil.getSubjectPreferencesCache().clearConfiguration(subject.getId());
return subject;
} catch (Throwable t) {
throw getExceptionToThrowToClient(t);
@@ -170,8 +171,8 @@ public class SubjectGWTServiceImpl extends AbstractGWTServiceImpl implements Sub
subjectToModify = subjectManager.getSubjectById(subjectToModify.getId());
subjectToModify.setUserConfiguration(prefs);
}
-
- Configuration persistedPrefs = SubjectPreferencesCache.getInstance().getPreferences(subjectToModify.getId());
+
+ Configuration persistedPrefs = prefsCache.getPreferences(subjectToModify.getId());
if (updatePrefs && changedPrefs != null) {
Configuration userPrefs = subjectToModify.getUserConfiguration();
@@ -191,7 +192,7 @@ public class SubjectGWTServiceImpl extends AbstractGWTServiceImpl implements Sub
if (updatePrefs) {
//clear the prefs cache so that JSF UI refreshes it
- SubjectPreferencesCache.getInstance().clearConfiguration(subjectToModify.getId());
+ prefsCache.clearConfiguration(subjectToModify.getId());
}
}
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/authentication/LogoutAction.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/authentication/LogoutAction.java
index b86acae..1a0cfd5 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/authentication/LogoutAction.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/authentication/LogoutAction.java
@@ -37,7 +37,6 @@ import org.rhq.enterprise.gui.legacy.WebUser;
import org.rhq.enterprise.gui.legacy.util.RequestUtils;
import org.rhq.enterprise.gui.legacy.util.SessionUtils;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
-import org.rhq.enterprise.server.auth.prefs.SubjectPreferencesCache;
import org.rhq.enterprise.server.util.LookupUtil;
public class LogoutAction extends Action {
@@ -72,7 +71,7 @@ public class LogoutAction extends Action {
if (webUser != null) {
Subject subject = webUser.getSubject();
if (subject != null) {
- SubjectPreferencesCache.getInstance().clearConfiguration(subject.getId());
+ LookupUtil.getSubjectPreferencesCache().clearConfiguration(subject.getId());
}
}
}
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/SessionCacheListener.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/SessionCacheListener.java
index faa8873..caa58b5 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/SessionCacheListener.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/SessionCacheListener.java
@@ -1,3 +1,21 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
package org.rhq.enterprise.gui.startup;
import javax.servlet.http.HttpSessionEvent;
@@ -6,7 +24,7 @@ import javax.servlet.http.HttpSessionListener;
import org.rhq.core.domain.auth.Subject;
import org.rhq.enterprise.gui.legacy.WebUser;
import org.rhq.enterprise.gui.legacy.util.SessionUtils;
-import org.rhq.enterprise.server.auth.prefs.SubjectPreferencesCache;
+import org.rhq.enterprise.server.util.LookupUtil;
public class SessionCacheListener implements HttpSessionListener {
@@ -19,7 +37,7 @@ public class SessionCacheListener implements HttpSessionListener {
if (webUser != null) {
Subject subject = webUser.getSubject();
if (subject != null) {
- SubjectPreferencesCache.getInstance().clearConfiguration(subject.getId());
+ LookupUtil.getSubjectPreferencesCache().clearConfiguration(subject.getId());
}
}
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/prefs/SubjectPreferencesBase.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/prefs/SubjectPreferencesBase.java
index 5b1b980..e8ef7c3 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/prefs/SubjectPreferencesBase.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/prefs/SubjectPreferencesBase.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -20,9 +20,7 @@ package org.rhq.enterprise.server.auth.prefs;
import java.lang.reflect.Method;
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -30,6 +28,7 @@ import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.util.StringUtil;
+import org.rhq.enterprise.server.util.LookupUtil;
public abstract class SubjectPreferencesBase {
@@ -41,11 +40,9 @@ public abstract class SubjectPreferencesBase {
protected static final String PREF_ITEM_DELIM_REGEX = "\\|";
private int subjectId;
- private Set<String> changed;
public SubjectPreferencesBase(Subject subject) {
this.subjectId = subject.getId();
- this.changed = new HashSet<String>();
}
/**
@@ -117,7 +114,7 @@ public abstract class SubjectPreferencesBase {
}
protected String getPreference(String key) throws IllegalArgumentException {
- PropertySimple prop = SubjectPreferencesCache.getInstance().getUserProperty(subjectId, key);
+ PropertySimple prop = LookupUtil.getSubjectPreferencesCache().getUserProperty(subjectId, key);
if (prop == null) {
if (this.subjectId == 0) {
@@ -239,10 +236,10 @@ public abstract class SubjectPreferencesBase {
val = value.toString();
}
- SubjectPreferencesCache.getInstance().setUserProperty(subjectId, key, val);
+ LookupUtil.getSubjectPreferencesCache().setUserProperty(subjectId, key, val);
}
protected void unsetPreference(String key) {
- SubjectPreferencesCache.getInstance().unsetUserProperty(subjectId, key);
+ LookupUtil.getSubjectPreferencesCache().unsetUserProperty(subjectId, key);
}
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/prefs/SubjectPreferencesCache.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/prefs/SubjectPreferencesCache.java
deleted file mode 100644
index d88bd85..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/prefs/SubjectPreferencesCache.java
+++ /dev/null
@@ -1,139 +0,0 @@
-package org.rhq.enterprise.server.auth.prefs;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.rhq.core.domain.auth.Subject;
-import org.rhq.core.domain.configuration.Configuration;
-import org.rhq.core.domain.configuration.Property;
-import org.rhq.core.domain.configuration.PropertySimple;
-import org.rhq.enterprise.server.auth.SubjectManagerLocal;
-import org.rhq.enterprise.server.common.EntityManagerFacadeLocal;
-import org.rhq.enterprise.server.configuration.ConfigurationManagerLocal;
-import org.rhq.enterprise.server.util.LookupUtil;
-
-public class SubjectPreferencesCache {
-
- protected final Log log = LogFactory.getLog(SubjectPreferencesCache.class);
-
- private Map<Integer, Configuration> subjectPreferences;
-
- private static final SubjectPreferencesCache instance = new SubjectPreferencesCache();
-
- private SubjectManagerLocal subjectManager;
- private EntityManagerFacadeLocal entityManagerFacade;
- private ConfigurationManagerLocal configurationManager;
-
- private SubjectPreferencesCache() {
- subjectPreferences = new HashMap<Integer, Configuration>();
- subjectManager = LookupUtil.getSubjectManager();
- entityManagerFacade = LookupUtil.getEntityManagerFacade();
- configurationManager = LookupUtil.getConfigurationManager();
- }
-
- public static SubjectPreferencesCache getInstance() {
- return instance;
- }
-
- private void load(int subjectId) {
- // if subject ID is 0, it probably means this is a new LDAP user that needs to be registered
- if (subjectId != 0 && !subjectPreferences.containsKey(subjectId)) {
- try {
- Subject subject = subjectManager.loadUserConfiguration(subjectId);
- Configuration configuration = subject.getUserConfiguration();
- subjectPreferences.put(subjectId, configuration);
- } catch (Throwable t) {
- log.warn("Can not get preferences for subject[id=" + subjectId + "], subject does not exist yet");
- }
- }
- }
-
- public synchronized PropertySimple getUserProperty(int subjectId, String propertyName) {
- load(subjectId);
-
- Configuration config = subjectPreferences.get(subjectId);
- if (config == null) {
- return null;
- }
-
- PropertySimple prop = config.getSimple(propertyName);
- if (prop == null) {
- return null;
- }
-
- return new PropertySimple(propertyName, prop.getStringValue());
- }
-
- public synchronized void setUserProperty(int subjectId, String propertyName, String value) {
- load(subjectId);
-
- Configuration config = subjectPreferences.get(subjectId);
- if (config == null) {
- return;
- }
-
- PropertySimple prop = config.getSimple(propertyName);
- if (prop == null) {
- prop = new PropertySimple(propertyName, value);
- config.put(prop); // add new to collection
- mergeProperty(prop);
- } else if (prop.getStringValue() == null || !prop.getStringValue().equals(value)) {
- prop.setStringValue(value);
- mergeProperty(prop);
- }
- }
-
- private void mergeProperty(PropertySimple prop) {
- // merge will persist if property doesn't exist (i.e., id = 0)
- PropertySimple mergedProperty = entityManagerFacade.merge(prop); // only merge changes
- if (prop.getId() == 0) {
- // so subsequent merges do not continue re-persisting property as new
- prop.setId(mergedProperty.getId());
- }
- }
-
- public synchronized void unsetUserProperty(int subjectId, String propertyName) {
- load(subjectId);
-
- Configuration config = subjectPreferences.get(subjectId);
- if (config == null) {
- return;
- }
-
- Property property = config.remove(propertyName);
- // it's possible property was already removed, and thus this operation becomes a no-op to the backing store
- if (property != null && property.getId() != 0) {
- try {
- configurationManager.deleteProperties(new int[] { property.getId() });
- } catch (Throwable t) {
- log.error("Could not remove " + property, t);
- }
- }
- }
-
- /**
- * @param subjectId the subject to get preferences of
- * @return the <b>COPY</b> of the configuration object - changes done to that instance will not be reflected in the persisted
- * preferences
- */
- public synchronized Configuration getPreferences(int subjectId) {
- load(subjectId);
-
- Configuration config = subjectPreferences.get(subjectId);
- if (config == null) {
- return new Configuration();
- } else {
- return config.deepCopy();
- }
- }
-
- public synchronized void clearConfiguration(int subjectId) {
- if (log.isTraceEnabled()) {
- log.trace("Removing PreferencesCache For " + subjectId);
- }
- subjectPreferences.remove(subjectId);
- }
-}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/prefs/SubjectPreferencesCacheBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/prefs/SubjectPreferencesCacheBean.java
new file mode 100644
index 0000000..d196d07
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/prefs/SubjectPreferencesCacheBean.java
@@ -0,0 +1,171 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.server.auth.prefs;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ejb.ConcurrencyManagement;
+import javax.ejb.ConcurrencyManagementType;
+import javax.ejb.EJB;
+import javax.ejb.Lock;
+import javax.ejb.LockType;
+import javax.ejb.Singleton;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.Property;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.common.EntityManagerFacadeLocal;
+import org.rhq.enterprise.server.configuration.ConfigurationManagerLocal;
+
+(a)ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
+@Singleton
+public class SubjectPreferencesCacheBean implements SubjectPreferencesCacheLocal {
+
+ protected final Log log = LogFactory.getLog(SubjectPreferencesCacheBean.class);
+
+ private Map<Integer, Configuration> subjectPreferences;
+
+ @EJB
+ private SubjectManagerLocal subjectManager;
+
+ @EJB
+ private EntityManagerFacadeLocal entityManagerFacade;
+
+ @EJB
+ private ConfigurationManagerLocal configurationManager;
+
+ private SubjectPreferencesCacheBean() {
+ subjectPreferences = new HashMap<Integer, Configuration>();
+ }
+
+ private void load(int subjectId) {
+ // if subject ID is 0, it probably means this is a new LDAP user that needs to be registered
+ if (subjectId != 0 && !subjectPreferences.containsKey(subjectId)) {
+ try {
+ Subject subject = subjectManager.loadUserConfiguration(subjectId);
+ Configuration configuration = subject.getUserConfiguration();
+ subjectPreferences.put(subjectId, configuration);
+ } catch (Throwable t) {
+ log.warn("Can not get preferences for subject[id=" + subjectId + "], subject does not exist yet");
+ }
+ }
+ }
+
+ @Override
+ @Lock(LockType.READ)
+ public PropertySimple getUserProperty(int subjectId, String propertyName) {
+ load(subjectId);
+
+ Configuration config = subjectPreferences.get(subjectId);
+ if (config == null) {
+ return null;
+ }
+
+ PropertySimple prop = config.getSimple(propertyName);
+ if (prop == null) {
+ return null;
+ }
+
+ return new PropertySimple(propertyName, prop.getStringValue());
+ }
+
+ @Override
+ @Lock(LockType.WRITE)
+ public void setUserProperty(int subjectId, String propertyName, String value) {
+ load(subjectId);
+
+ Configuration config = subjectPreferences.get(subjectId);
+ if (config == null) {
+ return;
+ }
+
+ PropertySimple prop = config.getSimple(propertyName);
+ if (prop == null) {
+ prop = new PropertySimple(propertyName, value);
+ config.put(prop); // add new to collection
+ mergeProperty(prop);
+ } else if (prop.getStringValue() == null || !prop.getStringValue().equals(value)) {
+ prop.setStringValue(value);
+ mergeProperty(prop);
+ }
+ }
+
+ private void mergeProperty(PropertySimple prop) {
+ // merge will persist if property doesn't exist (i.e., id = 0)
+ PropertySimple mergedProperty = entityManagerFacade.merge(prop); // only merge changes
+ if (prop.getId() == 0) {
+ // so subsequent merges do not continue re-persisting property as new
+ prop.setId(mergedProperty.getId());
+ }
+ }
+
+ @Override
+ @Lock(LockType.WRITE)
+ public void unsetUserProperty(int subjectId, String propertyName) {
+ load(subjectId);
+
+ Configuration config = subjectPreferences.get(subjectId);
+ if (config == null) {
+ return;
+ }
+
+ Property property = config.remove(propertyName);
+ // it's possible property was already removed, and thus this operation becomes a no-op to the backing store
+ if (property != null && property.getId() != 0) {
+ try {
+ configurationManager.deleteProperties(new int[] { property.getId() });
+ } catch (Throwable t) {
+ log.error("Could not remove " + property, t);
+ }
+ }
+ }
+
+ /**
+ * @param subjectId the subject to get preferences of
+ * @return the <b>COPY</b> of the configuration object - changes done to that instance will not be reflected in the persisted
+ * preferences
+ */
+ @Override
+ @Lock(LockType.READ)
+ public Configuration getPreferences(int subjectId) {
+ load(subjectId);
+
+ Configuration config = subjectPreferences.get(subjectId);
+ if (config == null) {
+ return new Configuration();
+ } else {
+ return config.deepCopy();
+ }
+ }
+
+ @Override
+ @Lock(LockType.WRITE)
+ public void clearConfiguration(int subjectId) {
+ if (log.isTraceEnabled()) {
+ log.trace("Removing PreferencesCache For " + subjectId);
+ }
+ subjectPreferences.remove(subjectId);
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/prefs/SubjectPreferencesCacheLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/prefs/SubjectPreferencesCacheLocal.java
new file mode 100644
index 0000000..73e82e7
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/prefs/SubjectPreferencesCacheLocal.java
@@ -0,0 +1,38 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.server.auth.prefs;
+
+import javax.ejb.Local;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+
+@Local
+public interface SubjectPreferencesCacheLocal {
+
+ PropertySimple getUserProperty(int subjectId, String propertyName);
+
+ void setUserProperty(int subjectId, String propertyName, String value);
+
+ void unsetUserProperty(int subjectId, String propertyName);
+
+ Configuration getPreferences(int subjectId);
+
+ void clearConfiguration(int subjectId);
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/ShutdownListener.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/ShutdownListener.java
index 5194fb6..f8dca66 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/ShutdownListener.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/ShutdownListener.java
@@ -23,9 +23,10 @@ import java.sql.SQLException;
import java.sql.Statement;
import javax.annotation.PreDestroy;
+import javax.annotation.Resource;
+import javax.ejb.EJB;
import javax.ejb.Singleton;
import javax.ejb.Startup;
-import javax.management.Notification;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
@@ -34,7 +35,10 @@ import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.cloud.Server;
import org.rhq.core.domain.cloud.Server.OperationMode;
import org.rhq.core.util.jdbc.JDBCUtil;
-import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.RHQConstants;
+import org.rhq.enterprise.server.cloud.CloudManagerLocal;
+import org.rhq.enterprise.server.cloud.instance.ServerManagerLocal;
+import org.rhq.enterprise.server.scheduler.SchedulerLocal;
/**
* This listens for the RHQ server's shutdown notification and when it hears it, will start shutting down RHQ components
@@ -47,13 +51,22 @@ import org.rhq.enterprise.server.util.LookupUtil;
@Singleton
@Startup
public class ShutdownListener {
- /**
- * Logger
- */
private final Log log = LogFactory.getLog(ShutdownListener.class);
private final String RHQ_DB_TYPE_MAPPING_PROPERTY = "rhq.server.database.type-mapping";
+ @EJB
+ private SchedulerLocal schedulerBean;
+
+ @EJB
+ private ServerManagerLocal serverManager;
+
+ @EJB
+ private CloudManagerLocal cloudManager;
+
+ @Resource(name = "RHQ_DS", mappedName = RHQConstants.DATASOURCE_JNDI_NAME)
+ private DataSource dataSource;
+
/**
* This is called when the shutdown notification is received from the JBoss server. This gives a chance for us to
* cleanly shutdown our application in an orderly fashion.
@@ -61,12 +74,14 @@ public class ShutdownListener {
* @see javax.management.NotificationListener#handleNotification(Notification, Object)
*/
@PreDestroy
- public void handleNotification(Notification notification, Object handback) {
+ public void handleNotification() {
// JBossAS 4.2.3 used to send us this JMX notification on shutdown - AS7 does not have shutdown notifications.
// So we are using the @PreDestroy mechanism on a singleton EJB to attempt to clean up the application before it is shutdown
+ log.info("Shutdown listener has been told we are shutting down - starting to clean up now...");
stopScheduler();
updateServerOperationMode();
stopEmbeddedDatabase();
+ log.info("Shutdown listener completed its shutdown tasks. It is safe to shutdown now.");
}
/**
@@ -75,7 +90,7 @@ public class ShutdownListener {
private void stopScheduler() {
try {
log.info("Shutting down the scheduler gracefully - currently running jobs will be allowed to finish...");
- LookupUtil.getSchedulerBean().shutdown(true);
+ schedulerBean.shutdown(true);
log.info("The scheduler has been shutdown and all jobs are done.");
} catch (Throwable t) {
// only show ugly stack traces if the user runs the server in debug mode
@@ -90,9 +105,9 @@ public class ShutdownListener {
private void updateServerOperationMode() {
try {
// Set the server operation mode to DOWN unless in MM
- Server server = LookupUtil.getServerManager().getServer();
+ Server server = serverManager.getServer();
if (Server.OperationMode.MAINTENANCE != server.getOperationMode()) {
- LookupUtil.getCloudManager().updateServerMode(new Integer[] { server.getId() }, OperationMode.DOWN);
+ cloudManager.updateServerMode(new Integer[] { server.getId() }, OperationMode.DOWN);
}
} catch (Throwable t) {
// only show ugly stack traces if the user runs the server in debug mode
@@ -113,8 +128,7 @@ public class ShutdownListener {
Connection connection = null;
Statement statement = null;
try {
- DataSource ds = LookupUtil.getDataSource();
- connection = ds.getConnection();
+ connection = dataSource.getConnection();
statement = connection.createStatement();
statement.execute("shutdown");
log.info("Embedded database closed cleanly");
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
index c5b0823..e1ef4a8 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
@@ -27,6 +27,7 @@ import java.util.List;
import java.util.Properties;
import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.Singleton;
import javax.ejb.Startup;
@@ -49,10 +50,10 @@ import org.rhq.core.domain.resource.Agent;
import org.rhq.core.util.ObjectNameFactory;
import org.rhq.enterprise.communications.ServiceContainerConfigurationConstants;
import org.rhq.enterprise.communications.util.SecurityUtil;
+import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.alert.engine.internal.AlertConditionCacheCoordinator;
import org.rhq.enterprise.server.auth.SessionManager;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
-import org.rhq.enterprise.server.auth.prefs.SubjectPreferencesCache;
import org.rhq.enterprise.server.cloud.CloudManagerLocal;
import org.rhq.enterprise.server.cloud.instance.CacheConsistencyManagerLocal;
import org.rhq.enterprise.server.cloud.instance.ServerManagerLocal;
@@ -84,6 +85,8 @@ import org.rhq.enterprise.server.util.concurrent.AvailabilityReportSerializer;
* This startup singleton EJB performs the rest of the RHQ Server startup initialization.
* In order for it to do its work properly, we must ensure everything has been deployed and started;
* specifically, all EJBs must have been deployed and available.
+ *
+ * This bean is not meant for client consumption - it is only for startup initialization.
*/
@Singleton
@Startup
@@ -116,6 +119,9 @@ public class StartupBean {
@EJB
private SubjectManagerLocal subjectManager;
+ @Resource(name = "RHQ_DS", mappedName = RHQConstants.DATASOURCE_JNDI_NAME)
+ private DataSource dataSource;
+
/**
* Performs the final RHQ Server initialization work that needs to talk place. EJBs are available in this method.
*
@@ -133,7 +139,6 @@ public class StartupBean {
// get singletons right now so we load the classes immediately into our classloader
AlertConditionCacheCoordinator.getInstance();
SessionManager.getInstance();
- SubjectPreferencesCache.getInstance();
AlertSerializer.getSingleton();
AvailabilityReportSerializer.getSingleton();
@@ -179,8 +184,7 @@ public class StartupBean {
// Ensure the class is loaded and the dbType is set for our current db
Connection conn = null;
try {
- DataSource ds = LookupUtil.getDataSource();
- conn = ds.getConnection();
+ conn = dataSource.getConnection();
DatabaseTypeFactory.setDefaultDatabaseType(DatabaseTypeFactory.getDatabaseType(conn));
} catch (Exception e) {
log.error("Could not initialize server.", e);
@@ -683,24 +687,17 @@ public class StartupBean {
}
/**
- * Registers a listener to the JBoss server's shutdown notification so some components can be cleaned up in an
+ * Registers a listener to the system shutdown notification so some components can be cleaned up in an
* orderly fashion when the server is shutdown.
*
- * @throws RuntimeException if cannot register this service as a shutdown listener
+ * @throws RuntimeException if cannot register a shutdown listener
*/
private void registerShutdownListener() throws RuntimeException {
// as of JBossAS 4.0.5, this is the known MBean name of the service that notifies when the server is shutting down
- // TODO: find out how AS7 can notify us when its going down - right now, this code won't work on AS7
- /*
- try {
- ObjectName jbossServerName = new ObjectName("jboss.system:type=Server");
- MBeanServer jbossServer = ManagementFactory.getPlatformMBeanServer();
- jbossServer.addNotificationListener(jbossServerName, new ShutdownListener(), null, null);
- } catch (Exception e) {
- throw new RuntimeException("Failed to register the Server Shutdown Listener", e);
- }
- */
- log.warn("!!! TODO: REGISTER OUR SHUTDOWN LISTENER!!!");
+ // AS7 today does not have notifications like this. So we have a new EJB singleton ShutdownListener with a PreDestroy method.
+ // If that doesn't work, we can try to create a system shutdown hook in here. Thus I'm leaving this method in here in case
+ // we need it later. Just add a Runtime.addShutdownHook call in here that calls our ShutdownListener.
+ return;
}
/**
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
index 313f295..183fc3e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
@@ -53,6 +53,8 @@ import org.rhq.enterprise.server.alert.engine.jms.CachedConditionProducerBean;
import org.rhq.enterprise.server.alert.engine.jms.CachedConditionProducerLocal;
import org.rhq.enterprise.server.auth.SubjectManagerBean;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.auth.prefs.SubjectPreferencesCacheBean;
+import org.rhq.enterprise.server.auth.prefs.SubjectPreferencesCacheLocal;
import org.rhq.enterprise.server.authz.AuthorizationManagerBean;
import org.rhq.enterprise.server.authz.AuthorizationManagerLocal;
import org.rhq.enterprise.server.authz.RoleManagerBean;
@@ -604,7 +606,11 @@ public final class LookupUtil {
public static PlatformUtilizationManagerLocal getPlatformUtilizationManager() {
return lookupLocal(PlatformUtilizationManagerBean.class);
}
-
+
+ public static SubjectPreferencesCacheLocal getSubjectPreferencesCache() {
+ return lookupLocal(SubjectPreferencesCacheBean.class);
+ }
+
public static CoreServerMBean getCoreServer() {
CoreServerMBean rhqServer;
try {