A Little JSON Rest Server
Java Shell
Switch branches/tags
Nothing to show
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
example
src/main
.gitignore
README.mdown
pom.xml
run_example.sh

README.mdown

ALJeeRS

A Little JSON (ignore the e's) Rest Server.

This project is a super simple wrapper around Jetty that allows you to easily get JSON requests and send JSON responses.

Running examples via the console

  • install maven (or make sure mvn is in your path)
  • run ./run_example.sh
  • cruise on over to http://localhost:8080/fe to check out the simple console

The console lets you make GET, PUT, POST, HEAD and DELETE request against any of the configured handlers. If you're running the example you'll be able to hit a bunch of methods in the ExampleHandler and see what their output looks like...

Running the app

The app is just a Java app with Jetty embeded... so you can run it the same way you run any Java app. The main class is com.phatduckk.aljeers.Aljeers. The only "special" thing it needs is a property that tells it what config file to use.

The config is just a properties file where the keys are a URI "prefix" and the values are a full qualified class name. If you look at the example/example.conf file you'll see 2 registered handlers...

/example = com.phatduckk.aljeers.example.ExampleHandler
/fe = com.phatduckk.aljeers.handler.FrontendHandler

This tells the app that when a request comes in for /example/FOO the FOO method in the class com.phatduckk.aljeers.example.ExampleHandler should be executed.

Writing a handler

  • write a class that extends BaseHandler
  • all public methods are eligible to be accessed via a URI
    • to make a method accessible
      • its signature must match public methodNameHere(HttpServletRequest req, HttpServletResponse resp)
      • you need to annotate it with @GET, @POST, @PUT, @DELETE or @HEAD to define what HTTP methods are allowed
    • the method can throw any Throwable it wants...
    • anything returned from the method will be JSON-encoded and sent to the client
      • Throwables are also JSON encoded
      • the response body will contain the serialized response
  • edit the server's config file to register your handler with a URI prefix /my_prefix = com.example.you.handler.YourNewHandler
  • restart the app and tell it to use your config file -Dconf.handlers=your_config_file.conf

Debugging

  • including a X-Aljeers-Debug: true header or a x-aljeers-debug=true query string param will get you into debug mode
    • debug mode is strictly to make it easy to look at calls thru a browser/curl and shouldn't be used otherwise
    • your output will be pretty-printed
    • the body of the response will contain a bunch more info
      • status HTTP ststus of the response
      • responseType fully qualified class name of the returned payload (ex: java.util.HashMap)
      • simpleResponseType a simple representation of responseType (ex: HashMap)
    • the frontend console has a convenient checkbox to toggle debug mode on/off

Example: write a handler, configure it, compile the project & run it...

Here's a condensed version of the code in the ExampleHandler

package com.example.you;

import com.phatduckk.aljeers.handler.BaseHandler;
import com.phatduckk.aljeers.handler.annotations.GET;
import com.phatduckk.aljeers.handler.annotations.HEAD;
import com.phatduckk.aljeers.handler.annotations.POST;
import com.phatduckk.aljeers.handler.annotations.PUT;
import com.phatduckk.aljeers.example.User;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class YourHandler extends BaseHandler {
    @GET
    /**
     * String response
     */
    public Object endpointThatReturnsAString(HttpServletRequest req, HttpServletResponse resp) {
        return "Hello there";
    }

    @GET
    /**
     * String response based on a query string param
     */
    public Object endpointThatGrabsAQueryStringParameter(HttpServletRequest req, HttpServletResponse resp) {
        return "Hello there " + req.getParameter("name");
    }

    @GET
    /**
     * An error
     */
    public Object endpointWithError(HttpServletRequest req, HttpServletResponse resp) throws Throwable {
        throw new Exception("balls, shit broke");
    }

    @POST
    /**
     * This one's a bit interesting...
     *
     * This method expects the entire body of an HTTP POST to be a JSON representation of a
     * com.phatduckk.aljeers.example.User class
     *
     * The getObjectFromRequest() method will map the request's body to a com.phatduckk.aljeers.example.User class.
     * The code then sets a couple properties on the user (email) and returns it. (BS use case but its an example...)
     *
     * You can try this out using the console frontend
     */
    public Object postAUser(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        User user = null;
        try {
            user = (User) getObjectFromRequest(req, User.class);
            user.setEmail("arin@example.com");
        } catch (IOException e) {
            throw new Exception("Include a JSON representation of a user in the POST body. Ex: {\"name\": \"John Doe\"}");
        }

        return user;
    }
}

Once you've written the code you need to update your config file (ex: path/to/your/handlers.conf) and add:

/my_prefix = com.example.you.YourHandler

Now compile your code

mvn compile
mvn package

Run the app

java -Dconf.handlers=path/to/your/handlers.conf  -jar target/aljeers-1.0-SNAPSHOT-jar-with-dependencies.jar

Test an endpoint

String response at:

http://localhost:8080/my_prefix/endpointThatReturnsAString
or
http://localhost:8080/my_prefix/endpointThatGrabsAQueryStringParameter?name=bill

check out an error response:

http://localhost:8080/my_prefix/endpointWithError

POST a user

curl -d "{\"name\": \"arin\"}" http://localhost:8080/my_prefix/postAUser && echo ""

turn debug mode on and try it again

curl "X-Aljeers-Debug:true" -d "{\"name\": \"arin\"}" http://localhost:8080/my_prefix/postAUser && echo ""

Or enable the Frontend console in path/to/your/handlers.conf and test from http://localhost:8080/fe

/fe = com.phatduckk.aljeers.handler.FrontendHandler

TODO:

  • wrap up the request and response objects
    • expose a getStatus() method on the response
    • expose easy getInt(paramName, defaultValue) type methods on the request object
  • deal with headers better
  • standardize the response payload
  • write some unit tests
  • test/optimize performance
  • make console pretty