spring-cloud-function icon indicating copy to clipboard operation
spring-cloud-function copied to clipboard

CloudEvents examples to cover most use cases

Open salaboy opened this issue 3 years ago • 9 comments

Is your feature request related to a problem? Please describe. A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

When looking at the CloudEvents example here: https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-samples/function-sample-cloudevent/src/main/java/io/spring/cloudevent/DemoApplication.java

It will be great to have also the two following examples:

  1. Emitting a Cloud Event not from an incoming request (maybe using a timer)
  2. Receiving and event that doesn't return anything besides 200

Describe the solution you'd like A clear and concise description of what you want to happen.

These two examples added to: https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-samples/function-sample-cloudevent/src/main/java/io/spring/cloudevent/DemoApplication.java

  1. Emitting a Cloud Event not from an incoming request (maybe using a timer)
  2. Receiving and event that doesn't return anything besides 200

Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered.

I am happy to implement the examples if I get some validations from developers that this is a good idea

Additional context Add any other context or screenshots about the feature request here.

salaboy avatar Jan 02 '21 09:01 salaboy

@olegz I am just tagging you here because I saw your nickname all over the place in these examples, hence I thought you might be able to give me some input here.

salaboy avatar Jan 02 '21 09:01 salaboy

@olegz I might be also missing the example, but it will be great to have an example where a Message containing a CloudEvent can be serialized to JSON to be sent for example to a JS application using the CloudEvent SDK JS

salaboy avatar Jan 03 '21 10:01 salaboy

@salaboy Great suggestions and we'll do our best to act on it. Quick question though. . . I am not sure I follow the last suggestion. All of the examples provided are already JSON-based. There is also an example of JSON-based structured-mode CloudEvent (see the last sample explanation) where we're dealing with RSocket for which there are no protocol bindings (assuming that would be the same for JS). Any, please clarify

olegz avatar Jan 03 '21 17:01 olegz

@olegz thanks for answering.. I didn't got a notification by github for your comment.. hence 4 days without answering.. sorry about that.. My last comment was wrongly formulated.. Instead of saying JS I should have said WebSockets.. as I am dealing with WebSockets in a JS application, hence I am doing exactly the same thing as you are doing with RSocket.. so what I was missing was how to transform a CloudEvent object to the string version that you have in the last example that you pointed me out.

I finally made it like this:

  @PostMapping("/events")
    public Mono<CloudEvent> event(@RequestBody Mono<CloudEvent> body) {
        return body.map(
                event -> {
                    byte[]serialized = EventFormatProvider
                            .getInstance()
                            .resolveFormat(JsonFormat.CONTENT_TYPE)
                            .serialize(event);
                    // Sent to websocket here.. 
                    return event;
                });
    }

Having that example.. somewhere in the samples code will save people loads of time, as in the blog post there is just a string hardcoded..

salaboy avatar Jan 07 '21 08:01 salaboy

@salaboy, so I see that with CloudEvent you are using SDK. That's your choice, but looking at your code it appears to me that the whole serialization/deserialization is a non-functional concern and as such should be handled by the framework. I explicitly talk about it in these two blogs - part 1 and part 2.

So, don't you think it would be better to have something like this

@Bean("events")
public Function<Mono<byte[]>, Mono<byte[]>> processEvent() {
    return mono -> mono.doOnNext(event -> {
          // Sent to websocket here.. 
    });
}

. . . add spring-cloud-function-web to the classpath and off you go.

Given that you simply want an event in its raw form (byte[]) all you need to do is declare signature that reflects this and we'll take care of the rest. And of course if you are interested in the whole event then you can simply change the signature to public Function<Mono<Message<byte[]>>>, Mono<Message<byte[]>>> where you still get the actual 'data' as as payload, but also the Cloud Event attributes as message headers

olegz avatar Jan 07 '21 09:01 olegz

@olegz that is pretty useful yes.. is that byte[] representation going to conform with the JSON serialization of the CloudEvent or is it going to be the Message structure serialized? I will read more carefully your blog posts :)

salaboy avatar Jan 07 '21 09:01 salaboy

@salaboy The byte[] in the above case would represent the entire Cloud Event without modification (as it came from the wire).

Anyway, i guess it would be better if you formulate the actual business case. For example; I want to post User data. . . I want to do some things with it, and then I want to produce an Employee. Both incoming and outgoing requests must be Cloud Events This way it will be easier for us to understand what exactly you are trying to accomplish from the business perspective rather then how do you do this using this approach? where the actual 'approach' may not be the most efficient one. Knowing the actual use case will help not only to suggest a better approach but to also see if there are any improvements/enhancements that would need to be done within the framework.

olegz avatar Jan 07 '21 13:01 olegz

@olegz the use case is as follows:

  1. A cloud event is generated in Service A in the backend
  2. Another Service B (backend) catch the cloud event (using some kind of messaging layer, kafka)
  3. Service B needs to now forward the Cloud Event to a frontend via websockets, where the CloudEvent needs to be serialized so the CloudEvent JS SDK can parse it.

Service B is a spring boot service using the Cloud Events Message integration

salaboy avatar Jan 13 '21 10:01 salaboy

Ok, I am back after more than 1 year :) There are still things that I find complicated to do with Spring Cloud Functions and I would like to know how to proceed to see if I can explain what the use cases are or to see if I can contribute with the solutions if someone from the team helps me to find them.

salaboy avatar Feb 02 '22 16:02 salaboy

These should really come from the community that is using it. We've provided 4 samples covering all of the ways we support CE (natively via message and SDK). There is not much else we can provide other then revise and accept samples from the community that is actively using cloud events.

olegz avatar Nov 14 '22 15:11 olegz