All Projects → joshlong → a-feign-like-rsocket-client

joshlong / a-feign-like-rsocket-client

Licence: Apache-2.0 license
@Mario5Gray had a great idea - a Feign for RSocket. So, here it is.

Programming Languages

java
68154 projects - #9 most used programming language

Projects that are alternatives of or similar to a-feign-like-rsocket-client

Rsocket Java
Java implementation of RSocket
Stars: ✭ 2,099 (+10395%)
Mutual labels:  reactive, rsocket
netifi-quickstart-java
Project to assist you in getting started using Netifi.
Stars: ✭ 23 (+15%)
Mutual labels:  reactive, rsocket
springboot-rsocketjwt-example
Example of using JWT with RSocket and Spring Boot
Stars: ✭ 26 (+30%)
Mutual labels:  reactive, rsocket
whatsup
Reactive framework, simple, fast, easy to use!
Stars: ✭ 115 (+475%)
Mutual labels:  reactive
reactive-search
Incremental search using React and RxJS
Stars: ✭ 15 (-25%)
Mutual labels:  reactive
FSRx
Parent repository to accompany session/workshop for Full Stack Reactive Java/Kotlin
Stars: ✭ 26 (+30%)
Mutual labels:  reactive
reacnetgenerator
an automatic reaction network generator for reactive molecular dynamics simulation
Stars: ✭ 25 (+25%)
Mutual labels:  reactive
ifunny
Решение для конкурса FunCode Java/Kotlin Challenge
Stars: ✭ 25 (+25%)
Mutual labels:  reactive
potassium
A framework for writing robot software with functional programming in Scala
Stars: ✭ 16 (-20%)
Mutual labels:  reactive
reactive-extensions
Extensions to the dotnet/reactive library.
Stars: ✭ 46 (+130%)
Mutual labels:  reactive
statechart
A rust implementation of statecharts: hierarchical, reactive state machines
Stars: ✭ 41 (+105%)
Mutual labels:  reactive
rxjava2-http
Transmit RxJava2 Flowable over http with non-blocking backpressure
Stars: ✭ 19 (-5%)
Mutual labels:  reactive
spring-boot-rsocket
Plain Spring Boot RSocket Starter
Stars: ✭ 26 (+30%)
Mutual labels:  rsocket
fpEs
Functional Programming for EcmaScript(Javascript)
Stars: ✭ 40 (+100%)
Mutual labels:  reactive
mono-reactive
open source Reactive Extensions (Rx) implementation for Mono
Stars: ✭ 65 (+225%)
Mutual labels:  reactive
vertx-codegen
Vert.x code generator for asynchronous polyglot APIs
Stars: ✭ 95 (+375%)
Mutual labels:  reactive
Bird
🐤 Bird is a lightweight HTTP networking library written in Swift. It is based on Apples new Reactive Framework Combine and focused on maintain- and extendability.
Stars: ✭ 17 (-15%)
Mutual labels:  reactive
immerx-state
Reactive, fractal and no-nonsense state management with Immer
Stars: ✭ 19 (-5%)
Mutual labels:  reactive
urx
urx is a stream-based Reactive state management library
Stars: ✭ 18 (-10%)
Mutual labels:  reactive
Reactive.XAF
DevExpress XAF extension framework. 𝗹𝗶𝗻𝗸𝗲𝗱𝗶𝗻.𝗲𝘅𝗽𝗮𝗻𝗱𝗳𝗿𝗮𝗺𝗲𝘄𝗼𝗿𝗸.𝗰𝗼𝗺, 𝘆𝗼𝘂𝘁𝘂𝗯𝗲.𝗲𝘅𝗽𝗮𝗻𝗱𝗳𝗿𝗮𝗺𝗲𝘄𝗼𝗿𝗸.𝗰𝗼𝗺 and 𝘁𝘄𝗶𝘁𝘁𝗲𝗿 @𝗲𝘅𝗽𝗮𝗻𝗱𝗳𝗿𝗮𝗺𝗲𝘄𝗼𝗿𝗸 and or simply 𝗦𝘁𝗮𝗿/𝘄𝗮𝘁𝗰𝗵 this repository and get notified from 𝗚𝗶𝘁𝗛𝘂𝗯
Stars: ✭ 60 (+200%)
Mutual labels:  reactive

A Feign-like RSocket Client

Inspiration

It'd be nice to have easy Feign-like RSocket clients. This is a thing @Mario5Gray has talked about, and it seems like a great idea. So here it is.

Installation

Add the following dependency to your build:

<dependency>
    <groupId>com.joshlong.rsocket</groupId>
    <artifactId>client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

In your Java code you need to enable the RSocket client support. Use the @EnableRSocketClient annotation. You'll also need to define an RSocketRequester bean.

@SpringBootApplication
@EnableRSocketClient
class RSocketClientApplication {
 
 @Bean RSocketRequester requester (RSocketRequester.Builder builder) {
  return builder.connectTcp("localhost", 8888).block();
 }
}

then, define an RSocket client interface, like this:

@RSocketClient
public interface GreetingClient {

	@MessageMapping("supplier")
	Mono<GreetingResponse> greet();

	@MessageMapping("request-response")
	Mono<GreetingResponse> requestResponse(Mono<String> name);

	@MessageMapping("fire-and-forget")
	Mono<Void> fireAndForget(Mono<String> name);

	@MessageMapping("destination.variables.and.payload.annotations.{name}.{age}")
	Mono<String> greetMonoNameDestinationVariable(
            @DestinationVariable("name") String name,
	    @DestinationVariable("age") int age, 
            @Payload Mono<String> payload);
}

If you invoke methods on this interface it'll in turn invoke endpoints using the configured RSocketRequester for you, turning destination variables into route variables and turning your payload into the data for the request.

Mapping Headers (RSocket metadata) to the RSocket request

You can map @Header elements to parameters in the method invocation. The header parameters get sent as composite RSocket metadata. Normal invocations of RSocket metadata would require two parts - a mime type and a value tht can be encoded. The encoding is a separate issue - Spring ships with a ton of encoders/decoders out of the box, but by default Spring Framework's built in support uses something called CBOR. There is still the question of how to communicate the mimetype. We expect the mime-type to be specified as the value() attribute for the @Header annotation. Thus:

import com.joshlong.rsocket.client.RSocketClient;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import reactor.core.publisher.Mono;

@RSocketClient
interface GreetingClient {

	@MessageMapping("greetings")
	Mono<String> greet(@Header( "messaging/x.bootiful.client-id") String clientId, @Payload Mono<String> name);

}

This needs to line up with the expectations for composite metadata on the responder side of course.

Pairing RSocketRequesters to @RSocketClient interfaces

You can annotate your interfaces with a @Qualifier annotation (or a meta-annotated qualifier of your own making ) and then annotate an RSocketRequester and this module will use that RSocketRequester when servicing methods on a particular interface.

The following demonstrates the concept in action. RSocket connections are stateful. Once they've connected, they stay connected and all subsequent interactions are assumed to be against the already established connection. Therefore, each RSocketRequester talks to a different logical (and physical) service, unlike, e.g., a WebClient which may be used to talk to any arbitrary host and port.

@RSocketClient
@Qualifier(Constants.QUALIFIER_2)
interface GreetingClient {

	@MessageMapping("greetings-with-name")
	Mono<Greeting> greet(Mono<String> name);

}

@RSocketClient
@PersonQualifier
interface PersonClient {

	@MessageMapping("people")
	Flux<Person> people();

}

@EnableRSocketClients
@SpringBootApplication
class RSocketClientConfiguration {

	@Bean
	@PersonQualifier // meta-annotation
	// @Qualifier(Constants.QUALIFIER_1)
	RSocketRequester one(@Value("${" + Constants.QUALIFIER_1 + ".port}") int port, RSocketRequester.Builder builder) {
		return builder.connectTcp("localhost", port).block();
	}

	
	@Bean 
	@Qualifier(Constants.QUALIFIER_2) // direct-annotation
	RSocketRequester two(@Value("${" + Constants.QUALIFIER_2 + ".port}") int port, RSocketRequester.Builder builder) {
		return builder.connectTcp("localhost", port).block();
	}

}

@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Qualifier(Constants.QUALIFIER_1)
@interface PersonQualifier {
}
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].