Search code examples
javamongodbhttpsessionspring-sessionspring-boot-starter

Moving from @EnableRedisHttpSession to @EnableMongoHttpSession receiving exception


I have a Java 8 spring boot project that was using the Redis HttpSession store. However, I want to change it to use the Mongo HttpSession store instead. I changed my deependency from:

 <dependency>
  <groupId>org.springframework.session</groupId>
  <artifactId>spring-session-data-redis</artifactId>
  <version>1.3.1.RELEASE</version>
</dependency>

to:

 <dependency>
  <groupId>org.springframework.session</groupId>
  <artifactId>spring-session-data-mongo</artifactId>
  <version>1.3.1.RELEASE</version>
</dependency>

And I changed the corresponding configuration annotation from @EnableRedisHttpSession to @EnableMongoHttpSession.

However, when I run the following commands, the service outputs the stack trace shown below.

$ curl -i --cookie-jar cookie.jar -d "username=jkaldon&password=abc123" --header "Content-Type: application/x-www-form-urlencoded"  --header "Host: authentication.services.mycompany.com" -X POST http://localhost:8080/api/v1/login
HTTP/1.1 200 
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Set-Cookie: XSRF-TOKEN=b3b28861-8ce8-4629-a54c-d6d73039a3ee; Domain=mycompany.com; Path=/; HttpOnly
Set-Cookie: SESSION=3a2846ee-4d7b-4e12-970a-81617f6b8b18; Domain=mycompany.com; Path=/; HttpOnly
Content-Type: application/json;charset=ISO-8859-1
Content-Length: 312
Date: Wed, 25 Oct 2017 18:36:08 GMT

{"sessionId":"3a2846ee-4d7b-4e12-970a-81617f6b8b18","xsrfToken":"b3b28861-8ce8-4629-a54c-d6d73039a3ee","currentUser":{"userId":"slkdjfois","firstName":"Joshua","lastName":"Kaldon","avatarUrl":"https://s3.amazonaws.com/uifaces/faces/twitter/mohanrohith/128.jpg"},"brandConfiguration":{"navBarTitle":"Sale Winds"}}

$ curl -v -b cookie.jar --cookie-jar cookie.jar --header "Host: authentication.mycompany.com" --header "X-XSRF-TOKEN: b3b28861-8ce8-4629-a54c-d6d73039a3ee" --header "Accept: application/json" -X POST http://localhost:8080/api/v1/validateSession
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> POST /api/v1/validateSession HTTP/1.1
> Host: authentication.mycompany.com
> User-Agent: curl/7.54.0
> Cookie: SESSION=3a2846ee-4d7b-4e12-970a-81617f6b8b18; XSRF-TOKEN=b3b28861-8ce8-4629-a54c-d6d73039a3ee
> X-XSRF-TOKEN: b3b28861-8ce8-4629-a54c-d6d73039a3ee
> Accept: application/json
> 
< HTTP/1.1 500 
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Wed, 25 Oct 2017 18:39:29 GMT
< Connection: close
< 
* Closing connection 0
{"timestamp":1508956769703,"status":500,"error":"Internal Server Error","exception":"org.springframework.expression.spel.SpelEvaluationException","message":"EL1008E: Property or field 'authentication' cannot be found on object of type 'java.util.LinkedHashMap' - maybe not public?","path":"/api/v1/validateSession"}

The stack trace follows:

13:12:38.553 WARN  o.s.s.w.c.HttpSessionSecurityContextRepository - SPRING_SECURITY_CONTEXT did not contain a SecurityContext but contained: '{authentication={authorities=[{role=ROLE_USER}], details={remoteAddress=127.0.0.1, sessionId=null}, authenticated=true, principal={password=null, username=jkaldon, authorities=[{role=ROLE_USER}], accountNonExpired=true, accountNonLocked=true, credentialsNonExpired=true, enabled=true}, credentials=null}}'; are you improperly modifying the HttpSession directly (you should always use SecurityContextHolder) or using the HttpSession attribute reserved for this class?
13:12:38.565 ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'authentication' cannot be found on object of type 'java.util.LinkedHashMap' - maybe not public?
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:226)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:94)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:81)
at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:51)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:87)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:132)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:233)
at org.springframework.session.data.mongo.AuthenticationParser.extractName(AuthenticationParser.java:41)
at org.springframework.session.data.mongo.AbstractMongoSessionConverter.extractPrincipal(AbstractMongoSessionConverter.java:85)
at org.springframework.session.data.mongo.JacksonMongoSessionConverter.convert(JacksonMongoSessionConverter.java:88)
at org.springframework.session.data.mongo.AbstractMongoSessionConverter.convert(AbstractMongoSessionConverter.java:110)
at org.springframework.session.data.mongo.MongoOperationsSessionRepository.convertToDBObject(MongoOperationsSessionRepository.java:141)
at org.springframework.session.data.mongo.MongoOperationsSessionRepository.save(MongoOperationsSessionRepository.java:77)
at org.springframework.session.data.mongo.MongoOperationsSessionRepository.save(MongoOperationsSessionRepository.java:44)
at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:245)
at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.access$100(SessionRepositoryFilter.java:217)
at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:170)
at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:80)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)

Also, FYI, this is what shows up in mongo after the first command is run:

> db.sessions.find().pretty()
{
    "_id" : "3a2846ee-4d7b-4e12-970a-81617f6b8b18",
    "created" : NumberLong("1508956567988"),
    "accessed" : NumberLong("1508956567988"),
    "interval" : 1800,
    "expireAt" : NumberLong("1508958367988"),
    "attrs" : {
        "SPRING_SECURITY_CONTEXT" : {
            "authentication" : {
                "authorities" : [
                    {
                        "role" : "ROLE_USER"
                    }
                ],
                "details" : {
                    "remoteAddress" : "0:0:0:0:0:0:0:1",
                    "sessionId" : null
                },
                "authenticated" : true,
                "principal" : {
                    "password" : null,
                    "username" : "jkaldon",
                    "authorities" : [
                        {
                            "role" : "ROLE_USER"
                        }
                    ],
                    "accountNonExpired" : true,
                    "accountNonLocked" : true,
                    "credentialsNonExpired" : true,
                    "enabled" : true
                },
                "credentials" : null
            }
        }
    },
    "principal" : "jkaldon"
}

Now keep mind that all of this worked fine when I was using Redis.

Thanks.


Solution

  • It turns out that I had accidentally lost a bean in my config class.

    I added the following to my configuration and now it works like a charm.

    @Bean
    public JdkMongoSessionConverter jdkMongoSessionConverter() {
        return new JdkMongoSessionConverter();
    }