I am trying to migrate from Spring Boot 2.7 application with Hazelcast 4.2 to Spring Boot 3.2 and Hazelcast 5.3, which also includes JCache Hazelcast provider.
In previous version I was using WebFilter from Hazelcast (https://github.com/hazelcast/hazelcast-wm/blob/master/src/main/java/com/hazelcast/web/WebFilter.java) registered with FilterRegistrationBean, but it is not prepared for Spring Boot 3 bacause of the lack of jakarta imports.
Because of that I wanted to use Spring Session Hazelcast 3 configuration, but after making request to application I am getting this stacktrace:
com.hazelcast.nio.serialization.HazelcastSerializationException: java.lang.ClassNotFoundException: org.springframework.session.hazelcast.SessionUpdateEntryProcessor
at com.hazelcast.internal.serialization.impl.defaultserializers.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:96)
at com.hazelcast.internal.serialization.impl.defaultserializers.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:85)
at (...)
Caused by: java.lang.ClassNotFoundException: org.springframework.session.hazelcast.SessionUpdateEntryProcessor
at jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
(...)
So then I added configuration for the hazelcast server and client to use "User Code Deployment" as stated in the documentation (along with Spring one): https://docs.hazelcast.com/hazelcast/5.3/clusters/deploying-code-on-member
but then I get error on missing class with @SessionScope
- do I have to add jar of classes?
com.hazelcast.core.HazelcastException: java.lang.NoClassDefFoundError: com/g4iner/ExampleCache$Companion
at com.hazelcast.internal.util.ExceptionUtil.lambda$static$0(ExceptionUtil.java:48)
I get this error after following this documentantion, but I'm not sure if I adjusted this in a right way: https://docs.spring.io/spring-session/reference/3.2/http-session.html#httpsession-hazelcast
There is also some information on Hazelcast but it lacks changes for new versions: https://docs.hazelcast.com/tutorials/spring-session-hazelcast
My configuration and code (using Spring Boot 3.2.6, Hazelcast 5.3.7 client, hazelcast 5.3.7 server running in docker-compose):
docker-compose.yml
version: "3"
services:
hazelcast:
image: hazelcast/hazelcast:5.3.7-slim-jdk17
environment:
- HZ_USERCODEDEPLOYMENT_ENABLED=true
ports:
- "5701:5701"
pom.xml
org.springframework.boot:spring-boot-starter-web-3.2.6
org.springframework.boot:spring-boot-starter-cache-3.2.6
org.springframework.session:spring-session-core-3.2.3
org.springframework.session:spring-session-hazelcast-3.2.3
javax.cache:cache-api-1.1.1
com.hazelcast:hazelcast-spring-5.3.7
com.hazelcast:hazelcast-5.3.7
application.yml
spring:
cache:
type: jcache
jcache:
provider: com.hazelcast.client.cache.HazelcastClientCachingProvider
hazelcast:
config: classpath:hazelcast-client.xml
hazelcast-client.xml
<hazelcast-client xmlns="http://www.hazelcast.com/schema/client-config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.hazelcast.com/schema/client-config
http://www.hazelcast.com/schema/client-config/hazelcast-client-config-5.3.xsd">
<cluster-name>dev</cluster-name>
<instance-name>hazelcast-client</instance-name>
<user-code-deployment enabled="true">
<classNames>
<className>org.springframework.session.hazelcast.SessionUpdateEntryProcessor</className>
<className>org.springframework.session.Session</className>
<className>org.springframework.session.MapSession</className>
</classNames>
</user-code-deployment>
<network>
<cluster-members>
<address>localhost:5701</address>
</cluster-members>
</network>
</hazelcast-client>
HazelcastSessionConfiguration.kt
@EnableHazelcastHttpSession
@Configuration
open class HazelcastSessionConfiguration {
@EnableHazelcastHttpSession
@Configuration
open class HazelcastSessionConfiguration {
@Bean
@SpringSessionHazelcastInstance
open fun hazelcastInstance(): HazelcastInstance {
val clientConfig = ClientConfig()
clientConfig.networkConfig.addAddress("localhost:5701")
clientConfig.userCodeDeploymentConfig.setEnabled(true).addClass(Session::class.java)
.addClass(MapSession::class.java).addClass(SessionUpdateEntryProcessor::class.java)
return HazelcastClient.newHazelcastClient(clientConfig)
}
// example config from Spring docs for Server - what and how do I need for docker instance?
@Bean
open fun hazelcastConfig(): Config {
val config = Config()
val attributeConfig = AttributeConfig()
.setName(HazelcastIndexedSessionRepository.PRINCIPAL_NAME_ATTRIBUTE)
.setExtractorClassName(PrincipalNameExtractor::class.java.name)
config.getMapConfig(HazelcastIndexedSessionRepository.DEFAULT_SESSION_MAP_NAME)
.addAttributeConfig(attributeConfig)
.addIndexConfig(
IndexConfig(IndexType.HASH, HazelcastIndexedSessionRepository.PRINCIPAL_NAME_ATTRIBUTE)
)
config.setClusterName("dev")
config.networkConfig.setPublicAddress("localhost:5701")
val serializerConfig = SerializerConfig()
serializerConfig.setImplementation(HazelcastSessionSerializer()).setTypeClass(MapSession::class.java)
config.serializationConfig.addSerializerConfig(serializerConfig)
return config
}
}
I tried different configurations,with and without "hazelcastConfig" bean, changing hazelcast to 5.4 and 4.2, or creating "hazelcastInstance" but nothing changes.
What am I missing here, what is the proper way of configuring client and server? Any help will be appreciated