hatenob

プログラムって分からないことだらけ

SpringBoot 2.2でRSocket

SpringBoot 2.2でRSocketを試してみました。

org.springframework.messaging.MessageDeliveryException: No handler for destination ''

というのが出て最初はうまく動かなかったのですが、何とか動きました。

動作確認環境

構成

ユーザからのリクエストを受け付けるRESTのエンドポイントがあり、バックエンドをRSocketで通信している風です。
clientという名前が分かりにくいですね。。

  [user]  -- http/rest --> [client] -- tcp/rsocket --> [server]

Server

ざっくりこんな感じです。

@Controller
public class GreetingRSocketController {
    @MessageMapping("hello")
    public Mono<GreetingData> hello(GreetingRequest request) {
        return Mono.just(new GreetingData("hello " + request.getWord()));
    }

    @MessageExceptionHandler
    public Mono<GreetingData> handleException(Exception e) {
        return Mono.just(GreetingData.fromException(e));
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class GreetingData {
    private String word;

    public static GreetingData fromException(Exception e) {
        return new GreetingData(e.getMessage());
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class GreetingRequest {
    private String word;
}

Client

こちらもざっくりと。
Serverと重複するGreetingDataとGreetingRequestは省略です。

@RestController
public class GreetingRestController {
    private final RSocketRequester requester;

    @Autowired
    public GreetingRestController(RSocketRequester requester) {
        this.requester = requester;
    }

    @GetMapping("/hello/{word}")
    public Publisher<GreetingData> current(@PathVariable("word") String word) {
        return requester.route("hello").data(new GreetingRequest(word)).retrieveMono(GreetingData.class);
    }
}

@Configuration
public class ClientConfiguration {
    @Bean
    public RSocket rsocket() {
        return RSocketFactory.connect()
                .dataMimeType(MimeTypeUtils.APPLICATION_JSON_VALUE)
                .metadataMimeType(WellKnownMimeType.MESSAGE_RSOCKET_ROUTING.getString())
                .frameDecoder(PayloadDecoder.ZERO_COPY)
                .transport(TcpClientTransport.create(7000))
                .start().block();
    }

    @Bean
    public RSocketRequester rsocketRequester(RSocketStrategies rsocketStrategies) {
        return RSocketRequester.wrap(rsocket(), MimeTypeUtils.APPLICATION_JSON,
                MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_ROUTING.getString()),
                rsocketStrategies);
    }
}

最初に書いた例外は、metaDataTimeTypeの設定不備によるものでした。