The following is a common question amongst Infinispan community users:
The simplest way is to take advantage Infinispan Protostream annotations to mark your objects queryable and decide how each object field should be indexed. Example:
Then, the ProtoSchemaBuilder can inspect the annotated class and derive a Google Protocol Buffers schema file from it. Example:
Finally, the schema file needs to be registered in the “___protobuf_metadata” cache:
Although this is by far the easiest way to make your Java objects queryable, this method might not always be viable. For example, you might not be able to modify the Java object classes to add the annotations. For such use cases, a more verbose method is available that does not require modifying the source code of the Java object.
For example, given this Java object:
A Protocol Buffers schema must be defined where comments are used to define the object as queryable and decide how each field is indexed:
This method also requires a Protostream message marshaller to be defined which specifies how each field is serialized/deserialized:
This method still requires the Protocol Buffers schema to be registered remotely, but on top of that, the schema and marshaller need to be registered in the client:
Clearly, this second method is a lot more verbose and more laborious when refactoring. If any changes are made to the Java object, the marshaller and Protocol Buffer schema need to also be changed accordingly. This is done automatically in the first method.
Both methods are demonstrated in full in the queryable-pojos demo.
Cheers
Galder
How do I make my Java objects queryable by remote clients?
Annotation Method
The simplest way is to take advantage Infinispan Protostream annotations to mark your objects queryable and decide how each object field should be indexed. Example:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.infinispan.protostream.annotations.ProtoDoc; | |
import org.infinispan.protostream.annotations.ProtoField; | |
@ProtoDoc("@Indexed") | |
public class Pokemon { | |
@ProtoDoc("@Field") | |
@ProtoField(number = 10) | |
String name; | |
@ProtoDoc("@Field") | |
@ProtoField(number = 20) | |
String type1; | |
… | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
RemoteCacheManager remote = … | |
SerializationContext serialCtx = | |
ProtoStreamMarshaller.getSerializationContext(remote); | |
ProtoSchemaBuilder protoSchemaBuilder = new ProtoSchemaBuilder(); | |
String protoFile = protoSchemaBuilder | |
.fileName(fileName) | |
.addClass(Pokemon.class) | |
.packageName("pokemons") | |
.build(serialCtx); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
RemoteCache<String, String> metadataCache = | |
remote.getCache(PROTOBUF_METADATA_CACHE_NAME); | |
metadataCache.put(fileName, protoFile); | |
String filesWithErrors = metadataCache.get(ERRORS_KEY_SUFFIX); | |
if (filesWithErrors != null) | |
throw new AssertionError("Error in proto file(s): " + filesWithErrors); | |
else | |
System.out.println("Added schema file: " + fileName); |
Plain Object Method
For example, given this Java object:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CryptoCurrency { | |
public final String description; | |
public final Integer rank; | |
.... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package crypto; | |
/** | |
* @Indexed | |
*/ | |
message CryptoCurrency { | |
/** | |
* @Field | |
*/ | |
required string description = 10; | |
/** | |
* @Field | |
*/ | |
required uint32 rank = 20; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.infinispan.protostream.MessageMarshaller; | |
public class CryptoCurrencyMarshaller implements MessageMarshaller<CryptoCurrency> { | |
@Override | |
public CryptoCurrency readFrom(ProtoStreamReader reader) throws IOException { | |
String description = reader.readString("description"); | |
Integer rank = reader.readInt("rank"); | |
return new CryptoCurrency(description, rank); | |
} | |
@Override | |
public void writeTo(ProtoStreamWriter writer, CryptoCurrency obj) throws IOException { | |
writer.writeString("description", obj.description); | |
writer.writeInt("rank", obj.rank); | |
} | |
... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SerializationContext serialCtx = ... | |
String protoFile = read(CryptoCurrency.class.getResourceAsStream("/crypto.proto")); | |
metadataCache.put("crypto.proto", protoFile); | |
... | |
serialCtx.registerProtoFiles(FileDescriptorSource.fromResources("/crypto.proto")); | |
serialCtx.registerMarshaller(new CryptoCurrencyMarshaller()); |
Both methods are demonstrated in full in the queryable-pojos demo.
Cheers
Galder