Anytime I wanted to create an endpoint, I had only used Node.js in the past. This time around I wanted to use Java and found it non-trivial to find out how to get started quickly, so this should help you.
We will build a simple status endpoint using undertow, resteasy and weld.
Editor
I am using IntelliJ IDEA to build my application.
Terminologies
Here are a few terminologies to know in order to understand what’s going on:
JBoss - is a division of Red Hat that provides support application server and middleware services.
Undertow - is a performant web server written in java. It is fully embeddable meaning you don’t need to have this web server running on the box before deploying your code unlike the others out there. Meaning you can just deploy a fat jar or a jar + all dependencies in an archive. I’ve had brief experience with jetty a while back. Undertow is sponsored by JBoss.
Servlet - a class or a program that runs inside the web server to handle incoming requests. It usually runs inside a Servlet container
JAX-RS - Java API for RESTful Web Services is a spec for creating web services as per the REST architecture.
RestEasy is JBoss’s implementation of the JAX-RS specification.
CDI - Context and dependency injection
Weld - is an implementation of the CDI standard
Dependencies To Add
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<version>3.1.0-Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-undertow</artifactId>
<version>3.1.0-Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-cdi</artifactId>
<version>3.1.0-Final</version>
</dependency>
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet</artifactId>
<version>2.4.1.Final</version>
</dependency>
resteasy-jackson is mainly used for creating codehaus jackon annotations for your response
resteasy-undertow - brings in the underdow webserver
resteasy-cdi - is the bridge that helps RESTEasy fetch an instance of the class that serve an incoming request from the CDI container.
weld-servlet - Nothing works without weld. I am still struggling to define the scope of this package.
Main - Starting Point
UndertowJaxrsServer server = new UndertowJaxrsServer();
ResteasyDeployment deployment = new ResteasyDeployment();
deployment.setApplicationClass(ExampleApplication.class.getName());
deployment.setInjectorFactoryClass("org.jboss.resteasy.cdi.CdiInjectorFactory");
DeploymentInfo deploymentInfo = server.undertowDeployment(deployment, "/");
deploymentInfo.setClassLoader(Main.class.getClassLoader());
deploymentInfo.setDeploymentName("Example");
deploymentInfo.setContextPath("/v1");
deploymentInfo.addListener(Servlets.listener(org.jboss.weld.environment.servlet.Listener.class));
server.deploy(deploymentInfo);
server.addResourcePrefixPath("/",
Handlers.resource(
new ClassPathResourceManager(
Main.class.getClassLoader()))
.addWelcomeFiles("index.html"));
Undertow.Builder builder = Undertow.builder().addHttpListener(8080, "0.0.0.0");
server.start(builder);
This is setting up Undertow server to start on port 8080 on your localhost. Using 0.0.0.0 is better in case you want to run this application inside a docker container.
With the ResteasyDeployment stuff, we are simply saying that all the JAX-RS components you want to use for handling incoming network requests are defined by the ExampleApplication class file. This is where we’ll specify the handler for Status endpoint. The rest of it is boiler plate code.
ExampleApplication
public class ExampleApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
final Set<Class<?>> clazzes = new HashSet<>();
clazzes.add(Status.class);
return clazzes;
}
}
Defines the application that specifies all the JAX-RS components. IN our case, it’ll just be the Status class.
Status
@Path("/status")
public class Status {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getStatus() {
return Response.ok().build();
}
}
A class becomes a JAX-RS component when it explicitly defines @Path or other annodtations.
Conclusion
Finally, when you run the Main class, the server should start and going to http://127.0.0.1:8080/v1/status should give you a 200.
Credits Undertow embedded example - I was stuck trying to make this example work with a fat jar and then gave up realizing weld has issues running in one. If someone knows how to get this to work with a fat jar, let me know. I’ll be excited to know how you did that, having spent hours on it.