JRestless allows you to create serverless (AWS Lambda) applications using JAX-RS.
- Description
- Motivation
- Features
- Function Types
- Usage Example
- Modules
- Release History
- Alternative Projects
- Limitations
- Meta
JRestless is a framework allowing you to build serverless JAX-RS applications or rather to run JAX-RS applications in FasS (Function as a Service) environments like AWS Lambda. This is achieved by providing a generic Jersey container that handles requests in the form of POJOs. For each FaaS environment there is a separate module acting as an integration layer between the actual environment and the generic Jersey container.
Since this framework is just a wrapper around or rather a container for Jersey, you can use almost all JAX-RS features plus Jersey's custom extensions like Spring integration - not Spring MVC, though since this functionality is provided by JAX-RS itself.
AWS Lambda is the only FaaS environment that supports Java at the moment and so it is the only supported environment for now.
The motivation for this project is to avoid a cloud vendor lock-in and to allow developers to run and test their code locally.
- Almost all JAX-RS features can be used (JSON/XML/text/... requests/responses, container request/response filters, etc.).
- Jersey extensions can be used. For example integration for Spring (an example can be found here: https://github.com/bbilger/jrestless-examples/tree/master/aws/gateway/aws-gateway-spring)
- Injection of provider and/or function type specific values via
@javax.ws.rs.core.Contextinto resources and endpoints:- All AWS functions can inject
com.amazonaws.services.lambda.runtime.Context. - AWS Gateway Functions can also inject the raw request GatewayRequest
- AWS Service Functions can also inject the raw request ServiceRequest
- All AWS functions can inject
- It's worth mentioning that AWS Gateway Functions is designed to be used with API Gateway's proxy integration type for Lambda Functions. So there are no limitations on the status code, the headers and the body you return.
- Gateway Functions are AWS Lambda functions that get invoked by AWS API Gateway. Read More...
- Service Functions are AWS Lambda functions that can either be invoked by other AWS Lambda functions or can be invoked directly through the AWS SDK. The point is that you don't use AWS API Gateway. You can abstract the fact that you invoke an AWS Lambda function away by using a special feign client (jrestless-aws-service-feign-client). Read More...
- SNS functions are planned for the next release.
Note: the framework is split up into multiple modules, so you choose which functionality you actually want to use. See Modules
All examples, including the following one, can be found in a separate repository: https://github.com/bbilger/jrestless-examples
JRestless does not depend on the serverless framework but it simplifies the necessary AWS configuration tremendously and will be used for this example.
Install serverless (>= 1.0.2) as described in the docs https://serverless.com/framework/docs/guide/installing-serverless/
Setup your AWS account as described in the docs https://serverless.com/framework/docs/providers/aws/setup/
Create a new function using serverless
mkdir aws-gateway-usage-example
cd aws-gateway-usage-example
serverless create --template aws-java-gradle --name aws-gateway-usage-example
rm -rf src/main/java/hello # remove the classes created by the template
mkdir -p src/main/java/com/jrestless/aws/examples # create the package structureReplace serverless.yml with the following contents:
service: aws-gateway-usage-example-service
provider:
name: aws
runtime: java8
stage: dev
region: eu-central-1
package:
artifact: build/distributions/aws-gateway-usage-example.zip
functions:
sample:
handler: com.jrestless.aws.examples.RequestHandler
events:
- http:
path: sample/{proxy+}
method: any
Replace build.gradle with the following contents:
apply plugin: 'java'
repositories {
jcenter()
mavenCentral()
}
dependencies {
compile(
'com.jrestless.aws:jrestless-aws-gateway-handler:0.3.0',
'org.glassfish.jersey.media:jersey-media-json-jackson:2.23'
)
}
task buildZip(type: Zip) {
archiveName = "${project.name}.zip"
from compileJava
from processResources
into('lib') {
from configurations.runtime
}
}
build.dependsOn buildZip
Create a new JAX-RS resource and a JAXB DTO (src/main/java/com/jrestless/aws/examples/SampleResource.java):
package com.jrestless.aws.examples;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@Path("/sample")
public class SampleResource {
@GET
@Path("/health")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response getHealth() {
return Response.ok(new HealthStatusDto("up and running")).build();
}
@XmlRootElement // for JAXB
public static class HealthStatusDto {
private String statusMessage;
@SuppressWarnings("unused")
private HealthStatusDto() {
// for JAXB
}
HealthStatusDto(String statusMessage) {
this.statusMessage = statusMessage;
}
@XmlElement // for JAXB
public String getStatusMessage() {
return statusMessage;
}
}
}Create the request handler (src/main/java/com/jrestless/aws/examples/RequestHandler.java):
package com.jrestless.aws.examples;
import com.jrestless.aws.gateway.GatewayResourceConfig;
import com.jrestless.aws.gateway.handler.GatewayRequestObjectHandler;
public class RequestHandler extends GatewayRequestObjectHandler {
public RequestHandler() {
// initialize the container with your resource configuration
init(new GatewayResourceConfig().packages("com.jrestless.aws.examples"));
// start the container
start();
}
}Build your function from within the directory aws-gateway-usage-example:
gradle buildThis, amongst other things, creates a deployable version of your function (build/distributions/aws-gateway-usage-example.zip) using the dependent task buildZip.
Now you can deploy the function using serverless:
serverless deployIf serverless is configured correctly, it should show you an endpoint in its output.
...
endpoints
ANY - https://<SOMEID>.execute-api.eu-central-1.amazonaws.com/dev/sample/{proxy+}
...
Hit the endpoint:
curl -H 'Accept: application/json' 'https://<SOMEID>.execute-api.eu-central-1.amazonaws.com/dev/sample/health'
# {"statusMessage":"up and running"}curl -H 'Accept: application/xml' 'https://<SOMEID>.execute-api.eu-central-1.amazonaws.com/dev/sample/health'
# <?xml version="1.0" encoding="UTF-8" standalone="yes"?><healthStatusDto><statusMessage>up and running</statusMessage></healthStatusDto>JRestless is split up into multiple modules whereas one has to depend on the *-handler modules, only. jrestless-aws-gateway-handler is probably the most interesting one.
All modules are available in jcenter.
- jrestless-aws-gateway-handler
- Provides an AWS Lambda RequestHandler that delegates requests from AWS API Gateway to Jersey.
- Read More...
- jrestless-aws-gateway-core
- Contains interfaces used by jrestless-aws-gateway-handler and might be of interest for local development, as well.
- Read More...
- jrestless-aws-service-handler
- Provides an AWS Lambda RequestHandler that delegates requests - in an HTTP format - to Jersey. This is intended but not limited to call one Lambda function from another.
- Read More...
- jrestless-aws-service-core
- Contains interfaces and classes used by jrestless-aws-service-handler, jrestless-aws-service-feign-client and might be of interest for local development, as well.
- Read More...
- jrestless-aws-service-feign-client
- Provides a feign client to call Lambda functions that use jrestless-aws-service-handler a.k.a. Lambda service functions. This allows to call Lambda service functions transparently through feign.
- Read More...
- jrestless-core-container
- Provides a generic (provider independent) Jersey container that handles requests in the form of POJOs.
- Read More...
- jrestless-test
- Provides common test functionality.
- Read More...
- Java
- lambadaframework provides similar functionality like JRestless. It implements some features of the JAX-RS standard and includes deployment functionality within the framework itself.
- ingenieux/lambada Non-JAX-RS Java framework
- aws-lambda-servlet run JAX-RS applications - uses Jersey and pretends to run in a servlet container
- JavaScript
- aws-serverless-express - run express applications
- Python
- for all function types
- stateless only (you could utilize some cache like Redis, though)
- AWS Lambda functions have a maximum execution time of 5 minutes
- currently no support for binary data in requests/responses (binary data gets encoded to base64, however, in JSON responses)
- Gateway functions
- AWS API Gateway has a timeout of 30 seconds
- Multiple headers with same name are not supported
- 0.3.0
- Add support for
AWS Lambda service functions. - Add support to call
AWS Lambda service functionsusing feign and the AWS SDK - allowing you to call those functions transparently via REST without using API Gateway.
- Add support for
- 0.2.0
- use the new
Lambda Function Proxyand catch-all paths provided by API Gateway (this reduces the framework's complexity and limitations significantly especially since the generation of a swagger definition is not necessary anymore)
- use the new
- 0.1.0 (-SNAPSHOT)
- (never released since the new features
Lambda Function Proxyand catch-all paths were released before) - add support for dynamic response Content-Type
- add support for custom response headers
- (never released since the new features
- 0.0.1
- intial release
Distributed under Apache 2.0 license. See License for more information.

