All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ratpack.session.SessionModule Maven / Gradle / Ivy

There is a newer version: 2.0.0-rc-1
Show newest version
/*
 * Copyright 2015 the original author or authors.
 *
 * Licensed 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 ratpack.session;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalListener;
import com.google.inject.*;
import com.google.inject.name.Names;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.util.AsciiString;
import ratpack.func.Action;
import ratpack.guice.BindingsSpec;
import ratpack.guice.ConfigurableModule;
import ratpack.guice.RequestScoped;
import ratpack.http.Request;
import ratpack.http.Response;
import ratpack.session.internal.*;
import ratpack.util.Types;

import javax.inject.Named;
import java.io.Serializable;
import java.util.function.Consumer;

/**
 * Provides support for HTTP sessions.
 * 

* This module provides the general session API (see {@link Session}), and a default {@link SessionStore} implementation that stores session data in local memory. * *

The session store

*

* It is expected that most applications will provide alternative bindings for the {@link SessionStore} type, overriding the default. * This allows arbitrary stores to be used to persist session data. *

* The default, in memory, implementation stores the data in a {@link Cache}{@code <}{@link AsciiString}, {@link ByteBuf}{@code >}. * This cache instance is provided by this module and defaults to storing a maximum of 1000 entries, discarding least recently used. * The {@link #memoryStore} methods are provided to conveniently construct alternative cache configurations, if necessary. *

Serialization

*

* Objects must be serialized to be stored in the session. * The get/set methods {@link SessionData} allow supplying a {@link SessionSerializer} to be used for the specific value. * For variants of the get/set methods where a serializer is not provided, the implementation of {@link SessionSerializer} bound with Guice will be used. * The default implementation provided by this module uses Java's in built serialization mechanism. * Users of this module may choose to override this binding with an alternative serialization strategy. *

* However, other Ratpack extensions may require session storage any rely on Java serialization. * For this reason, there is also always a {@link JavaSessionSerializer} implementation available that is guaranteed to be able to serialize any {@link Serializable} * object (that conforms to the {@link Serializable} contract. * Users of this module may also choose to override this binding with another implementation (e.g. one based on Kryo), * but this implementation must be able to serialize any object implementing {@link Serializable}. * * It is also often desirable to provide alternative implementations for {@link SessionSerializer} and {@link JavaSessionSerializer}. * The default binding for both types is an implementation that uses out-of-the-box Java serialization (which is neither fast nor efficient). * *

Example usage

*
{@code
 * import ratpack.guice.Guice;
 * import ratpack.path.PathTokens;
 * import ratpack.session.Session;
 * import ratpack.session.SessionModule;
 * import ratpack.test.embed.EmbeddedApp;
 *
 * import static org.junit.Assert.assertEquals;
 *
 * public class Example {
 *   public static void main(String... args) throws Exception {
 *     EmbeddedApp.of(a -> a
 *         .registry(Guice.registry(b -> b
 *             .module(SessionModule.class)
 *         ))
 *         .handlers(c -> c
 *             .get("set/:name/:value", ctx ->
 *                 ctx.get(Session.class).getData().then(sessionData -> {
 *                   PathTokens pathTokens = ctx.getPathTokens();
 *                   sessionData.set(pathTokens.get("name"), pathTokens.get("value"));
 *                   ctx.render("ok");
 *                 })
 *             )
 *             .get("get/:name", ctx -> {
 *               ctx.get(Session.class).getData()
 *                 .map(d -> d.require(ctx.getPathTokens().get("name")))
 *                 .then(ctx::render);
 *             })
 *         )
 *     ).test(httpClient -> {
 *       assertEquals("ok", httpClient.getText("set/foo/bar"));
 *       assertEquals("bar", httpClient.getText("get/foo"));
 *
 *       assertEquals("ok", httpClient.getText("set/foo/baz"));
 *       assertEquals("baz", httpClient.getText("get/foo"));
 *     });
 *   }
 * }
 * }
*/ public class SessionModule extends ConfigurableModule { /** * The name of the binding for the {@link Cache} implementation that backs the in memory session store. * * @see #memoryStore(Consumer) */ public static final String LOCAL_MEMORY_SESSION_CACHE_BINDING_NAME = "localMemorySessionCache"; /** * The key of the binding for the {@link Cache} implementation that backs the in memory session store. * * @see #memoryStore(Consumer) */ public static final Key> LOCAL_MEMORY_SESSION_CACHE_BINDING_KEY = Key.get( new TypeLiteral>() {}, Names.named(LOCAL_MEMORY_SESSION_CACHE_BINDING_NAME) ); /** * A builder for an alternative cache for the default in memory store. *

* This method is intended to be used with the {@link BindingsSpec#binder(Action)} method. *

{@code
   * import ratpack.guice.Guice;
   * import ratpack.session.SessionModule;
   *
   * public class Example {
   *   public static void main(String... args) {
   *     Guice.registry(b -> b
   *         .binder(SessionModule.memoryStore(c -> c.maximumSize(100)))
   *     );
   *   }
   * }
   * }
* * @param config the cache configuration * @return an action that binds the cache * @see #memoryStore(Binder, Consumer) */ public static Action memoryStore(Consumer> config) { return b -> memoryStore(b, config); } /** * A builder for an alternative cache for the default in memory store. *

* This method can be used from within a custom {@link Module}. *

{@code
   * import com.google.inject.AbstractModule;
   * import ratpack.session.SessionModule;
   *
   * public class CustomSessionModule extends AbstractModule {
   *   protected void configure() {
   *     SessionModule.memoryStore(binder(), c -> c.maximumSize(100));
   *   }
   * }
   * }
* }

* This method binds the built cache with the {@link #LOCAL_MEMORY_SESSION_CACHE_BINDING_KEY} key. * It also implicitly registers a {@link RemovalListener}, that releases the byte buffers as they are discarded. * * @param binder the guice binder * @param config the cache configuration */ public static void memoryStore(Binder binder, Consumer> config) { binder.bind(LOCAL_MEMORY_SESSION_CACHE_BINDING_KEY).toProvider(() -> { CacheBuilder cacheBuilder = Types.cast(CacheBuilder.newBuilder()); cacheBuilder.removalListener(n -> n.getValue().release()); config.accept(cacheBuilder); return cacheBuilder.build(); }).in(Scopes.SINGLETON); } @Override protected void configure() { memoryStore(binder(), s -> s.maximumSize(1000)); } @Provides @Singleton SessionStore sessionStoreAdapter(@Named(LOCAL_MEMORY_SESSION_CACHE_BINDING_NAME) Cache cache) { return new LocalMemorySessionStore(cache); } @Provides SessionIdGenerator sessionIdGenerator() { return new DefaultSessionIdGenerator(); } @Provides @RequestScoped SessionId sessionId(Request request, Response response, SessionIdGenerator idGenerator, SessionCookieConfig cookieConfig) { return new CookieBasedSessionId(request, response, idGenerator, cookieConfig); } @Provides SessionSerializer sessionValueSerializer(JavaSessionSerializer sessionSerializer) { return sessionSerializer; } @Provides JavaSessionSerializer javaSessionSerializer() { return new JavaBuiltinSessionSerializer(); } @Provides @RequestScoped Session sessionAdapter(SessionId sessionId, SessionStore store, Response response, ByteBufAllocator bufferAllocator, SessionSerializer defaultSerializer, JavaSessionSerializer javaSerializer) { return new DefaultSession(sessionId, bufferAllocator, store, response, defaultSerializer, javaSerializer); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy