Is aws lambda can expose only one spring boot api - java

I have developed 4 apis using spring boot. Now i m trying to enable aws lambda for serverless. Is it possible to expose 4 api’s with single lambda.

Is it possible to expose 4 api’s with single lambda.
AWS lambda is FaaS - functions as a service, One function per Lambda.
However you can arguably achieve the intended functionality with a wrapper/proxy function as the entry point and route the request to upstream methods/functions as needed
Its described here aws api gateway & lambda: multiple endpoint/functions vs single endpoint
Take a look at the following documentation on creating an API Gateway => Lambda proxy integration:
http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html
The following is merely a reworded explanation of what's given here aws api gateway & lambda: multiple endpoint/functions vs single endpoint .
AWS example has a good explanation; A Lambda request like the following:
POST /testStage/hello/world?name=me HTTP/1.1
Host: gy415nuibc.execute-api.us-east-1.amazonaws.com
Content-Type: application/json
headerName: headerValue
{
"a": 1
}
Will end up sending the following event data to your AWS Lambda function:
{
"message": "Hello me!",
"input": {
"resource": "/{proxy+}",
"path": "/hello/world",
"httpMethod": "POST",
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"cache-control": "no-cache",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-Mobile-Viewer": "false",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Viewer-Country": "US",
"Content-Type": "application/json",
"headerName": "headerValue",
"Host": "gy415nuibc.execute-api.us-east-1.amazonaws.com",
"Postman-Token": "9f583ef0-ed83-4a38-aef3-eb9ce3f7a57f",
"User-Agent": "PostmanRuntime/2.4.5",
"Via": "1.1 d98420743a69852491bbdea73f7680bd.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "pn-PWIJc6thYnZm5P0NMgOUglL1DYtl0gdeJky8tqsg8iS_sgsKD1A==",
"X-Forwarded-For": "54.240.196.186, 54.182.214.83",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
},
"queryStringParameters": {
"name": "me"
},
"pathParameters": {
"proxy": "hello/world"
},
"stageVariables": {
"stageVariableName": "stageVariableValue"
},
"requestContext": {
"accountId": "12345678912",
"resourceId": "roq9wj",
"stage": "testStage",
"requestId": "deef4878-7910-11e6-8f14-25afc3e9ae33",
"identity": {
"cognitoIdentityPoolId": null,
"accountId": null,
"cognitoIdentityId": null,
"caller": null,
"apiKey": null,
"sourceIp": "192.168.196.186",
"cognitoAuthenticationType": null,
"cognitoAuthenticationProvider": null,
"userArn": null,
"userAgent": "PostmanRuntime/2.4.5",
"user": null
},
"resourcePath": "/{proxy+}",
"httpMethod": "POST",
"apiId": "gy415nuibc"
},
"body": "{\r\n\t\"a\": 1\r\n}",
"isBase64Encoded": false
}
}
Now you have access to all headers, url params, body etc. So you could use that to handle requests differently in your wrapper/proxy Lambda function and route to upstream functions as per your routing needs.
Many people are using this methodology today as opposed to creating lambda function for each method and an api gateway resource.
There are pros and Cons to this approach
Deployment: if each lambda function is discrete then you can deploy them independently, which might reduce the risk from code changes (microservices strategy). Conversely you may find that needing to deploy functions separately adds complexity and is burdensome.
Self Description: API Gateway's interface makes it extremely intuitive to see the layout of your RESTful endpoints -- the nouns and verbs are all visible at a glance. Implementing your own routing could come at the expense of this visibility.
Lambda sizing and limits: If you proxy all -- then you'll wind up needing to choose an instance size, timeout etc. that will accommodate all of your RESTful endpoints. If you create discrete functions then you can more carefully choose the memory footprint, timeout, deadletter behavior etc. that best meets the needs of the specific invocation.
More on Monolithic lambda vs Micro Lambda here : https://hackernoon.com/aws-lambda-should-you-have-few-monolithic-functions-or-many-single-purposed-functions-8c3872d4338f

Related

How to translate the messages from the micronaut-problem-json library?

What: I would like to know how to translate the messages for the micronaut-problem-json library. Does it support src/main/resources/i18n/messages.properties? This information is not documented on the GitHub project's page.
The project: https://github.com/micronaut-projects/micronaut-problem-json/
Why: The motivation for this is obvious, to support the internationalization of the messages.
This is a typical payload generated by the library in case of a constraint validation error:
{
"type": "https://zalando.github.io/problem/constraint-violation",
"title": "Constraint Violation",
"status": 400,
"violations": [
{
"field": "create.signup.username",
"message": "size must be between 3 and 30"
}
]
}
I would like to add support to other languages, like Portuguese, Spanish, etc. When an HTTP request from the client includes the HTTP header Accept-Language: pt the server should return the following payload:
{
"type": "https://zalando.github.io/problem/constraint-violation",
"title": "Violação de integridade",
"status": 400,
"violations": [
{
"field": "create.signup.username",
"message": "o tamanho deve ser entre 3 e 30"
}
]
}
Out of the box, neither micronaut-problem-json nor the problem library uses Java Internationalization.
There are customizations that you can do within Micronaut. See Micronaut Problem Json User Documentation.
You can always request the feature or provide a pull-request.

Mock/not-mock response on a per request basis in Integration test

I am writing Integration tests. I have a need where for a positive test case request hit an actual service and recieve the response. But for a negative test case I must get the mocked response.
I am curious to understand if there is a way that I can mock/not-mock the request on a per configuration basis. Like for example if request accepts email address in request and I provide
"invalid#email.com" - response from mockoon must be a mocked response.
"valid#email.com" - mocking must not happen but rather it must hit the actual server to get the response. may be via redirecting or calling the actual service and responding the response to the caller.
I have tried Mockoon but feature is not yet present. So trying to help from the community :)
Regards,
You can use separate stub/mappings that match on different emails.
Assuming that your url is some-Url and uses a queryParameter of email...
{
"request": {
"url": "/some-Url",
"queryParameters": {
"email": {
"equalTo": "invalid#email.com"
}
}
},
"response": {
"status": 200
}
}
{
"request": {
"url": "/some-Url",
"queryParameters": {
"email": {
"equalTo": "valid#email.com"
}
}
},
"response": {
"proxyBaseUrl": "http://my-other-url.com"
}
}
This is possible with mockswitch - it supports various request / response pairs kinda like a switch case. You can define different cases and do request matching based on for each. If one the case matches it breaks the response flow and responds. Also easy to proxy requests to actual service based on certain case.
Their docs is available here https://mockswitch.com/docs/#switch-case-responses

Spring Cloud config throws NPE empty for array in the file

We used Spring Cloud Config version 2.1 and it worked.
We updated to Spring Cloud Config 2.2, and now it does not work.
More details are
https://github.com/spring-cloud/spring-cloud-config/issues/1599
I reported the issue to accelerate the process as well, or maybe it is not an issue. I do not know, so I am asking you to help.
Our config file: python-service.yml
resources:
- resource1
- resource2
newResources: []
As I learned, Spring Cloud config client makes requests to fetch configuration, and it passes header
Accept: application/vnd.spring-cloud.config-server.v2+json.
In Spring Cloud config v 2.1
Note, Spring Cloud version 2.1 does not send such header; instead, it sends Accept: application/json
HTTP http://localhost:8888/python-service/dev
Accept: application/vnd.spring-cloud.config-server.v2+json
Returns
{
"name": "python-service",
"profiles": [
"dev"
],
"label": null,
"version": null,
"state": null,
"propertySources": [
{
"name": "file:/configuration/python-service.yml",
"source": {
"resources[0]": "resource1",
"resources[1]": "resource2",
"newResources": []
}
}
]
}
However, it Spring Cloud Config v 2.2, it fails
{
"timestamp": "2020-04-24T08:38:19.803+0000",
"status": 500,
"error": "Internal Server Error",
"message": "Could not construct context for config=python-service profile=dev label=null includeOrigin=true; nested exception is java.lang.NullPointerException",
"path": "/python-service/dev"
}
The funny thing is that there is no exception log output in config-service logs!
If I remove the accept header, I will get (version 2.2)
{
"name": "python-service",
"profiles": [
"dev"
],
"label": null,
"version": null,
"state": null,
"propertySources": [
{
"name": "file:/configuration/python-service.yml",
"source": {
"resources[0]": "resource1",
"resources[1]": "resource2",
"newResources": ""
}
}
]
}
Here, why "newResources": "" became an empty String, if it is expected to be an empty array - another question.
To sum up
1) How to use empty array in Spring Cloud config.
2) Why there is no log message about the NPE in Spring config-service logs.
3) Without the accept header, why "newResources": "" became an empty String, if I expected an empty array.
As for now, I can remove empty array from my config, but it is very scary because our config is used in many services! This breaks backward compatibility.
It turns out, it is a bug in Spring Boot.
https://github.com/spring-cloud/spring-cloud-config/issues/1572#issuecomment-620496235
https://github.com/spring-projects/spring-boot/issues/20506
Possible options:
1) Wait until it is fixed and update libraries.
2) What we did. We replaced empty array with empty element.
newResources:
anotherField: value
alternatively, use null. However, make sure, your code can handle it. Also, emptyArray can be treated as an emptyString. I found this out in debugger.

RestTemplate and variable number of variable

I have to post json to api_url for login.
{
"username":"testre","password":"password"
}
When I use postman to check this api, it reply successful authentication like below.
{
"status": "success",
"code": 200,
"message": "username, password validated.",
"data": [
{
"password": "password",
"username": "testre"
}
],
"links": [
{
"rel": "self",
"link": "http://localhost:2222/pizza-shefu/api/v1.0/customers/login/"
},
{
"rel": "profile",
"link": "http://localhost:2222/pizza-shefu/api/v1.0/customers/testre"
}
]
}
For an unauthorized json like below.
{
"status": "unauthorized",
"code": 401,
"errorMessage": "HTTP_UNAUTHORIZED",
"description": "credentials provided are not authorized."
}
Previously I code to retrieve it using java. But now I want to refactor it using RestTemplate in spring. The problem is every example I read is written for fixed number of variables https://spring.io/guides/gs/consuming-rest/. Here I get different numbers of variable according to the login success status. I am new to spring so I'm confused in creating the class for login reply which we get from rest template. (Such as this in the example Quote quote = restTemplate.getForObject("http://gturnquist-quoters.cfapps.io/api/random", Quote.class); But I need to return a json object). I couldn't figure out how to write the RestTemplate part.
As suggested by #Andreas:
Add the superset of all fields for all possible responses
Identify the set of fields that are mandatory for every response and make them required
Make the rest of the fields as optional
Upon receveiving a response, check the status code and implement your logic accordingly.
If you are using Jackson for Deserialization, all fields are optional by default (see this question)

How to update rally defect using web service v2.0

I have ObjectID of defect.
Defect should be updated using only web services.
Get a security token using this endpoint:
https://rally1.rallydev.com/slm/webservice/v2.0/security/authorize
The result includes the token, "fbaa0c04-2616-....
{"OperationResult": {"_rallyAPIMajor": "2", "_rallyAPIMinor": "0", "Errors": [], "Warnings": [], "SecurityToken": "fbaa0c04-2616-...."}}
Post using 'create' endpoint with the security token appended in the end. In this example 123456789 is the OID of the defect where Description field is being updated
URL:
https://rally1.rallydev.com/slm/webservice/v2.0/defect/123456789?key=fbaa0c04-...
Request Body:
{
"Defect":{
"Description":"some description"
}
}
Here is another example of a Request Body (payload) where two fields are updated, one of which is the Owner, which is a reference to a User object. Reference fields must use ObjectID:
{"Defect":{
"State":"Open",
"Owner":"/user/987654321"
}
}
You'll find the Rally Rest Toolkit for Java helpful.
The following example shows a full CRUD lifecycle:
https://github.com/RallyTools/RallyRestToolkitForJava/blob/master/src/main/resources/examples/com/rallydev/rest/CrudExample.java

Categories