JRestless allows you to create serverless applications using JAX-RS.
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.
Supported Environments:
The motivation for this project is to avoid a cloud vendor lock-in and to allow developers to run and test their code locally.
@javax.ws.rs.core.Context
into resources and endpoints:
com.amazonaws.services.lambda.runtime.Context
.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/guide/credentials/
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 # remove the classes created by the template
mkdir -p src/main/java/com/jrestless/aws/examples # create the package structure
Replace 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.6.0',
'org.glassfish.jersey.inject:jersey-hk2:2.26',
'org.glassfish.jersey.media:jersey-media-json-jackson:2.26'
)
}
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 response object (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;
@Path("/sample")
public class SampleResource {
@GET
@Path("/health")
@Produces({ MediaType.APPLICATION_JSON })
public Response getHealthStatus() {
return Response.ok(new HealthStatusResponse("up and running")).build();
}
static class HealthStatusResponse {
private final String statusMessage;
HealthStatusResponse(String statusMessage) {
this.statusMessage = statusMessage;
}
public String getStatusMessage() {
return statusMessage;
}
}
}
Create the request handler (src/main/java/com/jrestless/aws/examples/RequestHandler.java
):
package com.jrestless.aws.examples;
import org.glassfish.jersey.server.ResourceConfig;
import com.jrestless.aws.gateway.GatewayFeature;
import com.jrestless.aws.gateway.handler.GatewayRequestObjectHandler;
public class RequestHandler extends GatewayRequestObjectHandler {
public RequestHandler() {
// initialize the container with your resource configuration
ResourceConfig config = new ResourceConfig()
.register(GatewayFeature.class)
.packages("com.jrestless.aws.examples");
init(config);
// start the container
start();
}
}
Build your function from within the directory aws-gateway-usage-example
:
gradle build
This, 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 deploy
If 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"}
A very good example of how to use JRestless on Fn Project can be found here: https://github.com/fnproject/fn-jrestless-example
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.
Distributed under Apache 2.0 license. See License for more information.