Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read files from the classpath in aws lambda java

I'm seeing this error when I try to execute my aws lambda function

1) Error injecting constructor, java.lang.NullPointerException
at in.nikhilbhardwaj.path.route.resources.ServicesResource.<init>(ServicesResource.java:66)
at in.nikhilbhardwaj.path.route.resources.ServicesResource.class(ServicesResource.java:56)
while locating in.nikhilbhardwaj.path.route.resources.ServicesResource
for parameter 0 at in.nikhilbhardwaj.path.alexa.intent.HelloWorldIntentAction.<init>(HelloWorldIntentAction.java:44)
while locating in.nikhilbhardwaj.path.alexa.intent.HelloWorldIntentAction
while locating in.nikhilbhardwaj.path.alexa.intent.IntentAction annotated with @com.google.inject.multibindings.Element(setName=,uniqueId=10, type=MAPBINDER, keyType=java.lang.String)
at in.nikhilbhardwaj.path.alexa.intent.IntentModule.configure(IntentModule.java:17) (via modules: in.nikhilbhardwaj.path.alexa.AlexaStarterApplicationModule -> in.nikhilbhardwaj.path.alexa.intent.IntentModule -> com.google.inject.multibindings.MapBinder$RealMapBinder)
while locating java.util.Map<java.lang.String, in.nikhilbhardwaj.path.alexa.intent.IntentAction>
for parameter 0 at in.nikhilbhardwaj.path.alexa.intent.IntentHandlerServiceImpl.<init>(IntentHandlerServiceImpl.java:16)
while locating in.nikhilbhardwaj.path.alexa.intent.IntentHandlerServiceImpl
while locating in.nikhilbhardwaj.path.alexa.intent.IntentHandlerService
for parameter 0 at in.nikhilbhardwaj.path.alexa.AlexaStarterSpeechlet.<init>(AlexaStarterSpeechlet.java:26)
while locating in.nikhilbhardwaj.path.alexa.AlexaStarterSpeechlet
Caused by: java.lang.NullPointerException
at java.io.Reader.<init>(Reader.java:78)
at java.io.InputStreamReader.<init>(InputStreamReader.java:113)
at in.nikhilbhardwaj.path.route.resources.ServicesResource.initializeServiceIds(ServicesResource.java:88)
at in.nikhilbhardwaj.path.route.resources.ServicesResource.<init>(ServicesResource.java:68)
at in.nikhilbhardwaj.path.route.resources.ServicesResource$$FastClassByGuice$$3d6e91ec.newInstance(<generated>)

I've modified my code to read from the classpath and not the file system by following this question

This is the line (Line 88 in ServicesResource.java) from where the exception is thrown -

Iterable<CSVRecord> records = CSVFormat.RFC4180.withFirstRecordAsHeader()
    .parse(new InputStreamReader(this.getClass().getResourceAsStream(RESOURCES_ROOT + RESOURCE_CALENDAR), StandardCharsets.UTF_8));

and these are the constants that I'm using -

public static final String RESOURCE_CALENDAR = "calendar.txt";
public static final String RESOURCES_ROOT = "/path-nj-us/";

I think that I've packaged the code that I upload to aws lambda correctly, it works when I remove these references. Here's is what the zip contains (I've omitted unrelated files) -

➜  distributions git:(master) ✗ jar tf path-alexa-skills-kit.zip
in/
in/nikhilbhardwaj/
in/nikhilbhardwaj/path/
in/nikhilbhardwaj/path/route/
in/nikhilbhardwaj/path/alexa/
in/nikhilbhardwaj/path/alexa/AlexaStarterApplicationModule.class
in/nikhilbhardwaj/path/alexa/AlexaStarterSpeechlet.class
in/nikhilbhardwaj/path/alexa/AlexaStarterSpeechletRequestStreamHandler.class
in/nikhilbhardwaj/path/route/model/Constants.class
in/nikhilbhardwaj/path/route/resources/
in/nikhilbhardwaj/path/route/resources/ServicesResource.class
in/nikhilbhardwaj/path/route/resources/StopsResource.class
in/nikhilbhardwaj/path/route/resources/StopTimesResource.class
in/nikhilbhardwaj/path/route/resources/TripsResource.class
log4j.properties
path-nj-us/
path-nj-us/agency.txt
path-nj-us/calendar.txt
path-nj-us/calendar_dates.txt
path-nj-us/fare_attributes.txt
path-nj-us/fare_rules.txt
path-nj-us/feed_info.txt
path-nj-us/frequencies.txt
path-nj-us/route_directions.txt
path-nj-us/routes.txt
path-nj-us/shapes.txt
path-nj-us/stop_times.txt
path-nj-us/stops.txt
path-nj-us/timetable_stop_order-new.txt
path-nj-us/timetables-new.txt
path-nj-us/transfers.txt
path-nj-us/trips.txt

I would really appreciate any pointers to figure out what's missing here or general tips to debug this further. This is the first aws lambda function that I'm writing, so it's entirely possible that I glossed over something important in the documentation or don't know what to look for.

I've added some more debugging code and run it, it appears that the resources aren't available -

URL r = this.getClass().getClassLoader().getResource("path-nj-us/calendar.txt");
if (r != null && r.getFile() != null) {
  System.out.println("Resource file name" + r.getFile());
} else {
  System.out.println("Resource not found in classpath");
}

This prints Resource not found in classpath. I've also tried the this.getClass().getResource() invariant with the same results.

I'll try posting to the aws forums to see if there is a known reason for this behavior or if reading files from the classpath is disallowed.

like image 970
nikhil Avatar asked Oct 18 '22 02:10

nikhil


1 Answers

Only two directories are accessed by awsLambda user code.

  1. /var/task
  2. /tmp

all lambda functions keep the source code on /var/task

in your code, use anyone of this path instead of current directory path "path-nj-us". like this

URL r = this.getClass().getClassLoader().getResource("/tmp/calendar.txt");
if (r != null && r.getFile() != null) {
  System.out.println("Resource file name" + r.getFile());
} else {
  System.out.println("Resource not found in classpath");
}
like image 64
Abdul Manaf Avatar answered Oct 29 '22 04:10

Abdul Manaf