Skip to content

Commit

Permalink
Use Flapdoodle Embedded MongoDB for integration tests and samples
Browse files Browse the repository at this point in the history
  • Loading branch information
vpavic committed Mar 25, 2016
1 parent 3980be3 commit 903cac4
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 32 deletions.
3 changes: 1 addition & 2 deletions .travis.yml
Expand Up @@ -2,7 +2,6 @@ language: java

services:
- redis-server
- mongodb

jdk:
- oraclejdk8
Expand All @@ -21,4 +20,4 @@ cache:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/

script: ./gradlew build
script: ./gradlew build
16 changes: 8 additions & 8 deletions docs/src/docs/asciidoc/guides/mongo.adoc
Expand Up @@ -122,12 +122,6 @@ The Mongo Sample Application demonstrates how to use Spring Session to transpare

You can run the sample by obtaining the {download-url}[source code] and invoking the following command:

[NOTE]
====
For the sample to work, you must have MongoDB on localhost and run it with the default port (27017).
Alternatively you can use docker to run local instance `docker run -p 27017:27017 mongo`
====

----
$ ./gradlew :samples:mongo:bootRun
----
Expand Down Expand Up @@ -156,9 +150,15 @@ When Spring Security's `SecurityContextPersistenceFilter` saves the `SecurityCon
When a new `HttpSession` is created, Spring Session creates a cookie named SESSION in your browser that contains the id of your session.
Go ahead and view the cookies (click for help with https://developer.chrome.com/devtools/docs/resources#cookies[Chrome] or https://getfirebug.com/wiki/index.php/Cookies_Panel#Cookies_List[Firefox]).

If you like, you can easily remove the session using mongo client. For example, on a Linux based system you can type:
If you like, you can easily inspect the session using mongo client. For example, on a Linux based system you can type:

[NOTE]
====
The sample application uses an embedded MongoDB instance that listens on a randomly allocated port.
The port used by embedded MongoDB together with exact command to connect to it is logged during application startup.
====

$ mongo
$ mongo --port ...
> use test
> db.sessions.find().pretty()

Expand Down
3 changes: 2 additions & 1 deletion samples/mongo/build.gradle
Expand Up @@ -21,6 +21,7 @@ dependencies {
"org.springframework.boot:spring-boot-starter-web",
"org.springframework.boot:spring-boot-starter-thymeleaf",
"nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect",
"de.flapdoodle.embed:de.flapdoodle.embed.mongo",
"org.springframework.security:spring-security-web:$springSecurityVersion",
"org.springframework.security:spring-security-config:$springSecurityVersion"

Expand Down Expand Up @@ -50,4 +51,4 @@ def reservePort() {
def result = socket.localPort
socket.close()
result
}
}
44 changes: 44 additions & 0 deletions samples/mongo/src/main/java/sample/EmbeddedMongoPortLogger.java
@@ -0,0 +1,44 @@
/*
* Copyright 2014-2016 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 sample;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

@Component
class EmbeddedMongoPortLogger implements ApplicationRunner, EnvironmentAware {

private static final Logger logger = LoggerFactory.getLogger(EmbeddedMongoPortLogger.class);

private Environment environment;

public void run(ApplicationArguments args) throws Exception {
String port = this.environment.getProperty("local.mongo.port");
logger.info("Embedded Mongo started on port " + port +
", use 'mongo --port " + port + "' command to connect");
}

public void setEnvironment(Environment environment) {
this.environment = environment;
}

}
1 change: 1 addition & 0 deletions samples/mongo/src/main/resources/application.properties
@@ -1,2 +1,3 @@
spring.thymeleaf.cache=false
spring.template.cache=false
spring.data.mongodb.port=0
3 changes: 2 additions & 1 deletion spring-session/build.gradle
Expand Up @@ -28,7 +28,8 @@ dependencies {
integrationTestCompile "redis.clients:jedis:2.4.1",
"org.apache.commons:commons-pool2:2.2",
"com.hazelcast:hazelcast-client:$hazelcastVersion",
"com.h2database:h2:$h2Version"
"com.h2database:h2:$h2Version",
"de.flapdoodle.embed:de.flapdoodle.embed.mongo:1.50.2"

integrationTestRuntime "org.springframework.shell:spring-shell:1.0.0.RELEASE"

Expand Down
Expand Up @@ -15,13 +15,21 @@
*/
package org.springframework.session.data.mongo;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import com.mongodb.MongoClient;
import de.flapdoodle.embed.mongo.MongodExecutable;
import org.junit.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
Expand All @@ -30,11 +38,15 @@
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.Session;
import org.springframework.session.data.AbstractITests;
import org.springframework.util.SocketUtils;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Abstract base class for {@link MongoOperationsSessionRepository} tests.
*
* @author Jakub Kubrynski
* @author Vedran Pavic
*/
abstract public class AbstractMongoRepositoryITests extends AbstractITests {

Expand Down Expand Up @@ -364,4 +376,22 @@ protected String getChangedSecurityName() {
return this.changedContext.getAuthentication().getName();
}

protected static class BaseConfig {

private int embeddedMongoPort = SocketUtils.findAvailableTcpPort();

@Bean(initMethod = "start", destroyMethod = "stop")
public MongodExecutable embeddedMongoServer() throws IOException {
return MongoITestUtils.embeddedMongoServer(this.embeddedMongoPort);
}

@Bean
@DependsOn("embeddedMongoServer")
public MongoOperations mongoOperations() throws UnknownHostException {
MongoClient mongo = new MongoClient("localhost", this.embeddedMongoPort);
return new MongoTemplate(mongo, "test");
}

}

}
@@ -0,0 +1,53 @@
/*
* Copyright 2014-2016 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 org.springframework.session.data.mongo;

import java.io.IOException;

import de.flapdoodle.embed.mongo.MongodExecutable;
import de.flapdoodle.embed.mongo.MongodStarter;
import de.flapdoodle.embed.mongo.config.IMongodConfig;
import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
import de.flapdoodle.embed.mongo.config.Net;
import de.flapdoodle.embed.mongo.distribution.Version;
import de.flapdoodle.embed.process.runtime.Network;

/**
* Utility class for Mongo integration tests.
*
* @author Vedran Pavic
*/
final class MongoITestUtils {

private MongoITestUtils() {
}

/**
* Creates {@link MongodExecutable} for use in integration tests.
* @param port the port for embedded Mongo to bind to
* @return the {@link MongodExecutable} instance
* @throws IOException in case of I/O errors
*/
static MongodExecutable embeddedMongoServer(int port) throws IOException {
IMongodConfig mongodConfig = new MongodConfigBuilder()
.version(Version.Main.PRODUCTION)
.net(new Net(port, Network.localhostIsIPv6()))
.build();
MongodStarter mongodStarter = MongodStarter.getDefaultInstance();
return mongodStarter.prepare(mongodConfig);
}

}
Expand Up @@ -15,27 +15,27 @@
*/
package org.springframework.session.data.mongo;

import java.net.UnknownHostException;
import java.util.Collections;
import java.util.Map;
import java.util.UUID;

import com.fasterxml.jackson.databind.Module;
import com.mongodb.MongoClient;
import org.junit.Test;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.geo.GeoModule;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.session.data.mongo.config.annotation.web.http.EnableMongoHttpSession;
import org.springframework.test.context.ContextConfiguration;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Integration tests for {@link MongoOperationsSessionRepository} that use
* {@link JacksonMongoSessionConverter} based session serialization.
*
* @author Jakub Kubrynski
* @author Vedran Pavic
*/
@ContextConfiguration
public class MongoRepositoryJacksonITests extends AbstractMongoRepositoryITests {
Expand All @@ -57,12 +57,7 @@ public void findByCustomIndex() throws Exception {

@Configuration
@EnableMongoHttpSession
static class Config {

@Bean
public MongoOperations mongoOperations() throws UnknownHostException {
return new MongoTemplate(new MongoClient(), "test");
}
static class Config extends BaseConfig {

@Bean
public AbstractMongoSessionConverter mongoSessionConverter() {
Expand Down
Expand Up @@ -15,23 +15,23 @@
*/
package org.springframework.session.data.mongo;

import java.net.UnknownHostException;
import java.util.Map;

import com.mongodb.MongoClient;
import org.junit.Test;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.session.data.mongo.config.annotation.web.http.EnableMongoHttpSession;
import org.springframework.test.context.ContextConfiguration;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Integration tests for {@link MongoOperationsSessionRepository} that use
* {@link JacksonMongoSessionConverter} based session serialization.
*
* @author Jakub Kubrynski
* @author Vedran Pavic
*/
@ContextConfiguration
public class MongoRepositoryJdkSerializationITests extends AbstractMongoRepositoryITests {
Expand Down Expand Up @@ -75,12 +75,7 @@ public void findByPrincipalNameNoSecurityPrincipalNameChangeReload()

@Configuration
@EnableMongoHttpSession
static class Config {

@Bean
public MongoOperations mongoOperations() throws UnknownHostException {
return new MongoTemplate(new MongoClient(), "test");
}
static class Config extends BaseConfig {

@Bean
public AbstractMongoSessionConverter mongoSessionConverter() {
Expand Down

0 comments on commit 903cac4

Please sign in to comment.