How can I use an object from a lambda expression in a different lambda expression

Viewed 153

I have this code

service.confirm(identity, id)
                .map(confirmationResponse -> InternalToExternalResponse.mapToExternal(confirmationResponse))
                .map(externalResponse->uriBuilder.buildAuthorizeUri(externalResponse))
                .lift(auditOperatorFactory.logRequestURI(identity, AuditCategory.BOOKKEEP));

Now i need to extend the uriBuilder.buildAuthorizeUri(externalResponse) to take confirmationResponse as a second parameter

Can I use the confirmationResponse from the first lambda expression inside the second lambda expression? the final code should be like

service.confirm(identity, id)
                .map(confirmationResponse -> InternalToExternalResponse.mapToExternal(confirmationResponse))
                .map(externalResponse-**>uriBuilder.buildAuthorizeUri(externalResponse,confirmationResponse ))**
                .lift(auditOperatorFactory.logRequestURI(identity, AuditCategory.BOOKKEEP));
4 Answers

You can combine the two lambda expressions:

service.confirm(identity, id)
                .map(confirmationResponse -> {
                    ExternalResponse externalResponse = InternalToExternalResponse.mapToExternal(confirmationResponse);
                    return uriBuilder.buildAuthorizeUri(externalResponse,confirmationResponse);})
                .lift(auditOperatorFactory.logRequestURI(identity, AuditCategory.BOOKKEEP));

I'd suggest using shorter lambda variable names, though:

service.confirm(identity, id)
                .map(cr -> {
                    ExternalResponse er = InternalToExternalResponse.mapToExternal(cr);
                    return uriBuilder.buildAuthorizeUri(er,cr);})
                .lift(auditOperatorFactory.logRequestURI(identity, AuditCategory.BOOKKEEP));

Why not merge into a single lambda?

service.confirm(identity, id)
       .map(confirmationResponse -> uriBuilder.buildAuthorizeUri(InternalToExternalResponse.mapToExternal(confirmationResponse), confirmationResponse))
       .lift(...)

You can pass the confirmationResponse to the next lambda as the result of this one. Since you need both, you can either create a custom object or use Pair like this:

service.confirm(identity, id)
                .map(confirmationResponse -> new Pair<ConfirmationResponse, ExternalResponse>(confirmationResponse, InternalToExternalResponse.mapToExternal(confirmationResponse)))
                .map(result ->u riBuilder.buildAuthorizeUri(result.second, result.first ))
                .lift(auditOperatorFactory.logRequestURI(identity, AuditCategory.BOOKKEEP));

No, you can't use the confirmationResponse in the second lambda. That would break the functional pattern.

You can include it in the first lambda's result, though. Just create youself a utility class like Pair:

service.confirm(identity, id)
       .map(confirmationResponse -> Pair.of(
           InternalToExternalResponse.mapToExternal(confirmationResponse), 
           confirmationResponse))
       .map(p -> uriBuilder.buildAuthorizeUri(p.getFirst(), p.getSecond())
       ...

I am not sure though, if that's good style here.

Related