John Varghese
John Varghese

Reputation: 23

Subscriber context not found in doOnError

I was wondering if someone could eyeball the following code snippet and tell me why the SubscriberContext inside the doOnError is not trigerred

public Mono<ServerResponse> handlePlatformAuthenticationResponse(final ServerRequest serverRequest) {
    Mono<MultiValueMap<String, String>> formData = serverRequest.body(BodyExtractors.toFormData());
        return formData
            .flatMap(this::provisionUserAndClass)
            .flatMap(tuple -> Mono.subscriberContext()
                .map(context -> {
                    // this is invoked if provisionUserAndClass completes successfully
                    TelemetryData telemetryData = context.get(TELEMETRY_DATA);
                    LTILaunchRequest<LTILaunchRequestSettings> launchRequest = tuple.getT2();
                    this.addLaunchDetailsToTelemetryContext(launchRequest, telemetryData);
                    return tuple;
                }))
             .doOnError(error -> Mono.subscriberContext()
                    .map(context -> {
                    // this is never invoked if provisionUserAndClass returns a Mono.error
                     TelemetryData telemetryData = context.get(TELEMETRY_DATA);
                     // log telemetryData + error message
                    }))
             .subscriberContext(context -> context.put(TELEMETRY_DATA, new TelemetryData()));
    }

    private Mono<Tuple2<ClassAndUserProvisioningResponse, LTILaunchRequest<LTILaunchRequestSettings>>> provisionUserAndClass(
            LTILaunchRequest<LTILaunchRequestSettings> ltiLaunchRequest) {
        // returning a Mono.error just to see behavior of Mono.subscriberContext() when error occurs. Actual code will call a service method
        return Mono.error(new ProvisioningException("fake")); 
    }

Upvotes: 1

Views: 965

Answers (2)

Prashant Pandey
Prashant Pandey

Reputation: 4642

.doOnError(error -> Mono.subscriberContext()
                    .map(context -> {
                    // this is never invoked if provisionUserAndClass returns a Mono.error
                     TelemetryData telemetryData = context.get(TELEMETRY_DATA);
                     // log telemetryData + error message
                    }).subscribe())

You forgot to subscribe to the Mono.subscriberContext().

Upvotes: 0

Martin Tarj&#225;nyi
Martin Tarj&#225;nyi

Reputation: 9987

To access context in case of error you could use doOnEach operator:

 .doOnEach(signal -> {
     if (signal.isOnError())
     {
         TelemetryData telemetryData = signal.getContext().get(TELEMETRY_DATA);
         Throwable error = signal.getThrowable();
         // ...
     }
 })

Mono.subscriberContext() can only be used meaningfully in operators where you have to return a Mono, like flatMap, concatMap, etc, but not in side-effect operators where there is nothing that would subscribe to the Mono<Context>.

Upvotes: 1

Related Questions