Getting Hazelcast Native Client working with Hibernate 5.2.x

Jan Vladimir Mostert :

I'm trying to get Hazelcast working with Hibernate, but unless i use the super_client option, it doesn't start up.

According to the docs, Super Client should only be used if your app is on the same RAC or data center. For local, this will be the case, for production, they will most definitely be separated, so Native Client is the only option that will work for us.

Super Client is a member of the cluster, it has socket connection to every member in the cluster and it knows where the data is so it will get to the data much faster. But Super Client has the clustering overhead and it must be on the same data center even on the same RAC. However Native client is not member and relies on one of the cluster members. Native Clients can be anywhere in the LAN or WAN. It scales much better and overhead is quite less. So if your clients are less than Hazelcast nodes then Super client can be an option; otherwise definitely try Native Client. As a rule of thumb: Try Native client first, if it doesn't perform well enough for you, then consider Super client.

The best option for starting up Hazelcast seems to be using Docker:

docker pull hazelcast/hazelcast:3.10.4
docker run --name=hazelcast -d=true -p 5701:5701 hazelcast/hazelcast:3.10.4

And this is what it looks like once it is up and running, i double checked that the Hazelcast port, 5701, is exposed which it clearly is.

CONTAINER ID        IMAGE                        COMMAND                  CREATED             STATUS              PORTS                    NAMES
77a5a0bed5eb        hazelcast/hazelcast:3.10.4   "bash -c 'set -euo p…"   3 days ago          Up 6 hours          0.0.0.0:5701->5701/tcp   hazelcast

The docker hub docs also mentions how to pass in JAVA_OPTS, i'm not sure if this is required or optional and what its purpose is, but this didn't help me get up and running:

-e JAVA_OPTS="-Dhazelcast.local.publicAddress=127.0.0.1:5701"

telnet 127.0.0.1 5701 successfully connects to localhost:5701, so i know the port is open. The docker docs doesn't mention what the default password is for this running Hazelcast instance, my assumption is that it's empty or that the password is dev-pass as mentioned in several older tutorials.

I'm using Hibernate 5.2.13.Final

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>${hibernate.version}</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>${hibernate.version}</version>
        <exclusions>
            <exclusion>
                <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
            </exclusion>
            <exclusion>
                <groupId>dom4j</groupId>
                <artifactId>dom4j</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>${hibernate-validator.version}</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-c3p0</artifactId>
        <version>${hibernate.version}</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-java8</artifactId>
        <version>${hibernate.version}</version>
    </dependency>

For Hazelcast, according to the docs, two dependencies are required,

    <dependency>
        <groupId>com.hazelcast</groupId>
        <artifactId>hazelcast</artifactId>
        <version>3.10.4</version>
    </dependency>
    <dependency>
        <groupId>com.hazelcast</groupId>
        <artifactId>hazelcast-hibernate52</artifactId>
        <version>1.2.3</version>
    </dependency>
    <dependency>
        <groupId>com.hazelcast</groupId>
        <artifactId>hazelcast-client</artifactId>
        <version>3.10.4</version>
    </dependency>

The docs show the following links:

enter image description here

Clicking Hibernate 5 shows that hazelcast-hibernate52 is the correct dependency

enter image description here

When i click See here for details, i'm greeted with docs that look somewhat outdated:

enter image description here

Assuming there's only a typo, i go through to the example:

<!DOCTYPE hibernate-configuration SYSTEM "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <property name="hibernate.cache.use_query_cache">false</property>
        <property name="hibernate.cache.use_minimal_puts">true</property>
        <property name="hibernate.cache.region.factory_class">com.hazelcast.hibernate.HazelcastCacheRegionFactory</property>
        <property name="hibernate.cache.hazelcast.use_native_client">false</property>
        <property name="hibernate.cache.hazelcast.native_client_hosts">127.0.0.1</property>
        <property name="hibernate.cache.hazelcast.native_client_group">hibernate</property>
        <property name="hibernate.cache.hazelcast.native_client_password">password</property>
        <property name="hibernate.connection.driver_class">org.apache.derby.jdbc.EmbeddedDriver</property>
        <property name="hibernate.connection.url">jdbc:derby:hibernateDB</property>
        <mapping resource="Employee.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

In the example, Use Native Client is set to false, yet it is being configured, is this a typo or is this the correct configuration?

I'm trying out these settings on a standard Hibernate Postgres with C3P0 setup, here's my persistence.xml

        <properties>

            <!-- Hibernate Config -->
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL95Dialect" />
            <property name="hibernate.generate_statistics" value="false" />

            <property name="hibernate.hbm2ddl.auto" value="validate"/>

            <property name="hibernate.physical_naming_strategy" value="za.co.convirt.util.CustomApplicationNamingStrategy"/>

            <property name="hibernate.connection.charSet" value="UTF-8"/>
            <property name="hibernate.show_sql" value="false" />
            <property name="hibernate.format_sql" value="false"/>
            <property name="hibernate.use_sql_comments" value="false"/>

            <!-- JDBC Config -->
            <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />

            <property name="javax.persistence.jdbc.time_zone" value="UTC" />
            <property name="hibernate.jdbc.time_zone" value="UTC"/>

            <!-- Connection Pool -->
            <property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider" />
            <property name="hibernate.c3p0.max_size" value="5" />
            <property name="hibernate.c3p0.min_size" value="1" />
            <property name="hibernate.c3p0.acquire_increment" value="1" />
            <property name="hibernate.c3p0.idle_test_period" value="300" />
            <property name="hibernate.c3p0.max_statements" value="0" />
            <property name="hibernate.c3p0.timeout" value="100" />

            <!-- Batch writing -->
            <property name="hibernate.jdbc.batch_size" value = "50"/>
            <property name="hibernate.order_updates" value = "true"/>
            <property name="hibernate.jdbc.batch_versioned_data" value = "true"/>

        </properties>

Some params are entered programmatically via (this has been in use for ages, so i know it works, but adding it here just in case it helps make the code more clear)

fun paramsFromArgs(args: Array<String>): Map<String, String> {
    val hibernateMap = mutableMapOf<String, String>()
    args.forEach {
        if (it.isNotBlank()) {
            if (it.startsWith("hibernate") || it.startsWith("javax.persistence")) {
                val split = it.split("=", limit = 2)
                hibernateMap.put(split.get(0), split.get(1))
            }
        }
    }
    return hibernateMap
}

Now when i setup Second Level cache with Hazelcast:

paramsDefault.add("hibernate.cache.use_query_cache=true")
paramsDefault.add("hibernate.cache.use_second_level_cache=true")
paramsDefault.add("hibernate.cache.region.factory_class=com.hazelcast.hibernate.HazelcastCacheRegionFactory")
paramsDefault.add("hibernate.cache.provider_configuration_file_resource_path=hazelcast.xml")
paramsDefault.add("hibernate.cache.hazelcast.use_native_client=false")
paramsDefault.add("hibernate.cache.hazelcast.native_client_address=127.0.0.1")
paramsDefault.add("hibernate.cache.hazelcast.native_client_group=dev")
paramsDefault.add("hibernate.cache.hazelcast.native_client_password=dev-pass22222asfasdf")
paramsDefault.add("hibernate.cache.hazelcast.client.statistics.enabled=true")

Database.setupEntityManagerFactory("default",
                Database.paramsFromArgs(paramsDefault.toTypedArray()))

Setting use_native_client to false like in the example doesn't seem to do anything, with the logs in debug mode, i'm not seeing anything Hazelcast related.

Switching it to true (which makes more sense considering it's being configured to have a password and IP address, it bombs out on startup.

hibernate.cache.hazelcast.use_native_client=true hibernate.cache.hazelcast.native_client_address=127.0.0.1 hibernate.cache.hazelcast.native_client_group=dev hibernate.cache.hazelcast.native_client_password=dev-pass

DEB [16:18:26.531] setup org.hibernate.jpa.internal.util.LogHelper PersistenceUnitInfo [
    name: default
    persistence provider classname: org.hibernate.jpa.HibernatePersistenceProvider
    classloader: null
    excludeUnlistedClasses: false
    JTA datasource: null
    Non JTA datasource: null
    Transaction type: RESOURCE_LOCAL
    PU root URL: file:/Users/vlad/Code/.../...
    Shared Cache Mode: null
    Validation Mode: null
    Jar files URLs []
    Managed classes names []
    Mapping files names []
    Properties [
        ...  
        hibernate.jdbc.time_zone: UTC
        javax.persistence.jdbc.password: 
        hibernate.cache.region.factory_class: com.hazelcast.hibernate.HazelcastCacheRegionFactory
        hibernate.c3p0.idle_test_period: 300
        hibernate.cache.hazelcast.use_native_client: true
        ...         
        hibernate.cache.hazelcast.native_client_group: dev
        ...
        javax.persistence.jdbc.driver: org.postgresql.Driver
        hibernate.use_sql_comments: false
        hibernate.cache.hazelcast.native_client_address: 127.0.0.1
        ...
        hibernate.cache.hazelcast.client.statistics.enabled: true
        hibernate.dialect: org.hibernate.dialect.PostgreSQL95Dialect
        hibernate.cache.provider_configuration_file_resource_path: hazelcast.xml]

HazelcastCacheRegionFactory is being used according to the logs:

    DEB [16:18:26.884] setup org.hibernate.cache.internal.RegionFactoryInitiator 
Cache region factory : com.hazelcast.hibernate.HazelcastCacheRegionFactory

Followed by two log entries that doesn't follow my logging standard (i'm guessing it's not using SLF4j?):

Sep 12, 2018 2:18:29 PM com.hazelcast.hibernate.HazelcastCacheRegionFactory
INFO: Starting up HazelcastCacheRegionFactory

... and then Unable to build Hibernate Session Factory:

ERR [16:18:29.802] setup ApplicationApi [PersistenceUnit: default] Unable to build Hibernate SessionFactory
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException (EntityManagerFactoryBuilderImpl.java:970)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build (EntityManagerFactoryBuilderImpl.java:895)
    at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory (HibernatePersistenceProvider.java:58)
    at javax.persistence.Persistence.createEntityManagerFactory (Persistence.java:55)
    at za.co.convirt.util.Database.setupEntityManagerFactory (Database.kt:20)
    at za.co.convirt.util.Database.setupEntityManagerFactory$default (Database.kt:19)
    at ApplicationApi$main$hibernateThread$1.invoke (ApplicationApi.kt:171)
    at ApplicationApi$main$hibernateThread$1.invoke (ApplicationApi.kt:26)
    at kotlin.concurrent.ThreadsKt$thread$thread$1.run (Thread.kt:30)

To make sure that it's not failing due to missing annotations on entities, i added a few @Cache annotations to entities, but it makes no difference.

@Table
@Entity
@EntityListeners(AuditListener::class)
@PersistenceContext(unitName = "default")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "Seat")
class Seat(
    name: String,
    ...

I've also added a hazelcast.xml, not sure if this is needed or not:

<hazelcast
        xmlns="http://www.hazelcast.com/schema/config"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
            http://www.hazelcast.com/schema/config
            http://www.hazelcast.com/schema/config/hazelcast-config-3.11.xsd">

    <services enable-defaults="true"/>

</hazelcast>

Is hibernate 5.2.x supported? (this ticket shows that the problems with Hibernate 5.2 was fixed, so my assumption is that it should work)

I want to run a stand-alone Hazelcast instance on one server and have multiple instances of the application use it as a central cache location, what am i missing from setup to make it work?


Update 1:

I've written a small piece of code that successfully connects to the local hazelcast instance (this is on my dev machine, same as with the rest of the code)

import com.hazelcast.client.HazelcastClient
import com.hazelcast.client.config.ClientConfig
import java.util.*

fun main(args: Array<String>) {

    val config = ClientConfig()
    config.getNetworkConfig().addAddress("127.0.0.1:5701")
    val hazelcastInstance = HazelcastClient.newHazelcastClient(config)

    val map = hazelcastInstance.getMap<String, String>("blah")
    map.forEach { t, u ->
        println(" $t -> $u ")
    }

    map.put("${Random().nextInt()}", "${Random().nextInt()}")

    hazelcastInstance.shutdown()

}

To proof that it's storing and retrieving from cache, i restart the main method several times and each time the number of entries in blah increases

Run1: 
    No printlns
Run2: 
    1498523740 -> -1418154711 
Run3: 
    1498523740 -> -1418154711 
    -248583979 -> -940621527 

So Hazelcast is working correctly ...


Update 2:

I can now connect hazelcast from Hibernate, but it's throwing an exception for every lookup it has to do.

Removing hazelcast.xml from my classpath and then removing the group and password options, Hibernate is starting up and connecting.

paramsDefault.add("hibernate.cache.use_query_cache=true")
paramsDefault.add("hibernate.cache.use_second_level_cache=true")
paramsDefault.add("hibernate.cache.region.factory_class=com.hazelcast.hibernate.HazelcastCacheRegionFactory")
paramsDefault.add("hibernate.cache.hazelcast.use_native_client=true")
paramsDefault.add("hibernate.cache.hazelcast.native_client_address=127.0.0.1")

Outputs:

Sep 13, 2018 6:02:37 PM com.hazelcast.hibernate.HazelcastCacheRegionFactory
INFO: Starting up HazelcastCacheRegionFactory
Sep 13, 2018 6:02:37 PM com.hazelcast.core.LifecycleService
INFO: hz.client_0 [dev] [3.10.4] HazelcastClient 3.10.4 (20180727 - 0f51fcf) is STARTING
Sep 13, 2018 6:02:38 PM com.hazelcast.client.spi.ClientInvocationService
INFO: hz.client_0 [dev] [3.10.4] Running with 2 response threads
Sep 13, 2018 6:02:38 PM com.hazelcast.core.LifecycleService
INFO: hz.client_0 [dev] [3.10.4] HazelcastClient 3.10.4 (20180727 - 0f51fcf) is STARTED
Sep 13, 2018 6:02:38 PM com.hazelcast.client.connection.ClientConnectionManager
INFO: hz.client_0 [dev] [3.10.4] Trying to connect to [127.0.0.1]:5701 as owner member
Sep 13, 2018 6:02:38 PM com.hazelcast.client.connection.ClientConnectionManager
INFO: hz.client_0 [dev] [3.10.4] Setting ClientConnection{alive=true, connectionId=1, channel=NioChannel{/127.0.0.1:61191->/127.0.0.1:5701}, remoteEndpoint=[127.0.0.1]:5701, lastReadTime=2018-09-13 18:02:38.356, lastWriteTime=2018-09-13 18:02:38.352, closedTime=never, lastHeartbeatRequested=never, lastHeartbeatReceived=never, connected server version=3.10.4} as owner with principal ClientPrincipal{uuid='532bf500-e03e-4620-a9c2-14bb55c07166', ownerUuid='2fb66fa1-a17f-49fe-ba2b-bf585d43906d'}
Sep 13, 2018 6:02:38 PM com.hazelcast.client.connection.ClientConnectionManager
INFO: hz.client_0 [dev] [3.10.4] Authenticated with server [127.0.0.1]:5701, server version:3.10.4 Local address: /127.0.0.1:61191
Sep 13, 2018 6:02:38 PM com.hazelcast.client.spi.impl.ClientMembershipListener
INFO: hz.client_0 [dev] [3.10.4] 

Members [1] {
    Member [127.0.0.1]:5701 - 2fb66fa1-a17f-49fe-ba2b-bf585d43906d
}

Sep 13, 2018 6:02:38 PM com.hazelcast.core.LifecycleService
INFO: hz.client_0 [dev] [3.10.4] HazelcastClient 3.10.4 (20180727 - 0f51fcf) is CLIENT_CONNECTED
Sep 13, 2018 6:02:38 PM com.hazelcast.internal.diagnostics.Diagnostics
INFO: hz.client_0 [dev] [3.10.4] Diagnostics disabled. To enable add -Dhazelcast.diagnostics.enabled=true to the JVM arguments.

However, any entity that's being retrieved that makes a call to Hazelcast, just stalls.

I've restarted Hazelcast with JAVA_OPTS to see if it makes a different, doesn't seem like it:

docker run --name=hazelcast -d=true -p 5701:5701 -e JAVA_OPTS="-Dhazelcast.local.publicAddress=127.0.0.1:5701" hazelcast/hazelcast:3.10.4

Digging into Hazelcast logs using:

docker logs -f hazelcast

I'm seeing the following:

 Sep 13, 2018 6:02:11 PM com.hazelcast.client.ClientEndpointManager
    INFO: [127.0.0.1]:5701 [dev] [3.10.4] Destroying ClientEndpoint{connection=Connection[id=2, /172.17.0.2:5701->/172.17.0.1:56514, endpoint=[172.17.0.1]:56514, alive=false, type=JAVA_CLIENT], principal='ClientPrincipal{uuid='d8a9b730-c5fd-458c-9ab6-671aece99305', ownerUuid='2fb66fa1-a17f-49fe-ba2b-bf585d43906d'}, ownerConnection=true, authenticated=true, clientVersion=3.10.4, creationTime=1536861657874, latest statistics=null}
    Sep 13, 2018 6:02:38 PM com.hazelcast.nio.tcp.TcpIpAcceptor
    INFO: [127.0.0.1]:5701 [dev] [3.10.4] Accepting socket connection from /172.17.0.1:56516
    Sep 13, 2018 6:02:38 PM com.hazelcast.nio.tcp.TcpIpConnectionManager
    INFO: [127.0.0.1]:5701 [dev] [3.10.4] Established socket connection between /172.17.0.2:5701 and /172.17.0.1:56516
    Sep 13, 2018 6:02:38 PM com.hazelcast.client.impl.protocol.task.AuthenticationMessageTask
    INFO: [127.0.0.1]:5701 [dev] [3.10.4] Received auth from Connection[id=3, /172.17.0.2:5701->/172.17.0.1:56516, endpoint=null, alive=true, type=JAVA_CLIENT], successfully authenticated, principal: ClientPrincipal{uuid='532bf500-e03e-4620-a9c2-14bb55c07166', ownerUuid='2fb66fa1-a17f-49fe-ba2b-bf585d43906d'}, owner connection: true, client version: 3.10.4
    Sep 13, 2018 6:03:11 PM com.hazelcast.transaction.TransactionManagerService
    INFO: [127.0.0.1]:5701 [dev] [3.10.4] Committing/rolling-back live transactions of client, UUID: d8a9b730-c5fd-458c-9ab6-671aece99305

Upon hitting the cache:

Sep 13, 2018 6:05:43 PM com.hazelcast.map.impl.operation.EntryOperation
SEVERE: [127.0.0.1]:5701 [dev] [3.10.4] java.lang.ClassNotFoundException: org.hibernate.cache.spi.entry.StandardCacheEntryImpl
com.hazelcast.nio.serialization.HazelcastSerializationException: java.lang.ClassNotFoundException: org.hibernate.cache.spi.entry.StandardCacheEntryImpl
    at com.hazelcast.internal.serialization.impl.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:86)
    at com.hazelcast.internal.serialization.impl.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:75)
    at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.read(StreamSerializerAdapter.java:48)
    at com.hazelcast.internal.serialization.impl.AbstractSerializationService.readObject(AbstractSerializationService.java:269)
    at com.hazelcast.internal.serialization.impl.ByteArrayObjectDataInput.readObject(ByteArrayObjectDataInput.java:574)
    at com.hazelcast.hibernate.serialization.Value.readData(Value.java:78)
    at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.readInternal(DataSerializableSerializer.java:160)
    at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.read(DataSerializableSerializer.java:106)
    at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.read(DataSerializableSerializer.java:51)
    at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.read(StreamSerializerAdapter.java:48)
    at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toObject(AbstractSerializationService.java:187)
    at com.hazelcast.query.impl.CachedQueryEntry.getValue(CachedQueryEntry.java:75)
    at com.hazelcast.hibernate.distributed.LockEntryProcessor.process(LockEntryProcessor.java:49)
    at com.hazelcast.hibernate.distributed.LockEntryProcessor.process(LockEntryProcessor.java:32)
    at com.hazelcast.map.impl.operation.EntryOperator.process(EntryOperator.java:319)
    at com.hazelcast.map.impl.operation.EntryOperator.operateOnKeyValueInternal(EntryOperator.java:182)
    at com.hazelcast.map.impl.operation.EntryOperator.operateOnKey(EntryOperator.java:167)
    at com.hazelcast.map.impl.operation.EntryOperation.runVanilla(EntryOperation.java:384)
    at com.hazelcast.map.impl.operation.EntryOperation.call(EntryOperation.java:188)
    at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.call(OperationRunnerImpl.java:202)
    at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:191)
    at com.hazelcast.spi.impl.operationexecutor.impl.OperationExecutorImpl.run(OperationExecutorImpl.java:406)
    at com.hazelcast.spi.impl.operationexecutor.impl.OperationExecutorImpl.runOrExecute(OperationExecutorImpl.java:433)
    at com.hazelcast.spi.impl.operationservice.impl.Invocation.doInvokeLocal(Invocation.java:581)
    at com.hazelcast.spi.impl.operationservice.impl.Invocation.doInvoke(Invocation.java:566)
    at com.hazelcast.spi.impl.operationservice.impl.Invocation.invoke0(Invocation.java:525)
    at com.hazelcast.spi.impl.operationservice.impl.Invocation.invoke(Invocation.java:215)
    at com.hazelcast.spi.impl.operationservice.impl.InvocationBuilderImpl.invoke(InvocationBuilderImpl.java:60)
    at com.hazelcast.client.impl.protocol.task.AbstractPartitionMessageTask.processMessage(AbstractPartitionMessageTask.java:67)
    at com.hazelcast.client.impl.protocol.task.AbstractMessageTask.initializeAndProcessMessage(AbstractMessageTask.java:123)
    at com.hazelcast.client.impl.protocol.task.AbstractMessageTask.doRun(AbstractMessageTask.java:111)
    at com.hazelcast.client.impl.protocol.task.AbstractMessageTask.run(AbstractMessageTask.java:101)
    at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:155)
    at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:125)
    at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.run(OperationThread.java:100)
Caused by: java.lang.ClassNotFoundException: org.hibernate.cache.spi.entry.StandardCacheEntryImpl
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at com.hazelcast.nio.ClassLoaderUtil.tryLoadClass(ClassLoaderUtil.java:173)
    at com.hazelcast.nio.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:147)
    at com.hazelcast.nio.IOUtil$ClassLoaderAwareObjectInputStream.resolveClass(IOUtil.java:615)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1866)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1749)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2040)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1571)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
    at com.hazelcast.internal.serialization.impl.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:82)
    ... 34 more

Do i need to include some kind of JAR inside my Hazelcast Docker setup, or what is happening here?

Jan Vladimir Mostert :

Finally got it working, here's what was needed:

1: Make sure you have all three these dependencies, initially i was missing the first one, but for some reason, wasn't getting a ClassNotFound exception as expected. It doesn't seem to be a transitive dependency of either hazelcast-client or hazelcast-hibernate52

    <dependency>
        <groupId>com.hazelcast</groupId>
        <artifactId>hazelcast</artifactId>
        <version>${hazelcast.version}</version>
    </dependency>
    <dependency>
        <groupId>com.hazelcast</groupId>
        <artifactId>hazelcast-hibernate52</artifactId>
        <version>${hazelcast-hibernate.version}</version>
    </dependency>
    <dependency>
        <groupId>com.hazelcast</groupId>
        <artifactId>hazelcast-client</artifactId>
        <version>${hazelcast.version}</version>
    </dependency>

2: If your dev instance of Hazelcast doesn't have a password, don't specify the password. 127.0.0.1 works fine, no need to run on an external server while dev-ing.

paramsDefault.add("hibernate.cache.use_query_cache=true")
paramsDefault.add("hibernate.cache.use_second_level_cache=true")
paramsDefault.add("hibernate.cache.region.factory_class=com.hazelcast.hibernate.HazelcastCacheRegionFactory")
paramsDefault.add("hibernate.cache.hazelcast.use_native_client=true")
paramsDefault.add("hibernate.cache.hazelcast.native_client_address=127.0.0.1")
//  paramsDefault.add("hibernate.cache.hazelcast.native_client_group=$ENV")
//  paramsDefault.add("hibernate.cache.hazelcast.native_client_password=dev-pass")

3: Get rid of hazelcast.xml - after removing that hazelcast.xml file, Hibernate actually started up even though my hazelcast.xml file just had a one-liner in it saying use default config.

4: Make sure all entities are marked with Serializable, otherwise entities won't cache and cause an exception on the Hazelcast server itself.

@Table
@Entity
@BatchSize(size = 50)
@PersistenceContext(unitName = "default")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "Tag")
class Tag(
    name: String,
) : Serializable {

5: If your entity has @OneToMany, @ManyToOne or other entities inside of it, make sure those entities are Serializable as well.

6: Write a little script to ensure that your entities are caching:

import com.hazelcast.client.HazelcastClient
import com.hazelcast.client.config.ClientConfig

fun main(args: Array<String>) {

    val config = ClientConfig()
    config.getNetworkConfig().addAddress("127.0.0.1:5701")
    val hazelcastInstance = HazelcastClient.newHazelcastClient(config)

    val map = hazelcastInstance.getMap<Any, Any>("Tag")

    println("=================")
    map.forEach { t, u ->
        println(" $t -> $u ")
    }
    println("=================")

    hazelcastInstance.shutdown()

}

The above script will println all Tag entities currently in the cache

7: When starting up the Docker instance, make sure you've exposed the port, without the -p option, nothing will work.

docker run --name=hazelcast -d=true -p 5701:5701 -e JAVA_OPTS="-Dhazelcast.local.publicAddress=127.0.0.1:5701" hazelcast/hazelcast:3.10.4

8: Check the Hazelcast logs to see if your Java / Kotlin client is connecting:

docker logs -f hazelcast

You should see something like this when there's a connection:

Sep 13, 2018 9:05:06 PM com.hazelcast.client.ClientEndpointManager
INFO: [127.0.0.1]:5701 [dev] [3.10.4] Destroying ClientEndpoint{connection=Connection[id=32, /172.17.0.2:5701->/172.17.0.1:56574, endpoint=[172.17.0.1]:56574, alive=false, type=JAVA_CLIENT], principal='ClientPrincipal{uuid='99cbf1b4-d11c-462d-bd87-4c069bc9b2ef', ownerUuid='2fb66fa1-a17f-49fe-ba2b-bf585d43906d'}, ownerConnection=true, authenticated=true, clientVersion=3.10.4, creationTime=1536872631771, latest statistics=null}
Sep 13, 2018 9:05:19 PM com.hazelcast.nio.tcp.TcpIpAcceptor
INFO: [127.0.0.1]:5701 [dev] [3.10.4] Accepting socket connection from /172.17.0.1:56576
Sep 13, 2018 9:05:19 PM com.hazelcast.nio.tcp.TcpIpConnectionManager
INFO: [127.0.0.1]:5701 [dev] [3.10.4] Established socket connection between /172.17.0.2:5701 and /172.17.0.1:56576
Sep 13, 2018 9:05:19 PM com.hazelcast.client.impl.protocol.task.AuthenticationMessageTask
INFO: [127.0.0.1]:5701 [dev] [3.10.4] Received auth from Connection[id=33, /172.17.0.2:5701->/172.17.0.1:56576, endpoint=null, alive=true, type=JAVA_CLIENT], successfully authenticated, principal: ClientPrincipal{uuid='ff51de39-fd9c-4ecf-bdd4-bbdb6ec6c79e', ownerUuid='2fb66fa1-a17f-49fe-ba2b-bf585d43906d'}, owner connection: true, client version: 3.10.4

These seems to be the crux of getting hazelcast hibernate working.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=108360&siteId=1
Recommended