1

getting below error while using tuple based input output arguments on azure spring boot function..

[2021-08-19T10:22:51.771Z] Caused by: java.lang.UnsupportedOperationException: At the moment only Tuple-based function are supporting multiple arguments
[2021-08-19T10:22:51.776Z]      at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.parseMultipleValueArguments(SimpleFunctionRegistry.java:879)
[2021-08-19T10:22:51.778Z]      at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.convertMultipleOutputArgumentTypeIfNecesary(SimpleFunctionRegistry.java:1180)
[2021-08-19T10:22:51.780Z]      at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.convertOutputIfNecessary(SimpleFunctionRegistry.java:1012)
[2021-08-19T10:22:51.781Z]      at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.apply(SimpleFunctionRegistry.java:492)
[2021-08-19T10:22:51.784Z]      at org.springframework.cloud.function.adapter.azure.FunctionInvoker.handleRequest(FunctionInvoker.java:122)
[2021-08-19T10:22:51.785Z]      at com.att.trace.function.HelloHandler.execute(HelloHandler.java:49)
[2021-08-19T10:22:51.786Z]      ... 16 more

Sourcecode:

package com.att.trace.function;

import java.util.Optional;

import com.att.trace.function.model.User;
import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.HttpMethod;
import com.microsoft.azure.functions.HttpRequestMessage;
import com.microsoft.azure.functions.HttpResponseMessage;
import com.microsoft.azure.functions.HttpStatus;
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.HttpTrigger;

import org.springframework.cloud.function.adapter.azure.FunctionInvoker;

import reactor.util.function.Tuple2;
import reactor.util.function.Tuple3;
import reactor.util.function.Tuples;


public class HelloHandler extends FunctionInvoker<Tuple2<String, Integer>, Tuple3<String, Boolean, Integer>> {

        @FunctionName("hello")
        public HttpResponseMessage execute(@HttpTrigger(name = "request", methods = { HttpMethod.GET,
                        HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<User>> request,              
                        ExecutionContext context) {
               
                User user = request.getBody().filter((u -> u.getName() != null))
                                .orElseGet(() -> new User(request.getQueryParameters().getOrDefault("name", "world")));
                context.getLogger().info("Greeting user name: " + user.getName());

                Tuple2<String, Integer> base = Tuples.of("one", 1);
                
                Tuple3<String, Boolean, Integer> push_to = handleRequest(base, context);
                System.out.println("push_to=" + push_to);

                return request.createResponseBuilder(HttpStatus.OK).body("ok")
                                .header("Content-Type", "application/json").build();
        }
}

package com.att.trace.function;
import java.util.function.Function;
import org.springframework.stereotype.Component;
import reactor.util.function.Tuple2;
import reactor.util.function.Tuple3;
import reactor.util.function.Tuples;
@Component
public class Hello implements Function<Tuple2<String, Integer>, Tuple3<String, Boolean, Integer>>{
  private static Logger log = LoggerFactory.getLogger(Hello.class);
  public Tuple3<String, Boolean, Integer> apply(Tuple2<String, Integer> objects) {

    System.out.println("objects.getT1()=" + objects.getT1());
    System.out.println("objects.getT2()=" + objects.getT2());
    Tuple3<String, Boolean, Integer> output = Tuples.of("one",false,1);

    return output;
    // return mono.map(user -> new Greeting("Hello, " + user.getName() + "!\n"));

  }
}

fyi using below spring boot starter. looks like already using latest version

https://learn.microsoft.com/en-us/azure/developer/java/spring-framework/getting-started-with-spring-cloud-function-in-azure

1 Answers1

0

You are probably using Tuples from wrong namespace

public class HelloHandler extends FunctionInvoker<Tuple2<String, Integer>, Tuple3<String, Boolean, Integer>> {

Make sure that you use reactor.util.function.Tuple

The other thing not making sense to me is FunctionInvoker<Tuple2<String, Integer>, Tuple3<String, Boolean, Integer>> that in function invoker you saying that you expect Tuple2 but in your execution method you map User

execute(@HttpTrigger(name = "request", methods = { HttpMethod.GET,
                        HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<User>> request

They should match

Vova Bilyachat
  • 18,765
  • 4
  • 55
  • 80
  • thanks for checking.. I have below imports import reactor.util.function.Tuple2; import reactor.util.function.Tuple3; import reactor.util.function.Tuples; import looks ok? I only see above in visual studio code suggestions.. – Tarunkumar Aghara Aug 19 '21 at 12:54
  • 1
    thanks Vova for your inputs.. you're right. if I change it to `public class HelloHandler extends FunctionInvoker> Tuple3 push_to = handleRequest(request.getBody().get(), context); ..... public class Hello implements Function>.... public Tuple3 apply(User objects) ` it worked ok... I did not execute should match too – Tarunkumar Aghara Aug 19 '21 at 13:41
  • Great, I am actually in process to run it locally to debug and update my answer :) I am happy it helped you :) – Vova Bilyachat Aug 19 '21 at 13:43
  • thanks! follow up question though - how do I pass trigger and input binding both to handleRequest method at same time? e.g. `@HttpTrigger(name = "request", methods = { HttpMethod.GET, HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage user, @BlobInput(name = "jsonblob", dataType = "string", path = "json/{id}.json") String requestjson, Tuple2 input= Tuples.of(user, requestjson); handleRequest(input, context); ` ...above doesn't work – Tarunkumar Aghara Aug 20 '21 at 08:35
  • Create a new question pls i will have a look – Vova Bilyachat Aug 20 '21 at 09:10
  • new question posted: https://stackoverflow.com/questions/68860401/azure-spring-boot-function-how-to-pass-trigger-and-input-binding-both-to-handler – Tarunkumar Aghara Aug 20 '21 at 11:32