How to read a file in AWS Lambda Function written in Java ?

21,165

Solution 1

I have made following changes in my code and now its works perfect :

Majorly changed following two lines :

ClassLoader classLoader = getClass().getClassLoader();

File cityFile = new File(classLoader.getResource("City.db").getFile());

package com.lambda;


import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
import java.io.*;

public class TestDetailsHandler implements RequestStreamHandler {


    public void  handleRequest(InputStream input,OutputStream output,Context context){

        // Get Lambda Logger
        LambdaLogger logger = context.getLogger();

        // Receive the input from Inputstream throw exception if any

        ClassLoader classLoader = getClass().getClassLoader();

        File cityFile = new File(classLoader.getResource("City.db").getFile());
        FileInputStream fis = null;

        try {
            fis = new FileInputStream(cityFile);

            System.out.println("Total file size to read (in bytes) : "
                    + fis.available());

            int content;
            while ((content = fis.read()) != -1) {
                // convert to char and display it
                System.out.print((char) content);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null)
                    fis.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

enter image description here

Solution 2

This is how I did it, let's say this is how your project structure looks like -

enter image description here

And you want to read the file config.properties which is inside the project-dir/resources directory.

The code for reading the content of the file would be -

InputStream input = null;
try {
    Path path = Paths.get(PropertyUtility.class.getResource("/").toURI());

    // The path for config file in Lambda Instance -
    String resourceLoc = path + "/resources/config.properties";

    input = new FileInputStream(resourceLoc);
} catch(Exception e) {
    // Do whatever
}

If you are following this project structure and using this code, then it will work in AWS Lambda.

PropertyUtility is just a utility class that I have created to read the contents of the config file. The PropertyUtility class looks like this -

enter image description here

As you can see in the above code, the path of the config file is different in the local system and in Lambda Instance.

In your local machine, PropertyUtility.class.getResource("/") points to bin, that is why you have to do path.getParent(), to point it to the project-directory which is HelloLambda in this example.

For the Lambda Instance, PropertyUtility.class.getResource("/") points directly to the project-directory.

Solution 3

If the file in located under resources directory, then the following solution should work:

String fileName = "resources/config.json";

Path path = Paths.get(this.getClass().getResource("/").toURI());
Path resourceLocation = path.resolve(fileName);

try(InputStream configStream = Files.newInputStream(resourceLocation)) {
            //use your file stream as you need.
}

Here the most important part is "resources/config.json", it must not be "/resources/config.json", because the file location is /var/task/resources/config.json in lambda, I checked.

Hope this helps who still face problem in reading file in aws lambda.

Solution 4

If the file is located under resources folder, you can use it directly in lambda by using something like the following code:

final BufferedReader br = new BufferedReader(new FileReader("/flows/cancellation/MessageArray.json"));

I wanted to read a json file, you can have different use case, but the code works. enter image description here

Share:
21,165
Sumit Arora
Author by

Sumit Arora

www.linkedin.com/in/sumitarora

Updated on April 17, 2020

Comments

  • Sumit Arora
    Sumit Arora about 4 years

    I have written an AWS Lambda Handler as below :

    package com.lambda;
    import com.amazonaws.services.lambda.runtime.Context;
    import com.amazonaws.services.lambda.runtime.LambdaLogger;
    import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
    import java.io.*;
    
    public class TestDetailsHandler implements RequestStreamHandler {
    
    
        public void  handleRequest(InputStream input,OutputStream output,Context context){
    
            // Get Lambda Logger
            LambdaLogger logger = context.getLogger();
    
            // Receive the input from Inputstream throw exception if any
    
            File starting = new File(System.getProperty("user.dir"));
                System.out.println("Source Location" + starting);
    
               File cityFile = new File(starting + "City.db");
            FileInputStream fis = null;
    
            try {
                fis = new FileInputStream(cityFile);
    
                System.out.println("Total file size to read (in bytes) : "
                        + fis.available());
    
                int content;
                while ((content = fis.read()) != -1) {
                    // convert to char and display it
                    System.out.print((char) content);
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (fis != null)
                        fis.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    
    }
    

    Its read a file : City.db , available in resources folder, even I kept to everywhere see below :

    enter image description here

    But it showing following message on execution of this lambda function :

    START RequestId: 5216ea47-fc43-11e5-96d5-83c1dcdad75d Version: $LATEST
    Source Location/
    java.io.FileNotFoundException: /city.db (No such file or directory)
        at java.io.FileInputStream.open0(Native Method)
        at java.io.FileInputStream.open(FileInputStream.java:195)
        at java.io.FileInputStream.<init>(FileInputStream.java:138)
        at com.lambda.TestDetailsHandler.handleRequest(TestDetailsHandler.java:26)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at lambdainternal.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:511)
        at lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:972)
        at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:231)
        at lambdainternal.AWSLambda.<clinit>(AWSLambda.java:59)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:348)
        at lambdainternal.LambdaRTEntry.main(LambdaRTEntry.java:93)
    END RequestId: 5216ea47-fc43-11e5-96d5-83c1dcdad75d
    REPORT RequestId: 5216ea47-fc43-11e5-96d5-83c1dcdad75d  Duration: 58.02 ms  Billed Duration: 100 ms     Memory Size: 1024 MB    Max Memory Used: 50 MB  
    

    enter image description here

    Contents of the Pom.xml file :

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.lambda</groupId>
        <artifactId>testdetails</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
        <name>test-handler</name>
    
        <dependencies>
            <dependency>
                <groupId>com.amazonaws</groupId>
                <artifactId>aws-lambda-java-core</artifactId>
                <version>1.1.0</version>
            </dependency>
    
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
    
    
    
            </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-shade-plugin</artifactId>
                    <version>2.3</version>
                    <configuration>
                        <createDependencyReducedPom>false</createDependencyReducedPom>
                    </configuration>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>shade</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </project>
    

    I have used various ways to keep file here and there , but at the end its not working. May you please let me know what is wrong here ?

    However in my another project where I have kept xyz.properties file in resources folder and reading from a PropertyManager file, its working fine. When I tested it on my system its working fine, but on AWS Lambda function it doesn't work.

  • Prashant
    Prashant about 7 years
    Use getaresourceAsStream() instead. You don't need to convert it to a file which might not work in all cases.