Reputation: 1182
I am trying to update a big project that was using Infinispan 7 to the v10.1.3.
I would like to use the new protostream marshaller, but I don't understand how to be able to use UUID as cache key, or even (easier ?) as a field in a class that I want to insert in a cache.
My cache was accessed like that : Map<UUID, Foo> testUUIDAsKey = manager.getCache("t1");
Here when trying to put a value into the cache, infinispan tells me that he don't know how to marshal an uuid.
Ok, so after reading the documentation, I tryied to switch to a easier test case : Map<String, Bar> testUUIDAsField = manager.getCache("t2");
Here, the Bar class have a field of type UUID, and I tried to use the protostream annotation processor that will generated and build a proto file automatically when the right annotation are used.
But this time, the annotation processor tells me that UUID class must be instantiable using an accessible no-argument constructor.
I know that protobuf can't manage UUID, I can store the value as string or by storing the 2 long values part of an uuid.
How can I register a UUID marshaller that would use String as it representation in the end ?
And how can I tell the annotation processor that it must use this marshaller ?
Then, how can I use UUID as a key ?
Thanks.
Upvotes: 1
Views: 569
Reputation: 406
Currently Infinispan registers a Protostream marshaller for the UUID, but unfortunately it is only in the server. I have created ISPN-11426 to make it so that UUIDs will be marshallable out of the box in embedded mode in future releases (10.1.4.Final and 11.x).
In the mean time, you can get UUIDs to work as the key by creating a SerializationContextInitializer and defining a UUIDMarshaller
class:
public static class Initializer implements SerializationContextInitializer {
@Override
public String getProtoFileName() {
return "org.example.package.proto";
}
@Override
public String getProtoFile() throws UncheckedIOException {
return "package org.example.package;\n" +
"message UUID {\n" +
" optional string value = 1;\n" +
"}\n";
}
@Override
public void registerSchema(SerializationContext serCtx) {
serCtx.registerProtoFiles(org.infinispan.protostream.FileDescriptorSource.fromString(getProtoFileName(), getProtoFile()));
}
@Override
public void registerMarshallers(SerializationContext serCtx) {
serCtx.registerMarshaller(new UUIDMarshaller("org.example.package.UUID"));
}
}
import java.io.IOException;
import java.util.UUID;
import org.infinispan.protostream.MessageMarshaller;
public class UUIDMarshaller implements MessageMarshaller<UUID> {
private final String typeName;
/**
* @param typeName so that marshaller can be used in multiple contexts
*/
public UUIDMarshaller(String typeName) {
this.typeName = typeName;
}
@Override
public UUID readFrom(ProtoStreamReader reader) throws IOException {
return UUID.fromString(reader.readString("value"));
}
@Override
public void writeTo(ProtoStreamWriter writer, UUID uuid) throws IOException {
writer.writeString("value", uuid.toString());
}
@Override
public Class<? extends UUID> getJavaClass() {
return UUID.class;
}
@Override
public String getTypeName() {
return typeName;
}
}
You will need to update the org.example.package
to something relevant to your project.
The Initializer class can then be provided programmatically via:
new GlobalConfigurationBuilder().serialization().addContextInitializer(new Initializer());
Or via xml:
<serialization>
<context-initializer class="org.example.package.Initializer" />
</serialization>
Upvotes: 4