This lab gives you experience with setting up an AWS (Amazon Web Services) Lambda with Java. It is derived from a workshop created by Amazon. However, you do not need to use anything from that workshop nor its github repository This lab is self-contained.
You will use a number of tools to develop this lab.
.jar
files: you will build a .jar
file to be uploaded to AWSAWS Classroom is a training environment for using AWS. It is not a certification course; you would need to take specific courses to become a certified AWS developer. If you would like to explore these other courses, talk to your instructor. Our primary reason to use AWS Classroom is to provide access to their services without requiring students to use a credit card to create their own accounts. Be careful of how you use the resources in AWS Classroom; there are limits, and exceeding those limits results in additional work to complete labs.
Note: AWS Classroom is delivered through a Canvas shell. This is an entirely separate instance of Canvas than the one used at MSOE. Do not use your MSOE password with the AWS Classroom because that could give other parties access to your MSOE account.
You should have received an email telling you how to get into the classroom. If you have not, contact your instructor. When you get this email, create a new Canvas account with AWS. Use your MSOE email address to create this account, just not your MSOE password. If required, set up two-factor authentication through your email address. Once you are in ,
You should now be seeing the AWS Console with an image similar to
Feel free to explore a bit. Many resources are part of the free tier; you can explore these without any problems. Do talk to your instructor before starting paid resources. But there are many resources that are free for the first year that you can try out on your own.
Warning: Do not hit the ↺ Reset button. It takes up to an hour for a reset to complete, and it is designed for cases where you have a large number of resources to destroy. For this course, you can achieve the same thing by simply deleting any Lambdas you write. If you do hit the reset button, do not hit it multiple times; hitting it restarts the process and means you have to wait even longer before the reset is complete.
To deploy a Java function as a Lambda, you first create a .jar
file with a specific format. Your instructor will give you a starting point for this lab on GitHub Classroom. Use the provided link to clone your repository. The source code is also available at the file unicorn-locator.zip
.
Take a peak at the source code: src/main/java/com/unicorn/location/UnicornPostLocationHandler.java. One source file, half a dozen folders. You can tell this tool was developed for working on much larger projects! Most of your changes for this lab will be in this file.
As mentioned above, this project builds using the tool Maven. Maven is similar to other build tools such as Make, CMake, and Ant. A key goal of Maven is to provide a simple, uniform build system, where “simple” means that users need not understand the details of the underlying mechanisms.
To run the Maven builder, press the control key twice (quickly) in IntelliJ. This will pop up a “Run Anything” dialog. This dialog allows running commands that are not built in to IntelliJ. In this case, enter the command mvn package
. Visit the target/
folder; you should see a Jar file called UnicornLocationApi-1.1-jar-with-dependencies.jar
. This is your java “lambda” that you will upload to AWS. If you cannot find the file, get help from your instructor.
If this fails, you may need to download Java 17. Visit the project structure. If there is no Java 17 option for SDK, use the drop-down menu to Download JDK… and pick a Java 17 distribution. Then re-execute mvn package
.
Return to the AWS website that you opened earlier. If it is not open yet, click on the AWS link in the upper left corner.
As mentioned earlier, AWS has a very large number of services. The simplest way to access them is to search. Click on the search bar at the top of the screen (just under the URL line) and enter “lambda”. Click on the lambda option that appears. Then,
unicorn
. Don’t ask why. All amazonians love unicorns.AWS is now ready for you to upload your Jar file.
Under the Code tab (where you start), and under the Code Source section, on the right, open the Upload from dropdown and select .zip or .jar file.
Within your IntelliJ project window, go into the target folder and find the UnicornLocationApi-1.1-jar-with-dependencies.jar that you built earlier. You can drag and drop this onto the .jar upload window you just opened.
In the Runtime Settings box (below the Code source box), click the “Edit” button on the right side. Set the Handler to “com.unicorn.location.UnicornPostLocationHandler::handleRequest” (Note that this is simply the fully-qualified method reference for the handleRequest method in the only Java class in the src folder. If you build your own IntelliJ project, folders may get compressed. In that case the handler name may be slightly different such as **main.java.**com.unicorn.location.UnicornPostLocationHandler::handleRequest
.
You are now ready to test. Click on the Test tab, then click the orange “Test” button. This test should pass and you should see a green box with the text “Executing function: succeeded”. Contact your instructor immediately if it does not.
At the top of the Amazon Console, enter api gateway into the search bar. Click on the API Gateway option that pops up.
In the HTTP API option box, click the bright orange Build button. Name your API unicorn-api. Then click on Add integration button and select Lambda. Click on the box for Lambda function and select the unicorn lambda you created earlier. Click on Next.
From the “Configure routes” page, click Add route, select “ANY” for the method, and set the resource path to /add-unicorn-location
. The integration target is that lambda you created (unicorn). Select 1.0 for the version. Finally, click on Next.
For “Stage name”, leave the entry to $default
. Click Next.
On the Review and Create screen, click on Create.
On the pane on the left, under Deploy, click on Stages, and select the $default stage. Then, under Invoke URL, click on the URL that will look something like: https://yszfheuqqvc.execute-api.us-east-1.amazonaws.com. Clicking on this brings up a new web page. Edit the URL at the top, adding your route at the end: https://yszfhaiqvc.execute-api.us-east-1.amazonaws.com/add-unicorn-location
You should get the response from the URL at this point. It should simply say, “Hello, World! I’m a fresh new lambda!”, just like in your Java code you compiled earlier.
The following steps will have you modify UnicornPostLocationHandler.java
(the only Java source file in the provided code) to add logging. Logging is very useful for debugging your Lambda. Without logging, the only way to track down issues is to return additional information from the Lambda, and that is a very slow way to debug code. Logging gives you the equivalent of System.out.println()
at a console.
Add the libraries you need for logging to your pom.xml
file in the root of your repo:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.12</version>
</dependency>
That file contains a <dependencies>
tag already. Put the new dependency items between the <dependencies>
start tag and the </dependencies>
end tag. For brevity, the next time we say to put some new text between a start and end tag, we’ll say to insert it inside the <dependencies> ... </dependencies>
tag, meaning the same thing.
Go to UnicornPostLocationHandler.java
and paste this as an instance variable in the class:
private final Logger logger = LoggerFactory.getLogger(UnicornPostLocationHandler.class);
Hopefully IntelliJ offers to import. If it does not, import Logger
and LoggerFactory
from org.slf4j
.
And now update your handleRequest method to look like this:
public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {
logger.info("Received a request here!");
return new APIGatewayProxyResponseEvent()
.withStatusCode(200)
.withBody("This is supposed to be the Unicorn Location API at some point!");
}
Now, rebuild by tapping the control key twice and running mvn package
again. Upload the new .jar to the lambda as you did before.
Retest the lambda through the web interface. It should still pass. At the bottom of the colorful pane telling you about the passed test, look at the Log output section. This section should match the print statements in your program, including any custom messages you slipped into the .info command above!
So far, your lambda simply prints the same response no matter what it is given as an input. To make the program respond to input, you will rewrite it to process JSON data. JSON stands for JavaScript Object Notation. In this notation, brackets ([
and ]
) are used to mark lists and braces ({
and }
) are used to mark objects. Values are comma-separated within the lists and objects. Using standard libraries, we can encode and decode text that is in JSON format. This means we can type simple text (as opposed to creating binary data) to write JSON data inputs.
Your next step is to extend your application to accept JSON data from the user. The provided code uses the Amazon API Gateway Proxy-Integration which embeds some additional information into the JSON received by the app so that we view the headers later, and not just the JSON body that the client sent. But for now, let’s insert some code that gets access to that body.
Insert the following directives into your pom.xml
file. As before, this code will be added between the <dependency> .. </dependency>
tags:
<dependency>
<groupId>com.fasterxml.jackson.jr</groupId>
<artifactId>jackson-jr-objects</artifactId>
<version>2.17.0</version>
</dependency>
This specifies using a library which processes JSON data.
Next, create a new file called UnicornLocation.java
and paste the following code into it:
package com.unicorn.location;
public class UnicornLocation {
private String unicornName;
private String longitude;
private String latitude;
public String getUnicornName() {
return unicornName;
}
public void setUnicornName(String unicornName) {
this.unicornName = unicornName;
}
public String getLongitude() {
return longitude;
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}
public String getLatitude() {
return latitude;
}
public void setLatitude(String latitude) {
this.latitude = latitude;
}
}
The jackson library can use this structure to generate and parse JSON objects.
Return to the UnicornPostLocationHandler.java
file and update the handler to
public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {
try {
UnicornLocation unicornLocation = JSON.std.beanFrom(UnicornLocation.class, input.getBody());
return new APIGatewayProxyResponseEvent()
.withStatusCode(200)
.withBody("Received unicorn location: " + JSON.std.asString(unicornLocation));
} catch (Exception e) {
logger.error("Error while processing the request", e);
return new APIGatewayProxyResponseEvent()
.withStatusCode(400)
.withBody("Error processing the request");
}
}
Make sure you import the jackson library:
import com.fasterxml.jackson.jr.ob.JSON;
Now rebuild and deploy your jar as above. Test it through the AWS interface. Your test should pass, but it will show an error code 400 because the application is expecting requests from the API Gateway. Return to the $default
stage of your API’s gateway, to that URL you first got working that looked something like https://yszfhaiqvc.execute-api.us-east-1.amazonaws.com/add-unicorn-location
. Refresh the link. It should show the same 400 error code you see in your test.
Next, download Postman and install it. Launch the app. Note you do not need to create a postman account for this lab. Within Postman, Use POST as the method, set the URL to the gateway URL: https://yszvc.execute-api.us-east-1.amazonaws.com/add-unicorn-location
, and set the body format to be raw. Enter the body
{
"unicornName": "Richard",
"longitude": "13.404954",
"latitude": "52.520008"
}
Clicking Send should return the response
Received unicorn location: {"latitude":"52.520008","longitude":"13.404954","unicornName":"Richard"}
You now have a lambda that turns JSON into a Java object!
You are NOT required to go any further with this lab. If your lambda is printing out the location it receives, you can stop there.
If you would like to add a DynamoDB, please see the main tutorial’s section that picks up here: Java on AWS Lambda: AWS SDK Verify created item. Throughout this workshop, we have been creating AWS components through the web interface (console), so we recommend you just expore the console on your own if you want to try this. Some notes:
template.yml
file. It is not clear what they are referring to, but you can use the SAM template that is at the bottom of the page.Be sure to commit and push your code to the assignment repository. Your instructor may have additional submission requirements. See Canvas.
You may need to demonstrate this lab to your instructor. In any case, please do not reset your resources for the lab. All these resources fall within the free tier, so completing this lab is unlikely to use any Amazon credits. Leaving them in place allows your instructor to investigate problems.
A collection of issues and possible solutions:
I’m having difficulties getting into AWS Classroom: Start with your email from AWS inviting you to the classroom. When you click on the button to accept the invitation, it gives you a choice based on having a Canvas account and creating a new account. What they mean to ask is whether you have an AWS Canvas account already, and the answer is most certainly “no”. Remember that the AWS Canvas is completely separate from the MSOE Canvas, so having an account on the Canvas system at MSOE does not mean you have a Canvas account with AWS. Click on the create new account button.
AWS console will not start up:
Check the top of your browser page for options to allow the browser to open new windows. AWS Learner Lab opens the console in a new browser window, and most browsers are set to require permission to open the new window. Give it the permission.
Consider changing browsers. Browsers that have worked include Firefox, Chrome, and Edge.
Ensure you have popups enabled for the AWS Console site. Your browser should prompt you for permission to open the console, but if it does not you may need to research how to allow it.
When I click on the Test button, I get a message indicating it failed: Try clicking on the Amazon Q helper button that appears; it seems this gives useful diagnostics. If that does not help, talk to your instructor.
IntelliJ shows errors in my code: Do not trust IntelliJ to identify errors. It often marks things as incorrect that are perfectly fine, and its corrections for the code in this lab are suspect. Look for a tiny “m” from Maven; its suggestions are much more helpful. You can also re-issue mvn package
to rebuild; error messages from this command are actual errors.
I ran mvn package
and still see lots of errors: make sure the pom.xml
file is in the top level of the project. Several students found it was moved to the src
subfolder, and the mvn
command cannot find the file in that case.