Skip to content

Commit

Permalink
Merge pull request #1 from Spaceman1701/feature/docs
Browse files Browse the repository at this point in the history
Basic Documentation
  • Loading branch information
Spaceman1701 committed Dec 25, 2018
2 parents b7775f4 + 69ba9a7 commit 3415d0b
Show file tree
Hide file tree
Showing 15 changed files with 645 additions and 0 deletions.
4 changes: 4 additions & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.vscode
_static
_build
_templates
19 changes: 19 additions & 0 deletions docs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SOURCEDIR = .
BUILDDIR = _build

# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
6 changes: 6 additions & 0 deletions docs/concepts/autoconfig.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Automatic Configuration
=======================

Control how generated code is used. Autoconfiguration can be accessed using the ``AutoConfigurationFactory``.
This singleton factory class can be used to access the configuration objects that Lighter generates at compile
time. Normally, applications will access this class to load the route configuration instance to pass to ``Lighter.Builder``.
102 changes: 102 additions & 0 deletions docs/concepts/endpoints.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
Endpoints
=========

Endpoints are the core of any Lighter application. They allow the application to interact
with the outside world. In Lighter, endpoints are methods that are identified using an endpoint annotation.
In the current MVP version of Lighter the endpoint annotations are ``@Get``, ``@Post``,
``@Put``, and ``@Delete``. Each of these annotations corresponds to an HTTP method.

Endpoints must always return a ``Response``. See the *Response API* docs page for details
about constructing responses.

Endpoint Annotations
--------------------

All of the endpoint annotations have the same API. Each one has an optional ``value`` field which can
be used to define a path template stub that the endpoint method should respond to. The full path template that
defines the endpoint is constructed by prepending the endpoint's Resource Controller path stub to the stub provided
in the endpoint annotation. See more about this in the Resource Contollers section below.

In order to handle HTTP requests, Lighter matches the request method and path against the set of endpoint methods
and path templates in the application. Method parameters are fulfilled by path parameters, query parameters, and the
request body.

Resource Controllers
--------------------

Every endpoint method must be a member of a ``@ResourceController`` annotated class. Resource Controllers are plain Java classes.
Resource Controllers must specify a path template stub that will be prepended to all of their members. This is useful as it avoids
the necessity of rewriting parts of a the template multiple times for related endpoints.

Resource Controllers will be instaintiated by Lighter. Thus, they must be instaintiable by the ``InjectionObjectFactory``. See the docs
page on the Injection API for details.

Path Template Syntax
--------------------

Path template syntax is similar to other web frameworks. Templates can contains three types of components:
Normal, Parameter, and Wildcard. Normal components match components exactly equal to themsevles. A path template
made of only Normal components would match only paths that are identical to it. Parmaeter components will match anything and
bind it to the provided name. Parmaeters are denoted by surrounding a name with ``{`` and ``}``. Every parameter
as a type which is inferred from the method signature. Wildcard components are denoted by a ``*`` and greedly match
any number of components.

Here are some examples:

The template ``foo/bar/123`` will match
exactly the path ``foo/bar/123`` and nothing else.

The template ``foo/bar/{id}`` will match
any path with exactly 3 components that begins with ``foo/bar/``. The third component of
the path will be bound to the name "id".

The template ``foo/bar/*`` will match
any path that begins with ``foo/bar/``.

The template ``foo/*/bar`` will match
any path that begins with ``foo`` and ends with ``bar``


Query Parameters
----------------

HTTP query parameter bindinds can be specified in a similar way to path Parmaeter components. However, query parameters
do not appear as part of the path template. Instead, the ``@QueryParameters`` annotation is used to provide a list of
name bindings. Since the names of query parameters are exposed as part of the applications API, Lighter allows external
and internal names of query parameters to differ. The external (*exposed*) name is what HTTP calls should use. The internal
(*mapped*) name should match the name of the parameter on the Java endpoint method.

Query parmaeter names are specified using an array of Strings. Exposed names and mapped names are seperated by a ``:``.
If only one name is provided, Lighter assumes the exposed name is identical to the mapped name.

Here are some examples:

The parameter ``foo:bar`` specifies
an exposed name ``foo`` which maps to a parameter on the Java method named ``bar``

The parameter ``foo`` specifies
an exposed name ``foo`` which maps to a parmaeter on the Java method named ``foo``

Similar to path Parameters, query parameter types are inferred from the Java method.

Accessing the Request Body
--------------------------

The request body content can be mapped to any method parameter by annotating it with ``@Body``. The type of
the body content is infered from the method.

Parameter Type Inference
------------------------

All endpoint parameter types are inferred from the Java method signature. Any Java type can be used as long
as the application ``TypeAdapterFactory`` is capable of producing a ``TypeAdater`` for the type. Query and
path parameters are assumed to have a MIME Media Type of ``text/plain``. The Media Type of the request body
is determined by the Content-Type header.

If a method parameter is optional (i.e. an error should not occur if Lighter can not provide data for the parameter),
it should have a type of ``java.util.Optional`` (or one of the allied Optional types provided in the standard library). Since
Lighter performs type inference at compile time, it is able to use the generic type parameter of ``Optional`` for serialization
and deserialization logic.

Lighter **will never** provide a ``null`` value for a method parameter. If a non-Optional parameter can not be provided for
any reason, Lighter will throw an error.
15 changes: 15 additions & 0 deletions docs/concepts/injection.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Injection API
=============
Control how your classes get instantiated by Lighter. The primary class applications
will interact with is the ``InjectionObjectFactory``. This functional interface is designed
to provide a implementation agnostic API for dependency injection containers. The interface is
very simple as it is only used when Lighter needs to construct a class for the application.

The interface is designed to match the Guice ``Injector#newInstance`` method.

The other class used for dependency construction is the ``ReverseInjector``. Implementations
of ``ReverseInjector`` provide an instance of ``InjectionObjectFactory``. Lighter will automatically
generate an implementation of ``ReverseInjector`` that has a setter for every dependency Lighter will
need to construct. The auto generated implementation conforms to Java Beans and javax.Inject standards
for dependency Injection. This implementation can be used as a configuration bean with dependency injection
frameworks that do not have an Injector class (like Dagger 2).
6 changes: 6 additions & 0 deletions docs/concepts/intro.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Using Lighter
=============
This section will provided overviews for all of the concepts required to develop real
applications with Lighter. This isn't API documentation. Instead, each page will contain
a detailed overview of one of Lighter's core concepts. This will be useful for determining
what features can solve which problems. Each page will also contain examples where appropriate.
12 changes: 12 additions & 0 deletions docs/concepts/lighter.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Lighter API
===========
Construct and interact with the ``Lighter`` instance. The ``Lighter`` object represents the
application itself. Lighter instances can only be constructed using the ``Lighter.Builder`` API.
This fluent API provides many configuration options for Lighter.

Both ``Lighter`` and ``Lighter.Builder`` are interfaces which define what configuration options and
operations all Lighter backends must support. Backends can choose to implement extra operations. The
Undertow backend (which is currently the only backend), provides only the required methods.

Lighter runs asycronously. ``Lighter#start`` returns as soon as the server is started. This allows the main
thread to be used for controlling Lighter.
29 changes: 29 additions & 0 deletions docs/concepts/request_guards.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
Request Guards
==============

Request guards allow your application to define preconditions to endpoint execution. This
feature is inspired by one of Ligther's primary inspirations: `Rocket Web Framework`_.

.. note:: This feature is currently in early stages of development. Expect lots of changes.

.. _Rocket Web Framework: https://rocket.rs/

Request Guards are special endpoint method dependencies that are not constructed directly
from the request. Instead, Request Guards are constructed by application defined logic
using a ``RequestGuardFactory``. Request Gaurds are identified using the ``RequestGuard``
marker interface. RequestGuardFactories are identified using the ``RequestGuardFactory`` interface
and the ``@ProducesRequestGuard`` annotation.

.. note:: The RequestGuardFactory API is an area that is targeted for change in the future. It is very
awkward to require both an interface and annotation to mark RequestGuardFactories.

Since Request Guards are constructed by application logic, they can be used to define custom pre-requesite
conditions for endpoints. In order to use a Request Guard, the endpoint method must simply add a parameter
of a ``RequestGuard`` type. Lighter will determine how to fulfill that requirement at compile time.

.. note:: Currently, Lighter does not support Optional Request Guards. This feature will be added soon.

.. note:: Request guard errors current cause a ``500 - Internal Server Error``. In the future, the API will
allow more control over how Request Guard construction errors occur.

RequestGuards are the idiomatic way to implement authentication and other cross-cutting concerns.
43 changes: 43 additions & 0 deletions docs/concepts/response_api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
Response API
============

The response API allows your application to return data to the outside world. Since every endpoint
must return a response, the API is designed to be very concise. However, applications will have
extemely variable requirements for Response structure, so the API also allows a great deal of
flexibility. In addition to this, Responses must be easy to use in unit tests.

The main class that applications will interact with is the ``Reponse`` class. To the user, ``Response`` is
a Plain Old Java Object. ``Response`` is immutable and method calls have no side effects. In addition to
``Response``, applications will interact with instances of the ``ResponseDecorator`` functional interface.
the ``Response#with`` method provides a fluent API for adding decorators to the ``Response`` object. This
is the primary way to build custom responses.

Lighter also provides the ``Responses`` static factory class with utility methods for constructing common HTTP
response types. ``Responses`` has methods for constructing ``3xx - Redirect``, JSON content, and no content
responses.

The Response API is type safe. The ``Response`` class type parameter is used to represent the type of the
response body content. ``ResponseDecorator`` application can change the type parameter. This allows chains
of decorator application to maintain type safety. ``java.lang.Void`` is used to represent an empty response.

Using Response
--------------

The ``Response`` class does not contain the serialized data. Instead, it contains a reference to the Java
object that will be serialized. Lighter uses the top level ``TypeAdapterFactory`` to serialize the content.
Lighter ensures that the type is serialized with the correct MIME Media Type by reading the Content-Type header
on the response.

When using the ``Response`` for unit testing endpoints, the Java object is directly available.

Standard Response Decorators
----------------------------

Lighter provides a few standard response decorators. These allow most required responses to be constructed.
Since ``ResponseDecorator`` is a functional interface, lambda functions can also be used.

The provided decorators are:

* HeaderResponse - adds a header to the response
* StatusResponse - sets the response status code
* JsonContent - adds an object as the response body and sets the content-type header to ``application/json``

0 comments on commit 3415d0b

Please sign in to comment.