From e1fb8ada8976cf3eed2bc1d5d711d1adf1e1fe2d Mon Sep 17 00:00:00 2001 From: Sergey Rymsha Date: Wed, 23 Oct 2019 16:37:50 +0200 Subject: [PATCH] Distributed Session Management #7529 --- .../xp/ignite/impl/IgniteActivator.java | 91 +++++++++++++++++++ .../enonic/xp/ignite/impl/IgniteCluster.java | 65 ++----------- .../xp/jaxrs/impl/JaxRsServiceImpl.java | 5 +- .../pipeline/ResourcePipelineImpl.java | 7 +- .../xp/web/jetty/impl/JettyActivator.java | 91 +++++++++++++------ .../xp/web/jetty/impl/JettyService.java | 50 ++++------ .../impl/JettySessionStorageFactories.java | 13 +++ .../JettySessionStorageFactoriesImpl.java | 66 ++++++++++++++ .../jetty/impl/XpServletContextProvider.java | 8 ++ .../impl/XpServletContextProviderImpl.java | 19 ++++ .../impl/websocket/WebSocketServiceImpl.java | 23 +---- .../websocket/WebSocketServiceImplTest.java | 10 +- .../SessionDataStoreFactoryActivator.java | 17 ++-- 13 files changed, 312 insertions(+), 153 deletions(-) create mode 100644 modules/core/core-ignite/src/main/java/com/enonic/xp/ignite/impl/IgniteActivator.java create mode 100644 modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/JettySessionStorageFactories.java create mode 100644 modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/JettySessionStorageFactoriesImpl.java create mode 100644 modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/XpServletContextProvider.java create mode 100644 modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/XpServletContextProviderImpl.java diff --git a/modules/core/core-ignite/src/main/java/com/enonic/xp/ignite/impl/IgniteActivator.java b/modules/core/core-ignite/src/main/java/com/enonic/xp/ignite/impl/IgniteActivator.java new file mode 100644 index 00000000000..1efe044f1a7 --- /dev/null +++ b/modules/core/core-ignite/src/main/java/com/enonic/xp/ignite/impl/IgniteActivator.java @@ -0,0 +1,91 @@ +package com.enonic.xp.ignite.impl; + +import java.util.Hashtable; + +import org.apache.ignite.Ignite; +import org.apache.ignite.Ignition; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Deactivate; +import org.osgi.service.component.annotations.Reference; + +import com.enonic.xp.cluster.ClusterConfig; +import com.enonic.xp.ignite.impl.config.ConfigurationFactory; +import com.enonic.xp.ignite.impl.config.IgniteSettings; + +import static org.apache.ignite.IgniteSystemProperties.IGNITE_NO_ASCII; +import static org.apache.ignite.IgniteSystemProperties.IGNITE_NO_SHUTDOWN_HOOK; +import static org.apache.ignite.IgniteSystemProperties.IGNITE_PERFORMANCE_SUGGESTIONS_DISABLED; +import static org.apache.ignite.IgniteSystemProperties.IGNITE_TROUBLESHOOTING_LOGGER; +import static org.apache.ignite.IgniteSystemProperties.IGNITE_UPDATE_NOTIFIER; + +@Component(immediate = true, configurationPid = "com.enonic.xp.ignite") +public class IgniteActivator +{ + private Ignite ignite; + + private ClusterConfig clusterConfig; + + private ServiceRegistration igniteReg; + + @SuppressWarnings("unused") + @Activate + public void activate( final BundleContext context, final IgniteSettings igniteSettings ) + { + if ( clusterConfig.isEnabled() ) + { + adjustLoggingVerbosity(); + + final IgniteConfiguration igniteConfig = ConfigurationFactory.create(). + clusterConfig( clusterConfig ). + igniteConfig( igniteSettings ). + bundleContext( context ). + build(). + execute(); + + System.setProperty( IGNITE_NO_SHUTDOWN_HOOK, "true" ); + + final Thread thread = Thread.currentThread(); + final ClassLoader classLoader = thread.getContextClassLoader(); + try + { + thread.setContextClassLoader( Ignite.class.getClassLoader() ); + ignite = Ignition.start( igniteConfig ); + } + finally + { + thread.setContextClassLoader( classLoader ); + } + igniteReg = context.registerService( Ignite.class, ignite, new Hashtable<>() ); + } + } + + @SuppressWarnings("unused") + @Deactivate + public void deactivate() + { + if ( ignite != null ) + { + igniteReg.unregister(); + ignite.close(); + } + } + + @SuppressWarnings("unused") + @Reference + public void setClusterConfig( final ClusterConfig clusterConfig ) + { + this.clusterConfig = clusterConfig; + } + + private static void adjustLoggingVerbosity() + { + System.setProperty( IGNITE_NO_ASCII, "false" ); + System.setProperty( IGNITE_PERFORMANCE_SUGGESTIONS_DISABLED, "true" ); + System.setProperty( IGNITE_UPDATE_NOTIFIER, "false" ); + System.setProperty( IGNITE_TROUBLESHOOTING_LOGGER, "false" ); + } +} diff --git a/modules/core/core-ignite/src/main/java/com/enonic/xp/ignite/impl/IgniteCluster.java b/modules/core/core-ignite/src/main/java/com/enonic/xp/ignite/impl/IgniteCluster.java index 3715eafa4d7..24bde971c90 100644 --- a/modules/core/core-ignite/src/main/java/com/enonic/xp/ignite/impl/IgniteCluster.java +++ b/modules/core/core-ignite/src/main/java/com/enonic/xp/ignite/impl/IgniteCluster.java @@ -3,8 +3,6 @@ import java.util.Hashtable; import org.apache.ignite.Ignite; -import org.apache.ignite.Ignition; -import org.apache.ignite.configuration.IgniteConfiguration; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import org.osgi.service.component.annotations.Activate; @@ -15,73 +13,34 @@ import org.slf4j.LoggerFactory; import com.enonic.xp.cluster.Cluster; -import com.enonic.xp.cluster.ClusterConfig; import com.enonic.xp.cluster.ClusterHealth; import com.enonic.xp.cluster.ClusterId; import com.enonic.xp.cluster.ClusterNode; import com.enonic.xp.cluster.ClusterNodes; -import com.enonic.xp.ignite.impl.config.ConfigurationFactory; -import com.enonic.xp.ignite.impl.config.IgniteSettings; -import static org.apache.ignite.IgniteSystemProperties.IGNITE_NO_ASCII; -import static org.apache.ignite.IgniteSystemProperties.IGNITE_NO_SHUTDOWN_HOOK; -import static org.apache.ignite.IgniteSystemProperties.IGNITE_PERFORMANCE_SUGGESTIONS_DISABLED; -import static org.apache.ignite.IgniteSystemProperties.IGNITE_TROUBLESHOOTING_LOGGER; -import static org.apache.ignite.IgniteSystemProperties.IGNITE_UPDATE_NOTIFIER; - -@Component(immediate = true, configurationPid = "com.enonic.xp.ignite") +@Component(immediate = true) public class IgniteCluster implements Cluster { private static final Logger LOG = LoggerFactory.getLogger( IgniteCluster.class ); - private Ignite ignite; - - private ServiceRegistration igniteReg; - private ServiceRegistration igniteAdminClientReg; - private ClusterConfig clusterConfig; + private Ignite ignite; @SuppressWarnings("unused") @Activate - public void activate( final BundleContext context, final IgniteSettings igniteSettings ) + public void activate( final BundleContext context ) { - adjustLoggingVerbosity(); - - final IgniteConfiguration igniteConfig = ConfigurationFactory.create(). - clusterConfig( clusterConfig ). - igniteConfig( igniteSettings ). - bundleContext( context ). - build(). - execute(); - - System.setProperty( IGNITE_NO_SHUTDOWN_HOOK, "true" ); - - final Thread thread = Thread.currentThread(); - final ClassLoader classLoader = thread.getContextClassLoader(); - try - { - thread.setContextClassLoader( Ignite.class.getClassLoader() ); - ignite = Ignition.start( igniteConfig ); - } - finally - { - thread.setContextClassLoader( classLoader ); - } - igniteReg = context.registerService( Ignite.class, ignite, new Hashtable<>() ); // Register admin-client to use in e.g reporting - igniteAdminClientReg = - context.registerService( IgniteAdminClient.class, new IgniteAdminClientImpl( this.ignite ), new Hashtable<>() ); + igniteAdminClientReg = context.registerService( IgniteAdminClient.class, new IgniteAdminClientImpl( ignite ), new Hashtable<>() ); } @SuppressWarnings("unused") @Deactivate public void deactivate() { - igniteReg.unregister(); igniteAdminClientReg.unregister(); - ignite.close(); } @Override @@ -126,13 +85,13 @@ private ClusterNodes doGetNodes() @Override public void enable() { - // Ignore. Ignite Cluster should be always enabled + // Ignore. Ignite Cluster should be always enabled if Ignite exists } @Override public void disable() { - // Ignore. Ignite Cluster should be always enabled + // Ignore. Ignite Cluster should be always enabled if Ignite exists } @Override @@ -143,16 +102,8 @@ public boolean isEnabled() @SuppressWarnings("unused") @Reference - public void setClusterConfig( final ClusterConfig clusterConfig ) - { - this.clusterConfig = clusterConfig; - } - - private static void adjustLoggingVerbosity() + public void setIgnite( final Ignite ignite ) { - System.setProperty( IGNITE_NO_ASCII, "false" ); - System.setProperty( IGNITE_PERFORMANCE_SUGGESTIONS_DISABLED, "true" ); - System.setProperty( IGNITE_UPDATE_NOTIFIER, "false" ); - System.setProperty( IGNITE_TROUBLESHOOTING_LOGGER, "false" ); + this.ignite = ignite; } } diff --git a/modules/jaxrs/jaxrs-impl/src/main/java/com/enonic/xp/jaxrs/impl/JaxRsServiceImpl.java b/modules/jaxrs/jaxrs-impl/src/main/java/com/enonic/xp/jaxrs/impl/JaxRsServiceImpl.java index 153450f64c7..3164f964ab1 100644 --- a/modules/jaxrs/jaxrs-impl/src/main/java/com/enonic/xp/jaxrs/impl/JaxRsServiceImpl.java +++ b/modules/jaxrs/jaxrs-impl/src/main/java/com/enonic/xp/jaxrs/impl/JaxRsServiceImpl.java @@ -90,7 +90,10 @@ public JaxRsComponent addingService( final ServiceReference refe } final JaxRsComponent component = this.context.getService( reference ); - add( component ); + if ( component != null ) + { + add( component ); + } return component; } diff --git a/modules/web/web-dispatch/src/main/java/com/enonic/xp/web/impl/dispatch/pipeline/ResourcePipelineImpl.java b/modules/web/web-dispatch/src/main/java/com/enonic/xp/web/impl/dispatch/pipeline/ResourcePipelineImpl.java index 4766c6589fc..283086caf8b 100644 --- a/modules/web/web-dispatch/src/main/java/com/enonic/xp/web/impl/dispatch/pipeline/ResourcePipelineImpl.java +++ b/modules/web/web-dispatch/src/main/java/com/enonic/xp/web/impl/dispatch/pipeline/ResourcePipelineImpl.java @@ -5,14 +5,13 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.CopyOnWriteArrayList; import javax.servlet.ServletContext; import javax.servlet.ServletException; import org.osgi.framework.ServiceReference; -import com.google.common.collect.Lists; - import com.enonic.xp.web.dispatch.DispatchConstants; import com.enonic.xp.web.impl.dispatch.mapping.ResourceDefinition; @@ -32,8 +31,8 @@ public abstract class ResourcePipelineImpl> ResourcePipelineImpl() { this.map = new HashMap<>(); - this.list = Lists.newCopyOnWriteArrayList(); - this.resourceQueue = Lists.newCopyOnWriteArrayList(); + this.list = new CopyOnWriteArrayList<>(); + this.resourceQueue = new CopyOnWriteArrayList<>(); } @Override diff --git a/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/JettyActivator.java b/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/JettyActivator.java index 99d6c453473..241dd12cc26 100644 --- a/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/JettyActivator.java +++ b/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/JettyActivator.java @@ -1,15 +1,18 @@ package com.enonic.xp.web.jetty.impl; -import java.util.ArrayList; +import java.util.Collections; import java.util.Dictionary; import java.util.Hashtable; +import java.util.IdentityHashMap; import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.stream.Collectors; import javax.servlet.ServletContext; -import org.eclipse.jetty.server.session.SessionCacheFactory; -import org.eclipse.jetty.server.session.SessionDataStoreFactory; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.servlet.ServletContextHandler; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; @@ -18,9 +21,10 @@ import org.osgi.service.component.annotations.Deactivate; import org.osgi.service.component.annotations.Reference; import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; -import com.enonic.xp.cluster.ClusterConfig; import com.enonic.xp.status.StatusReporter; +import com.enonic.xp.web.dispatch.DispatchConstants; import com.enonic.xp.web.dispatch.DispatchServlet; import com.enonic.xp.web.thread.ThreadPoolInfo; @@ -36,37 +40,64 @@ public final class JettyActivator private ServiceRegistration statusReporterReg; - private List dispatchServlets = new ArrayList<>(); + private ServiceRegistration xpServletContextReg; - private ClusterConfig clusterConfig; + private final Map dispatchServlets = Collections.synchronizedMap( new IdentityHashMap<>() ); - private SessionDataStoreFactory sessionDataStoreFactory; + private JettySessionStorageFactories jettySessionStorageFactories; - private SessionCacheFactory sessionCacheFactory; + private final ContextHandlerCollection contexts = new ContextHandlerCollection(); + + private final List unprovisionedDispatchServlets = new CopyOnWriteArrayList<>(); + + private volatile JettyConfig config; @Activate public void activate( final BundleContext context, final JettyConfig config ) - throws Exception { + this.config = config; this.context = context; fixJettyVersion(); - this.service = - new JettyService( clusterConfig.name().toString(), sessionDataStoreFactory, sessionCacheFactory, dispatchServlets, config ); + for ( DispatchServlet dispatchServlet : unprovisionedDispatchServlets ) + { + Handler handler = JettyService.initServletContextHandler( dispatchServlet, config ); + contexts.addHandler( handler ); + dispatchServlets.put( dispatchServlet, handler ); + } + unprovisionedDispatchServlets.clear(); + + this.service = new JettyService( jettySessionStorageFactories, contexts, config ); this.service.start(); publishController(); publishStatusReporter(); publishThreadPoolInfo(); + publishXpServletContext(); + } + + private void publishXpServletContext() + { + ServletContext xpServletContext = + this.service.handlers().stream().map( handler -> (ServletContext) ( (ServletContextHandler) handler ).getServletContext() ). + filter( servletContext -> servletContext.getVirtualServerName(). + equals( DispatchConstants.VIRTUAL_HOST_PREFIX + DispatchConstants.XP_CONNECTOR ) ). + findAny().orElse( null ); + + xpServletContextReg = context.registerService( XpServletContextProvider.class, new XpServletContextProviderImpl( xpServletContext ), + new Hashtable<>() ); } @Deactivate public void deactivate() - throws Exception { this.controllerReg.unregister(); this.statusReporterReg.unregister(); + if ( xpServletContextReg != null ) + { + xpServletContextReg.unregister(); + } this.service.stop(); } @@ -109,32 +140,34 @@ private void publishThreadPoolInfo() this.statusReporterReg = this.context.registerService( ThreadPoolInfo.class, threadPoolInfo, new Hashtable<>() ); } - @Reference(cardinality = ReferenceCardinality.AT_LEAST_ONE) + @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC) public void addDispatchServlet( final DispatchServlet dispatchServlet ) { - this.dispatchServlets.add( dispatchServlet ); + if ( config != null ) + { + Handler handler = JettyService.initServletContextHandler( dispatchServlet, config ); + dispatchServlets.put( dispatchServlet, handler ); + contexts.addHandler( handler ); + } + else + { + unprovisionedDispatchServlets.add( dispatchServlet ); + } } public void removeDispatchServlet( final DispatchServlet dispatchServlet ) { - this.dispatchServlets.remove( dispatchServlet ); - } - - @Reference - public void setClusterConfig( final ClusterConfig clusterConfig ) - { - this.clusterConfig = clusterConfig; - } - - @Reference - public void setSessionDataStoreFactory( final SessionDataStoreFactory sessionDataStoreFactory ) - { - this.sessionDataStoreFactory = sessionDataStoreFactory; + Handler handler = dispatchServlets.remove( dispatchServlet ); + unprovisionedDispatchServlets.remove( dispatchServlet ); + if ( handler != null ) + { + contexts.removeHandler( handler ); + } } @Reference - public void setSessionCacheFactory( final SessionCacheFactory sessionCacheFactory ) + public void setJettySessionStorageFactories( final JettySessionStorageFactories jettySessionStorageFactories ) { - this.sessionCacheFactory = sessionCacheFactory; + this.jettySessionStorageFactories = jettySessionStorageFactories; } } diff --git a/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/JettyService.java b/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/JettyService.java index f5d4700ceeb..ec3bc3de0a1 100644 --- a/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/JettyService.java +++ b/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/JettyService.java @@ -6,8 +6,6 @@ import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.session.DefaultSessionIdManager; -import org.eclipse.jetty.server.session.SessionCacheFactory; -import org.eclipse.jetty.server.session.SessionDataStoreFactory; import org.eclipse.jetty.server.session.SessionHandler; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; @@ -30,27 +28,18 @@ final class JettyService private final JettyConfig config; - private final List dispatcherServlets; - private final SessionDataStoreFactory sessionDataStoreFactory; - - private final SessionCacheFactory sessionCacheFactory; - - - private final String workerName; + private final JettySessionStorageFactories jettySessionStorageFactories; private Server server; private ContextHandlerCollection contexts; - public JettyService( final String workerName, final SessionDataStoreFactory sessionDataStoreFactory, - final SessionCacheFactory sessionCacheFactory, final List dispatcherServlets, + public JettyService( final JettySessionStorageFactories jettySessionStorageFactories, final ContextHandlerCollection contexts, final JettyConfig config ) { - this.workerName = workerName; - this.sessionDataStoreFactory = sessionDataStoreFactory; - this.sessionCacheFactory = sessionCacheFactory; - this.dispatcherServlets = List.copyOf( dispatcherServlets ); + this.contexts = contexts; + this.jettySessionStorageFactories = jettySessionStorageFactories; this.config = config; } @@ -96,7 +85,8 @@ boolean httpEnabled() List handlers() { - return List.of( contexts.getHandlers() ); + Handler[] handlers = contexts.getHandlers(); + return handlers == null ? List.of() : List.of( handlers ); } private void startJetty() @@ -104,11 +94,6 @@ private void startJetty() { this.server = new Server(); - this.contexts = new ContextHandlerCollection(); - - this.dispatcherServlets.stream(). - map( this::initServletContextHandler ). - forEach( contexts::addHandler ); new HttpConfigurator().configure( this.config, this.server ); @@ -116,16 +101,17 @@ private void startJetty() final InstrumentedHandler instrumentedHandler = new InstrumentedHandler( Metrics.registry(), Handler.class.getName() ); instrumentedHandler.setHandler( contexts ); - if ( sessionDataStoreFactory != null ) - { - this.server.addBean( sessionDataStoreFactory ); - this.server.addBean( sessionCacheFactory ); - } - this.server.setHandler( contexts ); final DefaultSessionIdManager sessionManager = new DefaultSessionIdManager( this.server ); - sessionManager.setWorkerName( this.workerName ); + + if ( jettySessionStorageFactories != null ) + { + this.server.addBean( jettySessionStorageFactories.getSessionDataStoreFactory() ); + this.server.addBean( jettySessionStorageFactories.getSessionCacheFactory() ); + sessionManager.setWorkerName( jettySessionStorageFactories.getWorkerName() ); + } + this.server.setSessionIdManager( sessionManager ); this.server.start(); @@ -134,7 +120,7 @@ private void startJetty() config.http_management_port(), config.http_monitor_port() ); } - private ServletContextHandler initServletContextHandler( final DispatchServlet servlet ) + public static ServletContextHandler initServletContextHandler( final DispatchServlet servlet, JettyConfig config ) { final ServletContextHandler context = new ServletContextHandler( null, "/", ServletContextHandler.SESSIONS ); final SessionHandler sessionHandler = context.getSessionHandler(); @@ -144,9 +130,9 @@ private ServletContextHandler initServletContextHandler( final DispatchServlet s context.addServlet( holder, "/*" ); context.setVirtualHosts( new String[]{DispatchConstants.VIRTUAL_HOST_PREFIX + servlet.getConnector()} ); - new SessionConfigurator().configure( this.config, sessionHandler ); - new GZipConfigurator().configure( this.config, context ); - new MultipartConfigurator().configure( this.config, holder ); + new SessionConfigurator().configure( config, sessionHandler ); + new GZipConfigurator().configure( config, context ); + new MultipartConfigurator().configure( config, holder ); return context; } diff --git a/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/JettySessionStorageFactories.java b/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/JettySessionStorageFactories.java new file mode 100644 index 00000000000..cb31b54c57b --- /dev/null +++ b/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/JettySessionStorageFactories.java @@ -0,0 +1,13 @@ +package com.enonic.xp.web.jetty.impl; + +import org.eclipse.jetty.server.session.SessionCacheFactory; +import org.eclipse.jetty.server.session.SessionDataStoreFactory; + +public interface JettySessionStorageFactories +{ + String getWorkerName(); + + SessionDataStoreFactory getSessionDataStoreFactory(); + + SessionCacheFactory getSessionCacheFactory(); +} diff --git a/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/JettySessionStorageFactoriesImpl.java b/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/JettySessionStorageFactoriesImpl.java new file mode 100644 index 00000000000..f488364fd9c --- /dev/null +++ b/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/JettySessionStorageFactoriesImpl.java @@ -0,0 +1,66 @@ +package com.enonic.xp.web.jetty.impl; + +import org.eclipse.jetty.server.session.SessionCacheFactory; +import org.eclipse.jetty.server.session.SessionDataStoreFactory; +import org.osgi.framework.BundleContext; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +import com.enonic.xp.cluster.ClusterConfig; + +@Component(immediate = true) +public class JettySessionStorageFactoriesImpl + implements JettySessionStorageFactories +{ + private String workerName; + + private SessionDataStoreFactory sessionDataStoreFactory; + + private SessionCacheFactory sessionCacheFactory; + + private ClusterConfig clusterConfig; + + @Override + public String getWorkerName() + { + return workerName; + } + + @Override + public SessionDataStoreFactory getSessionDataStoreFactory() + { + return sessionDataStoreFactory; + } + + @Override + public SessionCacheFactory getSessionCacheFactory() + { + return sessionCacheFactory; + } + + @Activate + public void activate( final BundleContext context ) + { + workerName = clusterConfig.name().toString(); + } + + @Reference + public void setSessionDataStoreFactory( final SessionDataStoreFactory sessionDataStoreFactory ) + { + this.sessionDataStoreFactory = sessionDataStoreFactory; + } + + @Reference + public void setSessionCacheFactory( final SessionCacheFactory sessionCacheFactory ) + { + this.sessionCacheFactory = sessionCacheFactory; + } + + @Reference + public void setClusterConfig( final ClusterConfig clusterConfig ) + { + this.clusterConfig = clusterConfig; + } + +} diff --git a/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/XpServletContextProvider.java b/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/XpServletContextProvider.java new file mode 100644 index 00000000000..dbd117f7d42 --- /dev/null +++ b/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/XpServletContextProvider.java @@ -0,0 +1,8 @@ +package com.enonic.xp.web.jetty.impl; + +import javax.servlet.ServletContext; + +public interface XpServletContextProvider +{ + ServletContext get(); +} diff --git a/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/XpServletContextProviderImpl.java b/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/XpServletContextProviderImpl.java new file mode 100644 index 00000000000..5f32348145d --- /dev/null +++ b/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/XpServletContextProviderImpl.java @@ -0,0 +1,19 @@ +package com.enonic.xp.web.jetty.impl; + +import javax.servlet.ServletContext; + +public class XpServletContextProviderImpl + implements XpServletContextProvider +{ + private final ServletContext servletContext; + + public XpServletContextProviderImpl( final ServletContext servletContext ) + { + this.servletContext = servletContext; + } + + public ServletContext get() + { + return servletContext; + } +} diff --git a/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/websocket/WebSocketServiceImpl.java b/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/websocket/WebSocketServiceImpl.java index 09229d02496..8f1d537d0cb 100644 --- a/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/websocket/WebSocketServiceImpl.java +++ b/modules/web/web-jetty/src/main/java/com/enonic/xp/web/jetty/impl/websocket/WebSocketServiceImpl.java @@ -2,9 +2,7 @@ import java.io.IOException; import java.util.List; -import java.util.Optional; -import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -28,8 +26,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.enonic.xp.web.dispatch.DispatchConstants; -import com.enonic.xp.web.jetty.impl.JettyController; +import com.enonic.xp.web.jetty.impl.XpServletContextProvider; import com.enonic.xp.web.websocket.EndpointFactory; import com.enonic.xp.web.websocket.WebSocketService; @@ -37,7 +34,7 @@ public final class WebSocketServiceImpl implements WebSocketService { - private JettyController controller; + private XpServletContextProvider xpServletContextProvider; private WebSocketServerFactory serverFactory; @@ -50,17 +47,7 @@ public void activate() { final WebSocketPolicy policy = WebSocketPolicy.newServerPolicy(); - final Optional xpServletContext = this.controller.getServletContexts().stream(). - filter( servletContext -> ( DispatchConstants.VIRTUAL_HOST_PREFIX + DispatchConstants.XP_CONNECTOR ).equals( - servletContext.getVirtualServerName() ) ). - findFirst(); - - if ( xpServletContext.isEmpty() ) - { - throw new ServletException( "Servlet context not found: " + DispatchConstants.XP_CONNECTOR ); - } - - this.serverFactory = new WebSocketServerFactory( xpServletContext.get(), policy ); + this.serverFactory = new WebSocketServerFactory( xpServletContextProvider.get(), policy ); final ServerContainerImpl serverContainer = new ServerContainerImpl( this.serverFactory ); try @@ -106,9 +93,9 @@ public boolean acceptWebSocket( final HttpServletRequest req, final HttpServletR } @Reference - public void setController( final JettyController controller ) + public void setXpServletContextProvider( final XpServletContextProvider xpServletContextProvider ) { - this.controller = controller; + this.xpServletContextProvider = xpServletContextProvider; } private WebSocketCreator newCreator( final EndpointFactory factory ) diff --git a/modules/web/web-jetty/src/test/java/com/enonic/xp/web/jetty/impl/websocket/WebSocketServiceImplTest.java b/modules/web/web-jetty/src/test/java/com/enonic/xp/web/jetty/impl/websocket/WebSocketServiceImplTest.java index 0fd854e5246..a58fa3f5074 100644 --- a/modules/web/web-jetty/src/test/java/com/enonic/xp/web/jetty/impl/websocket/WebSocketServiceImplTest.java +++ b/modules/web/web-jetty/src/test/java/com/enonic/xp/web/jetty/impl/websocket/WebSocketServiceImplTest.java @@ -1,7 +1,5 @@ package com.enonic.xp.web.jetty.impl.websocket; -import java.util.List; - import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -13,8 +11,8 @@ import com.squareup.okhttp.ws.WebSocketListener; import com.enonic.xp.web.dispatch.DispatchConstants; -import com.enonic.xp.web.jetty.impl.JettyController; import com.enonic.xp.web.jetty.impl.JettyTestSupport; +import com.enonic.xp.web.jetty.impl.XpServletContextProvider; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -37,13 +35,13 @@ protected void configure() { this.endpoint = new TestEndpoint(); - final JettyController controller = Mockito.mock( JettyController.class ); + final XpServletContextProvider provider = Mockito.mock( XpServletContextProvider.class ); this.server.setVirtualHosts( new String[]{DispatchConstants.VIRTUAL_HOST_PREFIX + DispatchConstants.XP_CONNECTOR} ); - Mockito.when( controller.getServletContexts() ).thenReturn( List.of( this.server.getHandler().getServletContext() ) ); + Mockito.when( provider.get() ).thenReturn( this.server.getHandler().getServletContext() ); this.service = new WebSocketServiceImpl(); - this.service.setController( controller ); + this.service.setXpServletContextProvider( provider ); this.service.activate(); this.servlet = new TestWebSocketServlet(); diff --git a/modules/web/web-session/src/main/java/com/enonic/xp/web/session/impl/SessionDataStoreFactoryActivator.java b/modules/web/web-session/src/main/java/com/enonic/xp/web/session/impl/SessionDataStoreFactoryActivator.java index 460c3397859..32c909736a4 100644 --- a/modules/web/web-session/src/main/java/com/enonic/xp/web/session/impl/SessionDataStoreFactoryActivator.java +++ b/modules/web/web-session/src/main/java/com/enonic/xp/web/session/impl/SessionDataStoreFactoryActivator.java @@ -15,6 +15,7 @@ import org.osgi.service.component.annotations.Deactivate; import org.osgi.service.component.annotations.Reference; import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicyOption; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,7 +42,7 @@ public void activate( final BundleContext context, final WebSessionConfig config { if ( ignite == null ) { - LOG.debug( "Waiting for ignite" ); + LOG.debug( "Waiting for Ignite" ); } else { @@ -69,14 +70,18 @@ public void activate( final BundleContext context, final WebSessionConfig config @Deactivate public void deactivate() - throws Exception { - ignite = null; - sessionDataStoreFactoryReg.unregister(); - sessionCacheReg.unregister(); + if ( sessionDataStoreFactoryReg != null ) + { + sessionDataStoreFactoryReg.unregister(); + } + if ( sessionCacheReg != null ) + { + sessionCacheReg.unregister(); + } } - @Reference(cardinality = ReferenceCardinality.OPTIONAL) + @Reference(cardinality = ReferenceCardinality.OPTIONAL, policyOption = ReferencePolicyOption.GREEDY) public void setIgnite( final Ignite ignite ) { this.ignite = ignite;