Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Making ProtoStreamMarshaller default marshaller and adding #807

Merged
merged 1 commit into from
Feb 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 76 additions & 59 deletions docs/src/main/asciidoc/infinispan-client-guide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -45,51 +45,50 @@ can be configured in this file:

|===

== Marshalling (Key Value types support)
== Serialization (Key Value types support)

By default the client will only support keys and values of the type byte[]. This can be configured
through the `hotrod-client.properties` file mentioned above through the `infinispan.client.hotrod.marshaller`
property. You can either supply your own marshaller implementation or use the `ProtoStreamMarshaller` as described
in the user guide linked above.
By default the client will support keys and values of the following types: byte[],
primitive wrappers (eg. Integer, Long, Double etc.), String, Date and Instant. User types require
some additional steps that are detailed here. Let's say we have the following user classes:

The recommended approach is to use `ProtoStreamMarshaller` as this provides support for String,
boxed primitives (Long, Integer etc.) and byte[] types with no additional work. Also using this
marshaller allows for indexed and non indexed querying, which can be useful.

=== ProtoStream Marshaller
.Author.java
----
public class Author {
private final String name;
private final String surname;
Infinispan provides an optional module that can be used to provide protostream, a protobuf based, marshaller
for clients. To enable proto stream marshaller you must add the `infinispan-remote-query-client` module
to your project manually. This can be done as shown here:
public Author(String name, String surname) {
this.name = Objects.requireNonNull(name);
this.surname = Objects.requireNonNull(surname);
}
// Getter/Setter/equals/hashCode/toString ommitted
}
----

[source,xml]
.Book.java
----
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-remote-query-client</artifactId>
<exclusions>
<exclusion>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
public class Book {
private final String title;
private final String description;
private final int publicationYear;
private final Set<Author> authors;
public Book(String title, String description, int publicationYear, Set<Author> authors) {
this.title = Objects.requireNonNull(title);
this.description = Objects.requireNonNull(description);
this.publicationYear = publicationYear;
this.authors = Objects.requireNonNull(authors);
}
// Getter/Setter/equals/hashCode/toString ommitted
}
----

Note that you must exclude `jboss-logging` as this module is currently not supported with {project-name}.

Then you must configure the marshaller in your `hotrod-client.properties` file.
The default serialization is done using a library based on protobuf. We need to define the proto
buf schema and a marshaller for each user type(s).

[source]
infinispan.client.hotrod.marshaller=org.infinispan.client.hotrod.marshall.ProtoStreamMarshaller

Doing this allows you to use byte[], primitive wrappers (eg. Integer, Long, Double etc.),
String, Date and Instant class instances in your cache immediately.

==== User Types

Once the `ProtoStreamMarshaller` is configured we can now start adding in our own custom user types
for serialization. This requires two steps: defining proto buf schema for the type(s) and a marshaller(s).
NOTE: Annotation based proto stream marshalling is not yet supported in
the {project-name} Infinispan client. This will be added soon, allowing you to only annotate your classes,
skipping the following steps.

Protobuf schema:: You can supply a protobuf schema through either one of two ways.
. Proto File
Expand Down Expand Up @@ -144,7 +143,7 @@ The last thing to do is to provide a `org.infinispan.protostream.MessageMarshall
for each user class defined in the proto schema. This class is then provided via `@Produces` in a similar
fashion to the code based proto schema definition above.
+
Here is the Marshaller class for our Author class.
Here is the Marshaller class for our Author & Book classes.
+
NOTE: The type name must match the `<protobuf package>.<protobuf message>` exactly!
+
Expand Down Expand Up @@ -177,6 +176,39 @@ public class AuthorMarshaller implements MessageMarshaller<Author> {
}
----
+
.BookMarshaller.java
----
public class BookMarshaller implements MessageMarshaller<Book> {
@Override
public String getTypeName() {
return "book_sample.Book";
}
@Override
public Class<? extends Book> getJavaClass() {
return Book.class;
}
@Override
public void writeTo(ProtoStreamWriter writer, Book book) throws IOException {
writer.writeString("title", book.getTitle());
writer.writeString("description", book.getDescription());
writer.writeInt("publicationYear", book.getPublicationYear());
writer.writeCollection("authors", book.getAuthors(), Author.class);
}
@Override
public Book readFrom(ProtoStreamReader reader) throws IOException {
String title = reader.readString("title");
String description = reader.readString("description");
int publicationYear = reader.readInt("publicationYear");
Set<Author> authors = reader.readCollection("authors", new HashSet<>(), Author.class);
return new Book(title, description, publicationYear, authors);
}
}
----
+
And you pass the marshaller by defining the following:
+
[source,java]
Expand All @@ -185,29 +217,14 @@ And you pass the marshaller by defining the following:
MessageMarshaller authorMarshaller() {
return new AuthorMarshaller();
}
----

NOTE: Annotation based proto stream marshalling is not yet supported in
the {project-name} infinispan client.

=== Providing your own Marshaller

You can implement the `org.infinispan.commons.marshaller.Marshaller` interface. This will allow you
to put keys and values of the types it supports directly with the client. All that is required is to have your
class available in classpath and configure the property value to be the fully qualified class name. This
method does not require any optional dependencies.

It is recommended to extend from the `org.infinispan.commons.marshall.AbstractMarshaller` class to reduce
the lines of the class. Here is an example of a Marshaller implementation for String instances.
With that class in your project/classpath, all you need to do is add the following to your
hotrod-client.properties as mentioned above.

[source]
infinispan.client.hotrod.marshaller=com.example.MyMarshaller
@Produces
MessageMarshaller bookMarshaller() {
return new BookMarshaller();
}
----

Note that the Marshaller implementation must have a no arg constructor or static factory method named
`getInstance`.
Now you can add entries into the cache of the types defi

== Dependency Injection

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.infinispan.client.hotrod.impl.ConfigurationProperties;
import org.infinispan.client.hotrod.logging.Log;
import org.infinispan.client.hotrod.logging.LogFactory;
import org.infinispan.client.hotrod.marshall.ProtoStreamMarshaller;
import org.infinispan.commons.util.Util;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget;
Expand Down Expand Up @@ -98,9 +99,10 @@ PropertiesBuildItem setup(ApplicationArchivesBuildItem applicationArchivesBuildI
reflectiveClass.produce(new ReflectiveClassBuildItem(false, false, "com.github.benmanes.caffeine.cache.PSMS"));
}

// This is always non null
Object marshaller = properties.get(ConfigurationProperties.MARSHALLER);

if (InfinispanClientProducer.isProtoBufAvailable(marshaller)) {
if (marshaller instanceof ProtoStreamMarshaller) {
ApplicationArchive applicationArchive = applicationArchivesBuildItem.getRootArchive();
// If we have properties file we may have to care about
Path metaPath = applicationArchive.getChildPath(META_INF);
Expand All @@ -123,7 +125,7 @@ PropertiesBuildItem setup(ApplicationArchivesBuildItem applicationArchivesBuildI
new String(bytes));
}

InfinispanClientProducer.handleQueryRequirements(properties);
InfinispanClientProducer.handleProtoStreamRequirements(properties);
}
}

Expand Down
1 change: 0 additions & 1 deletion extensions/infinispan-client/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-remote-query-client</artifactId>
<optional>true</optional>
</dependency>

<dependency>
Expand Down

This file was deleted.

Loading