-
Notifications
You must be signed in to change notification settings - Fork 167
[WIP] Allow POJOs as CloudEvent data, round 3 #211
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
Closed
slinkydeveloper
wants to merge
2
commits into
cloudevents:master
from
slinkydeveloper:third_iteration_196
Closed
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
29 changes: 29 additions & 0 deletions
29
core/src/main/java/io/cloudevents/core/codec/DataSerializationException.java
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| /* | ||
| * Copyright 2018-Present The CloudEvents Authors | ||
| * <p> | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * <p> | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * <p> | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| * | ||
| */ | ||
|
|
||
| package io.cloudevents.core.codec; | ||
|
|
||
| import io.cloudevents.core.format.EventFormat; | ||
|
|
||
| /** | ||
| * Exception representing a serialization error while using an {@link EventFormat}. | ||
| */ | ||
| public class DataSerializationException extends RuntimeException { | ||
| public DataSerializationException(Throwable e) { | ||
| super(e); | ||
| } | ||
| } |
31 changes: 31 additions & 0 deletions
31
core/src/main/java/io/cloudevents/core/codec/EventDataCodec.java
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| package io.cloudevents.core.codec; | ||
|
|
||
| import io.cloudevents.CloudEvent; | ||
| import io.cloudevents.core.format.EventSerializationException; | ||
| import io.cloudevents.lang.Nullable; | ||
|
|
||
| import javax.annotation.ParametersAreNonnullByDefault; | ||
|
|
||
| /** | ||
| * This interface represents how to encode an event data to bytes, in order to write the payload on the wire. | ||
| */ | ||
| @ParametersAreNonnullByDefault | ||
| public interface EventDataCodec { | ||
|
|
||
| /** | ||
| * Serialize a {@link CloudEvent} to a byte array. | ||
| * | ||
| * @param data the data to serialize. | ||
| * @return the byte representation of the provided event. | ||
| * @throws EventSerializationException if something goes wrong during serialization. | ||
| * @throws IllegalArgumentException if this codec cannot serialize the provided data | ||
| */ | ||
| byte[] serialize(@Nullable String dataContentType, Object data) throws DataSerializationException, IllegalArgumentException; | ||
|
|
||
| /** | ||
| * @param dataContentType the eventual content type to serialize | ||
| * @return true if this event codec instance can serialize the provided content type. | ||
| */ | ||
| boolean canSerialize(@Nullable String dataContentType); | ||
|
|
||
| } |
20 changes: 20 additions & 0 deletions
20
core/src/main/java/io/cloudevents/core/codec/impl/TextEventDataCodec.java
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package io.cloudevents.core.codec.impl; | ||
|
|
||
| import io.cloudevents.core.codec.DataSerializationException; | ||
| import io.cloudevents.core.codec.EventDataCodec; | ||
|
|
||
| public class TextEventDataCodec implements EventDataCodec { | ||
| @Override | ||
| public byte[] serialize(String dataContentType, Object data) throws DataSerializationException, IllegalArgumentException { | ||
| try { | ||
| return data.toString().getBytes(); | ||
| } catch (Throwable e) { | ||
| throw new DataSerializationException(e); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public boolean canSerialize(String dataContentType) { | ||
| return "text/plain".equals(dataContentType); | ||
| } | ||
| } |
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would make me abandon the SDK altogether and introduce my own type. A strong no (-1).
Motivation:
Currently, one does not need
coreto serialize an instance ofCloudEvent. If you change it toObject, it would mean that one will have to do something like:This is very JS-style plus makes the whole point of the
apimodule obsolete.It is "fine"-ish if
getDatawill returnDatatype that gives methods likeasBytes,asByteBuffer, or a custom type that will let accessing the original object, but making itObjectis a no go IMO.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok ok i'm interested in exploring the
Dataalternative, what about (names are provisional):There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to understand your idea, what should it look like the
Datainterface for you?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
few things to keep in mind:
Some implementations that care about the performance may want to implement
Dataon the same class that implements theCloudEventtype, so the method names should be carefully selected to not clash or confuse.This can as well be a set of methods of
CloudEventlikedataAsBytes(),dataAsByteBuffer(), etc etc. not genericdataAs(Class)tho.before we make 5 more rounds of PRs, I would like to step back and ask the question that was already asked:
Why do we even need to expose "raw" object access in
CloudEventon a first place? What are we trying to solve?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so i wonder if
dataAsBytes()anddataAsObject()just solves the problem we have here (I still prefer to have a sub interface and then I implement it in the same class of the cloudevent impl).[WIP] Allow POJOs as CloudEvent data #198 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dataAsObject()would require doing a mandatoryinstanceofcheck on the value to proceed with processing. You can't even use it in the JSON format to encode the body because it may returnbyte[]of already seriallized payload. You must have a concrete type to hint the serializer to use some other field other thandataAsBytes().How is it better than doing an
instanceofcheck on theCloudEventitself?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can and the implementation is pretty straightforward (look at the code here https://github.com/cloudevents/sdk-java/pull/211/files#diff-75b992e6fc5d4cd3890ea6e37c7fe2a4R114)
WDYM? Every serializer just use
val.getClass()to start the serialization.Of course you always need the
instanceof, but makes simpler the usage and the impl:CloudEventprovided by coreinstanceofCloudEvent. We can't build in this sdk all the differentJsonCloudEvent,XmlCloudEventbecause data can be anything...CloudEventdata, the builders/deserializers don't need to return different impls of the event depending on the payload, they always use the sameCloudEventV1andCloudEventV03My feeling about subclassing
CloudEventdepending on the type of data is that you're making the wrong thing "dynamic", while theDataidea makes more sense to me because is exactly thedatafield the dynamic one. It's another layer of indirection, but makes more explicit the conceptThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not a "straightforward implementation", this is
if {} else {}for a single case (byte[]) while it may also beByteBuffer,InputStream, or many other possibilities.dataAsBytes/dataAsByteBufferdo provide a straightforward way of handling the case.Then added it to
core. I only care aboutapihere.this is a wrong assumption because, in a pipeline, you will get instances of
CloudEvent, notSomeCloudEvent, wheregetData()will beObject, not the concrete type. That's how Java's type system works.This does not mean that the SDK should be dynamic tho.
That's not what I suggested. Please re-read.
Your perception is incorrect. I am saying that, if someone wants to apply an optimization, they can subclass and expose the raw object. Just re-read the original issue ( #196 ), the problem was in "double encoding".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's the very same thing i have to do with subclassing CloudEvent. Also, keep in mind that i cannot write directly byte[] into a jackson serializer, i need or a json type or a pojo to map to json (look at the diff).
I know, but the users of this sdk ends up using the interface
CloudEventinapi, hence I care to have well aligned interface and impls for 90% of users without letting them downcast because the 10% thinks data is not a dynamic field and we can "statically type it". Just look at the spec of CloudEvents https://github.com/cloudevents/spec/blob/v1.0/spec.md#event-data and you clearly see that "This specification does not place any restriction on the type of this information", hence what is the point of trying to make it look static with subclasses and whatnot?I'm not talking only about optimizations, I'm talking about the fact that if the user is allowed to put pojos inside the event (eg using the event builder providing a non byte array parameter), she/he expects to be able to get it back with a getter, like
getDataAsObject().And as I said, I see no point for the user of the sdk to do
Object data = ((BaseCloudEventImpl)event).getRawData()where they build withbuilder.withData(pojo). That makes the usage unnecessary awful...There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With
byte[], you don't need Jackson at all, you have the bytes already. It is up to the implementation to decide how to returnbyte[]. That's the whole point.