I am trying to write a Lambda function in java which connects to S3 and then fetch the data.
When I run it locally, using main function it works fine and returns the result. Buit when I upload it to AWS lambda and the run it, I get this error message:
"errorMessage": "Unable to execute HTTP request: Connect to bucket-name.s3.amazonaws.com:443 [bucket-name.s3.amazonaws.com/52.217.1.172] failed: connect timed out", "errorType": "com.amazonaws.SdkClientException",
I have my S3 bucket as public.
My pom.xml:
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.11.493</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.1.0</version>
</dependency>
My request Handler:
public class LambdaRequestHandler implements RequestHandler<String, String>{
@Autowired
public ClaimSuffixNumberService csService;
@Override
public String handleRequest(String input, Context context) {
// TODO Auto-generated method stub
if(csService==null) {
csService= Application.getBean(ClaimSuffixNumberService.class);
}
String result= csService.readAndMakeCall("claimSuffix");
return result;
}
}
My service
public String getObject(String fileName) {
System.out.println("Inside Get Object");
try {
BasicAWSCredentials awsCreds = new BasicAWSCredentials("access-key","secret-key");
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withRegion(Regions.US_EAST_1)
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
.build();
System.out.println(s3Client);
S3Object s3object = s3Client.getObject(new GetObjectRequest(bucket-name, object-name));
InputStream is = s3object.getObjectContent();
String content = StreamUtils.copyToString(is,
StandardCharsets.UTF_8);
return content;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public String readAndMakeCall(String fileName) {
// TODO Auto-generated method stub
try {
System.out.println("Reading for " + fileName);
String content = getObject(fileName);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
List<ClaimSuffixNumber> claimSuffixList = mapper.readValue(content, mapper.getTypeFactory().constructCollectionType(List.class, ClaimSuffixNumber.class));
System.out.println(claimSuffixList.toString());
for(ClaimSuffixNumber i: claimSuffixList)
{
System.out.println(i);
}
return claimSuffixList.toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return " ";
}
Like Mario said, your Lambda currently has no internet access. This is most likely because of your VPC configuration. I believe Mario's answer is correct. You can setup a S3 VPC endpoint. In my case, since I was working with SES and Lambda, you can't setup an endpoint for SES, so I'm adding a workaround using NAT Gateway. (NOTE: NAT Gateway does NOT have a free tier)
|---------------------|------------------|
| Destination | Target |
|---------------------|------------------|
| 0.0.0.0/0 | igw-#### |
|---------------------|------------------|
|---------------------|------------------|
| Destination | Target |
|---------------------|------------------|
| 0.0.0.0/0 | nat-#### |
|---------------------|------------------|
Just to reiterate, NAT Gateway does NOT have a free tier so keep that in mind. Here's the pricing info https://aws.amazon.com/vpc/pricing/