Author: taylor Date: Tue May 26 01:20:23 2015 New Revision: 1681669 URL: http://svn.apache.org/r1681669 Log: JS2-1325: initial implementation (read, write) of preferences caching performance improvements
Added: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletpreferences/UserSessionPreferences.java Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletpreferences/PortletPreferencesServiceImpl.java Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletpreferences/PortletPreferencesServiceImpl.java URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletpreferences/PortletPreferencesServiceImpl.java?rev=1681669&r1=1681668&r2=1681669&view=diff ============================================================================== --- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletpreferences/PortletPreferencesServiceImpl.java (original) +++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletpreferences/PortletPreferencesServiceImpl.java Tue May 26 01:20:23 2015 @@ -16,7 +16,10 @@ */ package org.apache.jetspeed.components.portletpreferences; +import org.apache.jetspeed.Jetspeed; import org.apache.jetspeed.JetspeedActions; +import org.apache.jetspeed.administration.PortalConfiguration; +import org.apache.jetspeed.administration.PortalConfigurationConstants; import org.apache.jetspeed.cache.CacheElement; import org.apache.jetspeed.cache.JetspeedCache; import org.apache.jetspeed.container.PortletWindow; @@ -26,6 +29,8 @@ import org.apache.jetspeed.om.portlet.Po import org.apache.jetspeed.om.portlet.Preference; import org.apache.jetspeed.om.portlet.Preferences; import org.apache.jetspeed.om.preference.FragmentPreference; +import org.apache.jetspeed.request.RequestContext; +import org.apache.jetspeed.request.RequestContextComponent; import org.apache.jetspeed.security.SubjectHelper; import org.apache.jetspeed.security.User; import org.apache.ojb.broker.query.Criteria; @@ -62,6 +67,7 @@ import java.util.TreeSet; public class PortletPreferencesServiceImpl extends PersistenceBrokerDaoSupport implements PortletPreferencesProvider { + protected static final String SESSION_CACHE_KEY = "portlet.preferences.user.key"; protected static final String DISCRIMINATOR_PORTLET = "portlet"; protected static final String DISCRIMINATOR_ENTITY = "entity"; protected static final String DISCRIMINATOR_USER = "user"; @@ -74,6 +80,8 @@ public class PortletPreferencesServiceIm protected static final String USER_NAME = "userName"; private PortletFactory portletFactory; + protected RequestContextComponent requestContextComponent; + protected PortalConfiguration configuration; /** * Cache elements are stored as element type JetspeedPreferencesMap @@ -82,8 +90,13 @@ public class PortletPreferencesServiceIm private List<String> preloadedApplications = null; private boolean preloadEntities = false; private boolean useEntityPreferences = true; + // JS2-1325: performance optimization to improve preference retrieval speed + // To go back to old behavior, set jetspeed/override.properties. + // Default is enabled + // preferences.session.cache.enabled = true + // since 2.3.0 + private boolean enableSessionCache = true; - public boolean isUseEntityPreferences() { return useEntityPreferences; @@ -101,7 +114,7 @@ public class PortletPreferencesServiceIm this.portletFactory = portletFactory; this.preferenceCache = preferenceCache; } - + public PortletPreferencesServiceImpl(PortletFactory portletFactory, JetspeedCache preferenceCache, List<String> apps, boolean preloadEntities) throws ClassNotFoundException { @@ -109,9 +122,21 @@ public class PortletPreferencesServiceIm this.preloadedApplications = apps; this.preloadEntities = preloadEntities; } - + public void init() { + try { + configuration = Jetspeed.getComponentManager().lookupComponent("PortalConfiguration"); + } + catch (Exception e) { + configuration = null; // not set in some unit tests + } + if (configuration != null) { + enableSessionCache = configuration.getBoolean(PortalConfigurationConstants.ENABLED_PREFERENCES_SESSION_CACHE); + } + else { + enableSessionCache = false; + } } public void destroy() @@ -179,7 +204,10 @@ public class PortletPreferencesServiceIm { userName = SubjectHelper.getPrincipal(window.getRequestContext().getSubject(), User.class).getName(); } - return retrieveUserPreferences(window, userName); + // JS2-1325: since 2.3.0 + return (enableSessionCache) ? + retrieveUserSessionWindowPreferences(window, userName) : + retrieveUserPreferences(window, userName); } /** @@ -353,10 +381,18 @@ public class PortletPreferencesServiceIm } } getPersistenceBrokerTemplate().store(dbPref); - } - // remove from cache to send distributed notification - String cacheKey = getUserPreferenceKey(appName, portletName, entityId, userName); - preferenceCache.remove(cacheKey); + } + if (enableSessionCache) { + UserSessionPreferences sessionPreferences = getUserSessionPreferences(); + if (sessionPreferences != null) { + sessionPreferences.updateWindowPreferences(window.getPortletEntityId(), map); + } + } + else { + // remove from cache to send distributed notification + String cacheKey = getUserPreferenceKey(appName, portletName, entityId, userName); + preferenceCache.remove(cacheKey); + } } catch (Throwable t) { @@ -882,4 +918,74 @@ public class PortletPreferencesServiceIm preferenceCache.remove(cacheKey); } + protected UserSessionPreferences retrieveUserSessionPreferences(String userName) { + RequestContext rc = null; + RequestContextComponent rcc = getRequestContextComponent(); + if (rcc != null) { + rc = rcc.getRequestContext(); + if (rc != null) { + UserSessionPreferences userPreferences = (UserSessionPreferences) rc.getSessionAttribute(SESSION_CACHE_KEY); + if (userPreferences != null) { + // return cached values + return userPreferences; + } + } + } + UserSessionPreferences sessionPreferences = new UserSessionPreferences(); + // not found in cache, query database + Criteria c = new Criteria(); + c.addEqualTo(DTYPE, DISCRIMINATOR_USER); + c.addEqualTo(USER_NAME, userName); + //query.addOrderByAscending(DTYPE); + QueryByCriteria query = QueryFactory.newQuery(DatabasePreference.class, c); + Iterator<DatabasePreference> preferences = getPersistenceBrokerTemplate().getIteratorByQuery(query); + while (preferences.hasNext()) + { + DatabasePreference preference = preferences.next(); + Map<String,PortletPreference> windowPreferences = sessionPreferences.getWindowPreferences(preference.getEntityId()); + if (windowPreferences == null) { + windowPreferences = sessionPreferences.createWindowPreferences(preference.getEntityId()); + } + windowPreferences.put(preference.getName(), new JetspeedPreferenceImpl(preference.getName(), preference.getValues(), preference.isReadOnly())); + } + if (rc != null) { + rc.setSessionAttribute(SESSION_CACHE_KEY, sessionPreferences); + } + return sessionPreferences; + } + + protected Map<String,PortletPreference> retrieveUserSessionWindowPreferences(PortletWindow window, String userName) + { + UserSessionPreferences sessionPreferences = retrieveUserSessionPreferences(userName); + Map<String,PortletPreference> result = sessionPreferences.getWindowPreferences(window.getPortletEntityId()); + if (result == null) { + result = sessionPreferences.createWindowPreferences(window.getPortletEntityId()); + } + return result; + } + + protected UserSessionPreferences getUserSessionPreferences() { + UserSessionPreferences sessionPreferences = null; + RequestContextComponent rcc = getRequestContextComponent(); + if (rcc != null) { + RequestContext rc = rcc.getRequestContext(); + if (rc != null) { + sessionPreferences = (UserSessionPreferences) rc.getSessionAttribute(SESSION_CACHE_KEY); + if (sessionPreferences == null) { + sessionPreferences = new UserSessionPreferences(); + rc.setSessionAttribute(SESSION_CACHE_KEY, sessionPreferences); + } + return sessionPreferences; + } + } + return new UserSessionPreferences(); + } + + protected RequestContextComponent getRequestContextComponent() { + if (requestContextComponent == null) { + requestContextComponent = Jetspeed.getComponentManager().lookupComponent("org.apache.jetspeed.request.RequestContextComponent"); + } + return requestContextComponent; + } + } Added: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletpreferences/UserSessionPreferences.java URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletpreferences/UserSessionPreferences.java?rev=1681669&view=auto ============================================================================== --- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletpreferences/UserSessionPreferences.java (added) +++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletpreferences/UserSessionPreferences.java Tue May 26 01:20:23 2015 @@ -0,0 +1,53 @@ +/* + * 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.jetspeed.components.portletpreferences; + +import org.apache.pluto.container.PortletPreference; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Created by dtaylor on 5/25/15. + */ +public class UserSessionPreferences { + + /** + * Portlet container requests preferences by window id. Portlet windows can hold 0..n preferences. + * This map is keyed on window id an associated to the user by putting it in the user session. + * Individual preferences are keyed by preference name each mapping to a portlet preference + */ + private Map<String,Map<String,PortletPreference>> windowPreferences = new ConcurrentHashMap<>(); + + public Map<String,PortletPreference> getWindowPreferences(String portletWindowId) { + return windowPreferences.get(portletWindowId); + } + + public Map<String,PortletPreference> createWindowPreferences(String portletWindowId) { + Map<String,PortletPreference> preferences = new HashMap<>(); + windowPreferences.put(portletWindowId, preferences); + return preferences; + } + + public Map<String,PortletPreference> updateWindowPreferences(String portletWindowId, Map<String,PortletPreference> preferences) { + windowPreferences.put(portletWindowId, preferences); + return preferences; + } + + +} --------------------------------------------------------------------- To unsubscribe, e-mail: jetspeed-dev-unsubscr...@portals.apache.org For additional commands, e-mail: jetspeed-dev-h...@portals.apache.org