5

In an attempt to externalize tomcat session for my existing application I am trying the Spring Session Redis solution. After following the steps to include necessary dependencies in pom.xml like so :

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
            <version>1.2.1.RELEASE</version>
        </dependency>

adding the springSessionRepositoryFilter in web.xml like this :

<filter>
        <filter-name>springSessionRepositoryFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSessionRepositoryFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

and adding the following in Spring XML configuration

<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>

<context:property-placeholder location="classpath:application.properties"/>

<bean class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:port="${spring.redis.port}"/>

and building and deploying on to tomcat, this is the error I am getting :

org.springframework.data.redis.serializer.SerializationException: Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.io.NotSerializableException: com.sun.jersey.client.apache.ApacheHttpClient

Any suggestion to or help is greatly appreciated. Thanks !! Also attached are my pom.xml entries : pom.xml entries

joeflux
  • 71
  • 1
  • 1
  • 4

5 Answers5

1

From your exception, com.sun.jersey.client.apache.ApacheHttpClient is not serializable because it did not implemented java.io.Serializable.

You need to serialize ApacheHttpClient in some other way, because it is a 3rd party library.

You can use org.codehaus.jackson.map.ObjectMapper from the Jackson library to achieve this.

Please refer this example.

You could also try SerializableEntity class shipped with HttpClient.

httpost.setEntity(new SerializableEntity(mySerializableObj, false));

Below are the general approaches to make a class serializable.

  • if the class is yours, make it Serializable ( this is not your case)
  • if the class is 3rd party, but you don't need it in the serialized form, mark the field as transient
  • if you need its data and it's third party, consider other means of serialization, like JSON, XML,BSON, MessagePack etc. where you can get 3rd party objects serialized without modifying their definitions.
Sundararaj Govindasamy
  • 8,180
  • 5
  • 44
  • 77
  • after trying your suggestion, now I get the following errors/exceptions... I am wondering if I am running into compatibility issues with Spring Session... 'code' org.springframework.data.redis.serializer.SerializationException: Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.io.NotSerializableException: org.springframework.context.support.ReloadableResourceBundleMessageSource – joeflux Jul 25 '16 at 12:44
1

Just want to illustrate one of the possible solutions here. For brevity, I assume you are using spring-boot.

Essentially, spring boot auto-configures the beans defined in RedisHttpSessionConfiguration class when you annotate your application with @EnableRedisHttpSession. And within the autoconfigured beans, sessionRedisTemplate is what you want customize the serializer. The codes below shows the default bean definition provided by RedisHttpSessionConfiguration.

@Bean
public RedisTemplate<Object, Object> sessionRedisTemplate(
        RedisConnectionFactory connectionFactory) {
    RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
    template.setKeySerializer(new StringRedisSerializer());
    template.setHashKeySerializer(new StringRedisSerializer());
    if (this.defaultRedisSerializer != null) {
        template.setDefaultSerializer(this.defaultRedisSerializer);
    }
    template.setConnectionFactory(connectionFactory);
    return template;
}

To override this bean config, simple declare a bean named sessionRedisTemplate in one of your @Configuration classes (e.g., HttpSessionConfig), and Spring-boot will does the magic to override its default setting. Here, I demo it with a GenericJackson2JsonSerializer.

@Configuration
public class HttpSessionConfig {

@Bean
public RedisTemplate<Object, Object> sessionRedisTemplate(
        RedisConnectionFactory connectionFactory) {
    RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
    template.setKeySerializer(new StringRedisSerializer());
    template.setHashKeySerializer(new StringRedisSerializer());

    template.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());

    template.setConnectionFactory(connectionFactory);
    return template;
}
}
imarchuang
  • 467
  • 7
  • 17
0

I had also same issue, and making the class Serializable solved my problem.

elifa
  • 1
  • 1
  • I think the important note here is that the class causing the OP's serialization exception is from an external library, so it can't simply be updated as `serializable` – acidnbass Dec 17 '21 at 20:48
0

I solved by adding Serializable to my entity to be like below:

public class YourEntity implements Serializable{}
Abd Abughazaleh
  • 4,615
  • 3
  • 44
  • 53
0

Your entity should implement Serializable interface.