// Path: core/src/main/java/com/softwaremill/session/javadsl/HttpSessionAwareDirectives.java
// public class HttpSessionAwareDirectives<T> extends AllDirectives {
// 
//     private final SessionManager<T> sessionManager;
// 
//     public HttpSessionAwareDirectives(SessionManager<T> sessionManager) {
//         this.sessionManager = sessionManager;
//     }
// 
//     public Route session(SessionContinuity sc, GetSessionTransport st, Function<SessionResult<T>, Route> continuity) {
//         return SessionDirectives$.MODULE$.session(sc, st, continuity);
//     }
// 
//     public Route setSession(SessionContinuity sc, SetSessionTransport st, T session, Supplier<Route> continuity) {
//         return SessionDirectives$.MODULE$.setSession(sc, st, session, continuity);
//     }
// 
//     public Route optionalSession(SessionContinuity sc, SetSessionTransport st, Function<Optional<T>, Route> continuity) {
//         return SessionDirectives$.MODULE$.optionalSession(sc, st, continuity);
//     }
// 
//     public Route requiredSession(SessionContinuity<T> sc, SetSessionTransport st, Function<T, Route> continuity) {
//         return SessionDirectives$.MODULE$.requiredSession(sc, st, continuity);
//     }
// 
//     public Route touchRequiredSession(SessionContinuity<T> sc, SetSessionTransport st, Function<T, Route> continuity) {
//         return SessionDirectives$.MODULE$.touchRequiredSession(sc, st, continuity);
//     }
// 
//     public Route invalidateSession(SessionContinuity<T> sc, SetSessionTransport st, Supplier<Route> continuity) {
//         return SessionDirectives$.MODULE$.invalidateSession(sc, st, continuity);
//     }
// 
//     public Route setNewCsrfToken(CsrfCheckMode<T> checkHeader, Supplier<Route> continuity) {
//         return CsrfDirectives$.MODULE$.setNewCsrfToken(checkHeader, continuity);
//     }
// 
//     public Route randomTokenCsrfProtection(CsrfCheckMode<T> checkHeader, Supplier<Route> continuity) {
//         return CsrfDirectives$.MODULE$.randomTokenCsrfProtection(checkHeader, continuity);
//     }
// 
//     public SessionManager<T> getSessionManager() {
//         return sessionManager;
//     }
// }
// 
// Path: core/src/main/java/com/softwaremill/session/javadsl/SessionTransports.java
// public static final SetSessionTransport CookieST = CookieST$.MODULE$;


import akka.NotUsed;
import akka.actor.ActorSystem;
import akka.dispatch.MessageDispatcher;
import akka.http.javadsl.ConnectHttp;
import akka.http.javadsl.Http;
import akka.http.javadsl.ServerBinding;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.HttpResponse;
import akka.http.javadsl.server.Route;
import akka.stream.ActorMaterializer;
import akka.stream.javadsl.Flow;
import com.softwaremill.session.BasicSessionEncoder;
import com.softwaremill.session.CheckHeader;
import com.softwaremill.session.RefreshTokenStorage;
import com.softwaremill.session.Refreshable;
import com.softwaremill.session.SessionConfig;
import com.softwaremill.session.SessionEncoder;
import com.softwaremill.session.SessionManager;
import com.softwaremill.session.SetSessionTransport;
import com.softwaremill.session.javadsl.HttpSessionAwareDirectives;
import com.softwaremill.session.javadsl.InMemoryRefreshTokenStorage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.concurrent.CompletionStage;
import static com.softwaremill.session.javadsl.SessionTransports.CookieST;
        ActorSystem system = ActorSystem.create("example");
        final ActorMaterializer materializer = ActorMaterializer.create(system);
        final Http http = Http.get(system);

        // ** akka-http-session setup **
        MessageDispatcher dispatcher = system.dispatchers().lookup("akka.actor.default-dispatcher");
        final SessionInvalidationJava app = new SessionInvalidationJava(dispatcher);

        // ** akka-http boiler plate continued **
        final Flow<HttpRequest, HttpResponse, NotUsed> routes = app.createRoutes().flow(system, materializer);
        final CompletionStage<ServerBinding> binding = http.bindAndHandle(routes, ConnectHttp.toHost("localhost", 8080), materializer);

        System.out.println("Server started, press enter to stop");
        System.in.read();

        binding
            .thenCompose(ServerBinding::unbind)
            .thenAccept(unbound -> system.terminate());
    }

    private Route createRoutes() {
        CheckHeader<MyJavaSession> checkHeader = new CheckHeader<>(getSessionManager());
        return
            route(
                randomTokenCsrfProtection(checkHeader, () ->
                    route(
                        path("logout", () ->
                            post(() ->
                                requiredSession(refreshable, sessionTransport, session ->
                                    invalidateSession(refreshable, sessionTransport, () ->
// Path: core/src/main/java/com/softwaremill/session/javadsl/HttpSessionAwareDirectives.java
// public class HttpSessionAwareDirectives<T> extends AllDirectives {
// 
//     private final SessionManager<T> sessionManager;
// 
//     public HttpSessionAwareDirectives(SessionManager<T> sessionManager) {
//         this.sessionManager = sessionManager;
//     }
// 
//     public Route session(SessionContinuity sc, GetSessionTransport st, Function<SessionResult<T>, Route> continuity) {
//         return SessionDirectives$.MODULE$.session(sc, st, continuity);
//     }
// 
//     public Route setSession(SessionContinuity sc, SetSessionTransport st, T session, Supplier<Route> continuity) {
//         return SessionDirectives$.MODULE$.setSession(sc, st, session, continuity);
//     }
// 
//     public Route optionalSession(SessionContinuity sc, SetSessionTransport st, Function<Optional<T>, Route> continuity) {
//         return SessionDirectives$.MODULE$.optionalSession(sc, st, continuity);
//     }
// 
//     public Route requiredSession(SessionContinuity<T> sc, SetSessionTransport st, Function<T, Route> continuity) {
//         return SessionDirectives$.MODULE$.requiredSession(sc, st, continuity);
//     }
// 
//     public Route touchRequiredSession(SessionContinuity<T> sc, SetSessionTransport st, Function<T, Route> continuity) {
//         return SessionDirectives$.MODULE$.touchRequiredSession(sc, st, continuity);
//     }
// 
//     public Route invalidateSession(SessionContinuity<T> sc, SetSessionTransport st, Supplier<Route> continuity) {
//         return SessionDirectives$.MODULE$.invalidateSession(sc, st, continuity);
//     }
// 
//     public Route setNewCsrfToken(CsrfCheckMode<T> checkHeader, Supplier<Route> continuity) {
//         return CsrfDirectives$.MODULE$.setNewCsrfToken(checkHeader, continuity);
//     }
// 
//     public Route randomTokenCsrfProtection(CsrfCheckMode<T> checkHeader, Supplier<Route> continuity) {
//         return CsrfDirectives$.MODULE$.randomTokenCsrfProtection(checkHeader, continuity);
//     }
// 
//     public SessionManager<T> getSessionManager() {
//         return sessionManager;
//     }
// }
// 
// Path: core/src/main/java/com/softwaremill/session/javadsl/SessionTransports.java
// public static final SetSessionTransport CookieST = CookieST$.MODULE$;


// Path: example/src/main/java/com/softwaremill/example/session/SessionInvalidationJava.java
import akka.NotUsed;
import akka.actor.ActorSystem;
import akka.dispatch.MessageDispatcher;
import akka.http.javadsl.ConnectHttp;
import akka.http.javadsl.Http;
import akka.http.javadsl.ServerBinding;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.HttpResponse;
import akka.http.javadsl.server.Route;
import akka.stream.ActorMaterializer;
import akka.stream.javadsl.Flow;
import com.softwaremill.session.BasicSessionEncoder;
import com.softwaremill.session.CheckHeader;
import com.softwaremill.session.RefreshTokenStorage;
import com.softwaremill.session.Refreshable;
import com.softwaremill.session.SessionConfig;
import com.softwaremill.session.SessionEncoder;
import com.softwaremill.session.SessionManager;
import com.softwaremill.session.SetSessionTransport;
import com.softwaremill.session.javadsl.HttpSessionAwareDirectives;
import com.softwaremill.session.javadsl.InMemoryRefreshTokenStorage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.concurrent.CompletionStage;
import static com.softwaremill.session.javadsl.SessionTransports.CookieST;

        ActorSystem system = ActorSystem.create("example");
        final ActorMaterializer materializer = ActorMaterializer.create(system);
        final Http http = Http.get(system);

        // ** akka-http-session setup **
        MessageDispatcher dispatcher = system.dispatchers().lookup("akka.actor.default-dispatcher");
        final SessionInvalidationJava app = new SessionInvalidationJava(dispatcher);

        // ** akka-http boiler plate continued **
        final Flow<HttpRequest, HttpResponse, NotUsed> routes = app.createRoutes().flow(system, materializer);
        final CompletionStage<ServerBinding> binding = http.bindAndHandle(routes, ConnectHttp.toHost("localhost", 8080), materializer);

        System.out.println("Server started, press enter to stop");
        System.in.read();

        binding
            .thenCompose(ServerBinding::unbind)
            .thenAccept(unbound -> system.terminate());
    }

    private Route createRoutes() {
        CheckHeader<MyJavaSession> checkHeader = new CheckHeader<>(getSessionManager());
        return
            route(
                randomTokenCsrfProtection(checkHeader, () ->
                    route(
                        path("logout", () ->
                            post(() ->
                                requiredSession(refreshable, sessionTransport, session ->
                                    invalidateSession(refreshable, sessionTransport, () ->
                                        extractRequestContext(ctx -> {