Skip to content

WTI API Project Implementation Details

John Clevenger edited this page Apr 21, 2020 · 28 revisions

Overview

WTI-API is an Eclipse Java EE (Enterprise Edition) project which provides the "back-end" code for the PC2v9 Web Team Interface (WTI). The services provided by the WTI-API project are accessed by the WTI-UI project, which implements the "front-end" (browser-side) portion of the overall WTI web team interface. Like the WTI-UI project, the WTI-API Java Project is housed in the projects folder of the pc2v9 project.

The WTI project was developed by a team of students from Eastern Washington University (EWU) consisting of Josie Isaacson, Andrew Combs, Ethan Holman, and Danielle Frodge, under the direction of EWU Professor Tom Capaul. The project was ported into the Eclipse and pc2v9 GitHub environments by John Clevenger.

The WTI-API project comprises several components, including:

  • a Swagger/OpenAPI API specification which defines the REST API accessible by the WTI-UI front-end;
  • a Jetty webserver which serves web pages (via the Swagger API) to the front-end WTI-UI project;
  • Jersey, an implementation of the JAX-RS specification, for handling HTTP requests made to the Jetty webserver;
  • Jackson, a set of tools for parsing and processing JSON;
  • a set of back-end services which listen via the PC2v9 API to a running PC² Server and forward messages via websockets from the PC² Server to the WTI-UI front-end code running in team browsers;
  • a websockets package which provides support for passing messages between the WTI-API back-end and the WTI-UI front-end.

Project Environment

WTI-API is implemented as a Java EE dynamic web application project. Eclipse with support for Java EE (Enterprise Edition) Version 8 or higher is recommended when developing code for the WTI-API project.

The following tool versions are contained in the WTI-API project libraries:

  • Jetty - version 9.4.14 - 9.4.15
  • Swagger - version 1.5.21
  • Jackson - version 2.9.8
  • Jersey - version 2.28

Swagger/OAS API

The WTI-API project creates an Application Program Interface (API) which is accessed by the WTI-UI front-end project. The API is documented using Swagger. Specifically, starting the WTI-API web team server (using the default settings) and then opening http://localhost:8080/swagger will return a Swagger web page showing the definition of the WTI-API project API endpoints. This documents the API which the WTI-UI front-end (or any client of WTI-API) can access.

The Swagger API documentation is dynamically generated at runtime by the Swagger libraries which are attached to the project's Jetty server (see below). Conceptually, the API is described by a file swagger.json (meaning, this is the file which specifies the content of the API web page displayed by opening the http://localhost:8080/swagger URL). The actual swagger.json text can be viewed by opening http://localhost:8080/api/swagger.json.

Note that there is not actually any swagger.json file anywhere in the project. Rather, when the Jetty server Swagger endpoints are referenced, the associated Swagger library routines scan the web app code for JAX-RS and Swagger annotations and use the resulting information to dynamically construct the Swagger API documentation. An important characteristic of this approach is that the Swagger documentation will always be "up to date"; any changes to API endpoint code in the project will be automatically reflected in the dynamically-generated documentation.

WTI-API Architecture Overview

TODO: update this section: move code-level details to the "Code" section, below. Also, finish the "high-level overview"...

The WTI-API project is organized using a Model-View-Controller (MVC) architecture. Conceptually the top-level controller is the class MainController. However, MainController is abstract; it has two concrete subclasses TeamsController and ContestController.

The WTI-API startup sequence (see below) arranges that when an external client, such as the WTI-UI project, attempts to login to the WTI web team server, the server transfers control to the login() method of a new instance of the TeamsController class (thus, there is one TeamsController for each team login; perhaps the class would have been better named as "TeamController").

The process of instantiating a TeamsController includes executing the superclass (MainController) constructor, which creates a new WTIWebsocket connection between the team client and the WTI server.

Top-level Project Organization

The WTI-API project is organized into three primary "source code" packages:

  • src, which contains a folder main housing source for the major WTI-API components, including:
    • config, holding the classes used for configuring and managing the Jetty server, as well as for providing the project logging facilities
    • controllers, containing ... TODO
    • jerseyConfig, which holds... TODO
    • models, containing... TODO
    • services, which holds... TODO
  • websockets, which houses types and classes used to support websocket communications between the WTI-UI front-end and this WTI-API back-end
  • tests, a collection of JUnit tests for various WTI-API components.

The top-level project also contains the following:

  • a set of libraries holding library packages used by both the WTI-API front-end and the WTI-UI back-end projects.
  • build and dist folders used during the WTI-API build process for creating distributable versions of the project. (Note that build and/or dist may be empty, depending on whether and how the WTI-API project has been built on the current system. See WTI Build Package Details for additional information).
  • demo, a folder holding the final "demo" version of the WTI project by the EWU student team (which may still be relevant because it may include efforts at demoing the not-completed support for Test Runs in the WTI system).
  • doc, a folder containing both the current WTI project documentation and the set of documentation developed by the EWU students during their project.
  • scripts, holding the Windows and Unix scripts used to start the WTI web team server.
  • testfiles, which contains a collection of "HelloWorld" programs in several languages used for testing the WTI system.
  • WebContent, a folder holding the "dynamic web content" for the WTI project. This includes the following sub-folders:
    • WEB_INF, containing a lib folder holding the .jar libraries used by the web application.
    • webapp, containing the resources (such as the Swagger definition files) defining the external view of the web application.

In addition, the top level of the WTI-API project contains standard Eclipse/Git files such as .classpath, .project, and .gitignore. It also contains the buildWTI.xml and packageWTI.xml files used for building the project, along with the pc2v9.ini file used to initialize the project at runtime. The readme.md file that accompanied the original EWU project is also included, although it is likely out of date.

Code Details

Startup Sequence

The main entry point for the WTI-API web application is config.JettyConfig.main(String[] args); this entry point (herein after referred to as just main()) is the entry point which is configured into the WebTeamInterface-1.1.jar manifest (and hence is what gets executed when WebTeamInterface-1.1.jar is invoked as a runnable jar).

The main() method creates a ServerInit object, which instantiates a Logging object for handling logging and then reads the pc2v9.ini file to obtain configuration parameters (such as the port number on which the Jetty server should listen for browser connections and the base name to be used for naming websockets). These logging and configuration parameter values are saved in the ServerInit object.

Next, main() invokes ServerInit static method updateUIAppConfig(). This method obtains the IP address for the machine on which it is running and then constructs URLs for HTTP and WebSocket (ws) connections to the machine using the local IP address along with the port and websocket name values read from the pc2v9.ini file. It then saves these URLs in a file WebContent/WTI-UI/assets/appconfig.json where is is subsequently used by the WTI-UI project (see WTI-UI-Project-Implementation-Details#environments).

Finally, main() invokes WebServer.startServer(), passing it the ServerInit object created above. This method creates a list of Jetty handlers, including

  • a ServletContextHandler websocket handler which is initialized with WTI class communication.WTIWebsocketMediator as the class to which websocket requests at ServerEndpoint("/WTISocket/{team_id}") should be routed.
  • a ContextHandler swagger handler which is initialized with the Web resource information found in ./WebContent/webapp, which includes the WTI-API project Swagger interface definition JavaScript files.
  • a ContextHandler webapp handler which is initialized with the Web resource information found in ./WebContent/WTI-UI, which contains the assets and resources of the WTI-UI front-end project. (Note that there is no ./WebContent/WTI-UI folder in the WTI-API Java project; this folder structure is put into the runtime distribution by the WTI-API build process -- see WTI Build Package Details for additional information.)
  • a ServletContextHandler jersey api handler which is initialized with a Context Path of /api and with a ServletContainer holding a variety of service provider class names. The service providers in the jersey api handler include:
    • the following classes which map to the path */:
      • org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJaxbJsonProvider
      • org.glassfish.jersey.jackson.JacksonFeature
      • the WTI TeamsController
      • the WTI ContestController
    • the class DefaultJaxrsConfig.class which maps to the path /swagger-core
    • a jetty.servlet.FilterHolder containing filtering support for CORS.

The net effect of the above is to define a list of handlers for the various WTI end-points.

startServer() then instantiates a Jetty Server listening on the specified port, sets the handler list into the Server, and starts the Server running. The overall effect is that the Jetty server listens at the specified port for requests having the /api/ context path and routes all such requests to the appropriate Jersey, Swagger, or websocket servlet.

The final step in startServer() is to execute server.join(), which has the effect of blocking until the Jetty server is terminated.

Controllers

The WTI-API project is

  • Abstract MainController
    • Constructing a MainController creates two things: a WTIWebsocket and a Logger.
  • ContestController extends MainController
  • TeamsController extends MainController ... TODO: finish this section

Models

... TODO: finish this section

Services

... TODO: finish this section

Websocket Message Handling

Websocket connections between the WTI-UI front-end and the WTI-API back-end are initiated during the login process invoked by the WTI-UI front-end (see WTI-UI websockets).

Incoming websocket requests received by Jetty are routed to the WTIWebsocketMediator class. This class defines four methods, each with a Java EE Annotation indicating the conditions under which it is invoked:

  • @OnOpen connect(): this method receives the javax.websocket.Session and the team-id associated with the newly-opened websocket and saves them in corresponding data structures.
  • @OnMessage message(): this method... TODO: finish this section
  • @OnClose close(): this method receives a Session and a teamId; it searches the current sessions table for a Session associated with the specified teamId and if such a session is found it is removed from the table.
  • @OnWebsocketError onError(): this method is invoked when a websocket error has occurred. It currently just displays an error message on the console; this should be changed so that errors are logged.

Various classes in the WTI-API project need to send message through websockets to remote endpoints (i.e., to a team's browser session). This is handled by... TODO: finish this section

See Also

PC2 Logo

Clone this wiki locally