0

Here is the piece of code I have

MyValue sampleValue = Values.newHeapInstance(MyValue.class); 

// subsequently set the couple of floats and int i have defined in MyValue interface

ChronicleMap<MyKey, MyValue> cache = ChronicleMapBuilder.of(MyKey.class, MyValue.class)
                .entries(100)
                .averageValue(sampleValue)
                .create();

When I do this I get the error

java.lang.IllegalArgumentException: Using BytesMarshallable and an interface value type not supported at net.openhft.chronicle.map.ChronicleMapBuilder.averageValue(ChronicleMapBuilder.java:660)

Can someone help me understand if this usage pattern is in-correct?

If I change to creating MyValue by implementing a concrete class and then doing a new on that as follows it works:

MyValue sampleValue = new MyValueImpl();

// subsequently set the couple of floats and int i have defined in MyValue interface

ChronicleMap<MyKey, MyValue> cache = ChronicleMapBuilder.of(MyKey.class, MyValue.class)
                .entries(100)
                .averageValue(sampleValue)
                .create();
Rajesh Pandya
  • 1,540
  • 4
  • 18
  • 31

2 Answers2

0

The reason for this exception can be found in the source:

            if (Serializable.class.isAssignableFrom(valueClass))
                LOG.warn("BytesMarshallable " + valueClass + " will be serialized as Serializable as the value class is an interface");
            else
                throw new IllegalArgumentException("Using BytesMarshallable and an interface value type not supported");
}

Which simply calls the isAssignableFrom method of the class Class which checks:

Determines if the class or interface represented by this Class object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specified Class parameter. It returns true if so; otherwise it returns false. If this Class object represents a primitive type, this method returns true if the specified Class parameter is exactly this Class object; otherwise it returns false.

So this checks if the Serializable Class is represented by the valueClass. So my understanding is that your MyValue isn't implementing the Serializable interface.

And yeah, even the comment states it:

Configures the average number of bytes, taken by serialized form of values

So If I'm not mistaken, simply let your Value Class implement the Serializable interface and you should be fine. Pretty ... confusing exception message I'd say.

maio290
  • 6,440
  • 1
  • 21
  • 38
0

Use of Values.newHeapInstance() suggests that MyValue is a so-called value interface. Objects of a specific value interface have constant size in serialized form. Value interfaces are supported by ChronicleMap specially, so you shouldn't configure value size at all, as presented in this example from tutorial:

ChronicleMap<LongValue, Order> orders = ChronicleMap
    .of(LongValue.class, Order.class)
    .name("orders-map")
    .entries(1_000_000)
    .create();

LongValue key = Values.newHeapInstance(LongValue.class);
key.setValue(id);
orders.put(key, order);

Note that there is no averageValue() call, nor averageValueSize(), nor constantValueSizeBySample().

The presented error message is indeed confusing, especially since ChronicleMap already knows that value class is a value interface and knows it's size. Feel free to open an issue in https://github.com/OpenHFT/Chronicle-Map.

leventov
  • 14,760
  • 11
  • 69
  • 98