EhCache No serializer found
Asked Answered
D

3

7

I am initializing my cache in the following way:

CacheManager cacheManager;

cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build();
cacheManager.init();

Cache<String, SmsMessageDto> myCache = cacheManager.createCache("myCache", CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, SmsMessageDto.class)
    .withExpiry(Expirations.timeToLiveExpiration(new Duration(cacheDuration, TimeUnit.MINUTES)))
    .build());
    

Which gives me the following warning:

org.ehcache.core.EhcacheManager - Could not create serializers for myCache
org.ehcache.spi.serialization.UnsupportedTypeException: No serializer found for type 'com.example.dto.SmsMessageDto'
    at org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider$AbstractProvider.getClassFor(DefaultSerializationProvider.java:271) ~[ehcache-3.0.0.rc1.jar:3.0.0.rc1]
    at org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider$TransientProvider.createSerializer(DefaultSerializationProvider.java:149) ~[ehcache-3.0.0.rc1.jar:3.0.0.rc1]
    at org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider$AbstractProvider.createValueSerializer(DefaultSerializationProvider.java:239) ~[ehcache-3.0.0.rc1.jar:3.0.0.rc1]
    at org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider.createValueSerializer(DefaultSerializationProvider.java:96) ~[ehcache-3.0.0.rc1.jar:3.0.0.rc1]
    at org.ehcache.core.EhcacheManager.getStore(EhcacheManager.java:455) [ehcache-3.0.0.rc1.jar:3.0.0.rc1]
    at org.ehcache.core.EhcacheManager.createNewEhcache(EhcacheManager.java:308) [ehcache-3.0.0.rc1.jar:3.0.0.rc1]
    at org.ehcache.core.EhcacheManager.createCache(EhcacheManager.java:261) [ehcache-3.0.0.rc1.jar:3.0.0.rc1]
    at org.ehcache.core.EhcacheManager.createCache(EhcacheManager.java:240) [ehcache-3.0.0.rc1.jar:3.0.0.rc1]
    at at.xcard.helper.SmsFailedCache.init(SmsFailedCache.java:45) [classes/:na]
    at at.xcard.SmsWorker.<init>(SmsWorker.java:49) [classes/:na]
    at at.xcard.Main.main(Main.java:36) [classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_25]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_25]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_25]
    at java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0_25]
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) [idea_rt.jar:na]
            

How can I convince EhCache to use my toString method of the com.example.dto.SmsMessageDto object?

Disorient answered 26/9, 2016 at 13:9 Comment(0)
S
2

In short it is not possible. You have to implement Serializable interface in your class SmsMessageDto. It will create a serializer for your Serializable class and the Exception will not display again. This answer was based in the following link http://www.ehcache.org/documentation/3.1/serializers-copiers.html section Bundled implementations.

From the documentation:

By default, cache managers are pre-configured with specially optimized Serializer that can handle the following types, in the following order:

java.io.Serializable

java.lang.Long

java.lang.Integer

java.lang.Float

java.lang.Double

java.lang.Character

java.lang.String

byte[]

Spraddle answered 14/10, 2016 at 13:28 Comment(0)
V
0

Given that you are not using the offheap or disk tier, there is no requirement for a serializer.

Now I see you are using version 3.0.0.rc1. I would strongly recommend not using an RC at this point and instead use the latest (at this time) 3.1.2.

I believe what you are experiencing is a bug that has most likely been fixed since then.

Volnay answered 28/9, 2016 at 6:46 Comment(2)
I've tested this both with 3.1.2 and 3.1.3 and it is still happening unfortunately.Disorient
Could you then update your question with the new code you use to do that? and the matching stack trace. I will also do a more complete answer covering your options in Ehcache. For what it's worth, I did a test locally and cannot reproduce the problem.Volnay
M
0

How can I convince EhCache to use my toString method of the com.example.dto.SmsMessageDto object?

For my answer I'm going to assume that you don't actually want to do that. I'm assuming that you saw that stacktrace in the log files and assumed that something was wrong - but you would actually just like to cache the SmsMessageDto in its entirety, retrieve it from the cache in its entirety, and then just easily call #toString() in your application code - instead of cacheing a String and subsequently having to manually pass it to a new SmsMessageDto constructor.

The thing about that stacktrace that you posted is that it is on the DEBUG level and does not influence the cacheing of your object. I did not see the log level in your copy of the stacktrace so either you left it out for brevity, or your logger is not configured to log the log level.

Here is the stacktrace from my own project:

DEBUG org.ehcache.core.EhcacheManager - Could not create serializers for util.cache.ehcache.TestCacheObject org.ehcache.spi.serialization.UnsupportedTypeException: No serializer found for type 'java.lang.Object' at org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider.getSerializerClassFor(DefaultSerializationProvider.java:136) ~[ehcache-3.10.0.jar:3.10.0] at org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider.createSerializer(DefaultSerializationProvider.java:98) ~[ehcache-3.10.0.jar:3.10.0] at org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider.createValueSerializer(DefaultSerializationProvider.java:90) ~[ehcache-3.10.0.jar:3.10.0] at org.ehcache.core.EhcacheManager.getStore(EhcacheManager.java:464) ~[ehcache-3.10.0.jar:3.10.0] at org.ehcache.core.EhcacheManager.createNewEhcache(EhcacheManager.java:342) ~[ehcache-3.10.0.jar:3.10.0] at org.ehcache.core.EhcacheManager.createCache(EhcacheManager.java:274) ~[ehcache-3.10.0.jar:3.10.0] at org.ehcache.core.EhcacheManager.createCache(EhcacheManager.java:252) ~[ehcache-3.10.0.jar:3.10.0] at util.cache.ehcache.shared.AbstractEhCache.addCache(AbstractEhCache.java:132) ~[classes/:?]

You can just ignore DEBUG messages from that class (org.ehcache.core.EhcacheManager). Everything will still work fine. For example for Log4j2:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <!--
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
            -->
            <PatternLayout pattern="%-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="Console"/>
        </Root>

        <Logger name="org.ehcache.core.EhcacheManager" level="WARN" additivity="false">
            <AppenderRef ref="Console"/>
        </Logger>
    </Loggers>
</Configuration>

You were trying to create a cache - I just use values of Object.class and everything worked, because everything is an Object. My implementation is also a bit more thread-safe. You might also want to look at the thread-safety of creating the CacheManager. Well, I'm not sure how thread-safe the EhCache implementation is, I'm just playing it safe.

private Cache<String, Object> getCache(Class<?> cacheClazz) {
    Cache theCache = getCacheManager().getCache(cacheClazz.getName(), String.class, Object.class);
    if (theCache == null) {
        theCache = addCache(cacheClazz);
    }
    return theCache;
}

private Cache addCache(Class<?> cacheClazz) {
    String mapKey = getClass() + "-" + cacheClazz.getName();
    // Using intern() on the key as I want to synchronize on it.
    // (Strings with different hashCodes represent different locks)
    mapKey = mapKey.intern();

    if (firstRunMap.get(mapKey) == null) {
        synchronized (mapKey) {
            if (firstRunMap.get(mapKey) == null) { // has it been created by another thread, or am I the first
                Cache newCache = getCacheManager().createCache(
                        cacheClazz.getName(),
                        CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, Object.class, ResourcePoolsBuilder.heap(10))
                                .withExpiry(ExpiryPolicy.NO_EXPIRY)
                                .build()
                );

                firstRunMap.put(mapKey, "");

                return newCache;
            }
        }
    }

    // Not the first thread
    return getCache(cacheClazz);
}
private Map<String, String> firstRunMap = new ConcurrentHashMap<>();

Note: You called your cache "myCache". My cache names reflect the name of the class that I want to cache. The idea being that each class gets cached in its own cache, and that I can later view the statistics of each class\cache and see how efficient the cacheing for that object is based on the cache hit\miss ratios.

Mayfair answered 7/7, 2023 at 14:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.