-1

I have a lambda function which has a handler which inturn has multiple routers. Each router corresponds to an API.

I have created a lambda client in java and need to call those APIs. To call these APIs, I need to invoke the handler and pass a payload to the client along with it. Can you guys help me with the syntax for invoking the handler and passing the payload.

3
  • What issues are you having with a search? I found this article that uses a simple annotation to help and this answer in S/O. Commented Oct 25, 2019 at 19:29
  • Before posting the question, I had followed S/O link you shared. What I need help with is how do I pass the payload. If I want to call a get API which takes a string as an input, how do i structure it as payload and pass it to the handler. Commented Oct 25, 2019 at 19:51
  • The link indicates that you just convert your JSON to a String and send it. Commented Oct 25, 2019 at 20:07

1 Answer 1

0

If I understand your question correctly I first created a Lambda that looked like:

public class SampleHandler implements RequestStreamHandler {
    private static final Logger logger = LogManager.getLogger(SampleHandler.class);

    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
        logger.info("handlingRequest");
        LambdaLogger lambdaLogger = context.getLogger();

        ObjectMapper objectMapper = new ObjectMapper();
        String inputString = new BufferedReader(new InputStreamReader(inputStream)).lines().collect(Collectors.joining("\n"));
        JsonNode jsonNode = objectMapper.readTree(inputString);

        String route = jsonNode.get("route").asText();

        RouterResult routerResult = new RouterResult();

        switch( route ) {
            case "requestTypeA":
                RequestTypeA requestTypeA = objectMapper.readValue(inputString, RequestTypeA.class);
                routerResult.setResult(handleRequestTypeA(requestTypeA));
                break;

            case "requestTypeB":
                RequestTypeB requestTypeB = objectMapper.readValue(inputString, RequestTypeB.class);
                routerResult.setResult(handleRequestTypeB(requestTypeB));
                break;

            default:
                logger.error( "don't know how to handle route of type \"" + route + "\n" );
                routerResult.setResult("error");
        }

        outputStream.write(objectMapper.writeValueAsString(routerResult).getBytes(StandardCharsets.UTF_8));

       logger.info("done with run, remaining time in ms is " + context.getRemainingTimeInMillis() );
    }


    private String handleRequestTypeA(RequestTypeA requestTypeA) {
        logger.info("handling requestTypeA, requestTypeA.requestA is " + requestTypeA.getRequestA() );

        return "handled requestTypeA";
    }

    private String handleRequestTypeB(RequestTypeB requestTypeB) {
        logger.info("handling requestTypeB, requestTypeB.requestB is " + requestTypeB.getRequestB() );

         return "handled requestTypeB";
    }
}

with RouterRequest.java:

public class RouterRequest {
    protected String route;

    public String getRoute() {
        return route;
    }
}

and RequestTypeA.java:

public class RequestTypeA extends RouterRequest {
    private String requestA;

    public RequestTypeA() {
        route = "requestTypeA";
    }

    public String getRequestA() {
        return requestA;
    }

    public void setRequestA(String requestA) {
        this.requestA = requestA;
    }
}

and RequestTypeB.java

public class RequestTypeB extends RouterRequest {
    private String requestB;

    public RequestTypeB() {
        route = "requestTypeB";
    }

    public String getRequestB() {
        return requestB;
    }

    public void setRequestB(String requestB) {
        this.requestB = requestB;
    }
}

And a result class, RouterResult.java:

public class RouterResult {
    private String result;

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    @Override
    public String toString() {
        return "RouterResult{" +
                "result='" + result + '\'' +
                '}';
    }
}

Then, to invoke this Lambda, you will need a role that has the lambda:InvokeFunction permission. The code to invoke looks like:

public class RouterRunner {
    private static final String AWS_ACCESS_KEY_ID = "<access key>";
    private static final String AWS_SECRET_ACCESS_KEY = "<access secret>";

    public static void main( String[] argv ) throws IOException {
        AWSCredentials credentials = new BasicAWSCredentials( AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY );
        AWSLambda lambda = AWSLambdaClientBuilder.standard()
                .withRegion(Regions.US_WEST_2)
                .withCredentials(new AWSStaticCredentialsProvider(credentials)).build();

        RequestTypeA requestTypeA = new RequestTypeA();
        requestTypeA.setRequestA("set from the runner, request type A");

        ObjectMapper objectMapper = new ObjectMapper();

        InvokeRequest invokeRequest = new InvokeRequest()
                .withFunctionName("lambda-router")
                .withPayload(objectMapper.writeValueAsString(requestTypeA));

        invokeRequest.setInvocationType(InvocationType.RequestResponse);

        InvokeResult invokeResult = lambda.invoke(invokeRequest);

        String resultJSON = new String(invokeResult.getPayload().array(), StandardCharsets.UTF_8);

        System.out.println( "result from lambda is " + resultJSON );

        RouterResult routerResult = objectMapper.readValue(resultJSON, RouterResult.class);

        System.out.println( "result.toString is " + routerResult.toString() );


        RequestTypeB requestTypeB = new RequestTypeB();
        requestTypeB.setRequestB("set from the runner, request type B");

        invokeRequest = new InvokeRequest()
                .withFunctionName("lambda-router")
                .withPayload(objectMapper.writeValueAsString(requestTypeB));

        invokeRequest.setInvocationType(InvocationType.RequestResponse);

        invokeResult = lambda.invoke(invokeRequest);

        resultJSON = new String(invokeResult.getPayload().array(), StandardCharsets.UTF_8);

        System.out.println( "result from lambda is " + resultJSON );

        routerResult = objectMapper.readValue(resultJSON, RouterResult.class);

        System.out.println( "result.toString is " + routerResult.toString() );
    }
}

There likely needs to be some error handling improvement and I'm sure you could make this a bit more efficient. But that's the overall idea. Ultimately on the Lambda side I convert the InputStream to a String and convert that String to some sort of object based on a common field in the request types. On the client side I convert the objects into JSON, send them out, and convert the result back from a JSON String back into the result object.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.