|
1 | | -package edu.lehigh.cse216.mfs409.admin; |
| 1 | +package merhoo.backend; |
2 | 2 |
|
3 | | -import java.sql.Connection; |
4 | | -import java.sql.DriverManager; |
5 | | -import java.sql.SQLException; |
6 | | -import java.util.Map; |
| 3 | +// Import the Spark package, so that we can make use of the "get" function to |
| 4 | +// create an HTTP GET route |
| 5 | +import spark.Spark; |
| 6 | + |
| 7 | +// Import Google's JSON library |
| 8 | +import com.google.gson.*; |
7 | 9 |
|
8 | 10 | /** |
9 | | - * App is our basic admin app. For now, all it does is connect to the database |
10 | | - * and then disconnect |
| 11 | + * For now, our app creates an HTTP server that can only get and add data. |
11 | 12 | */ |
12 | 13 | public class App { |
13 | | - /** |
14 | | - * The main routine reads arguments from the environment and then uses those |
15 | | - * arguments to connect to the database. |
16 | | - */ |
17 | | - public static void main(String[] argv) { |
18 | | - // get the Postgres configuration from the environment |
19 | | - Map<String, String> env = System.getenv(); |
20 | | - String ip = env.get("POSTGRES_IP"); |
21 | | - String port = env.get("POSTGRES_PORT"); |
22 | | - String user = env.get("POSTGRES_USER"); |
23 | | - String pass = env.get("POSTGRES_PASS"); |
| 14 | + public static void main(String[] args) { |
24 | 15 |
|
25 | | - // Some students find that they need the following lines |
26 | | - // *before DriverManager.getConnection* in order to get the postgres |
27 | | - // driver to load |
| 16 | + // gson provides us with a way to turn JSON into objects, and objects |
| 17 | + // into JSON. |
| 18 | + // |
| 19 | + // NB: it must be final, so that it can be accessed from our lambdas |
| 20 | + // |
| 21 | + // NB: Gson is thread-safe. See |
| 22 | + // https://stackoverflow.com/questions/10380835/is-it-ok-to-use-gson-instance-as-a-static-field-in-a-model-bean-reuse |
| 23 | + final Gson gson = new Gson(); |
28 | 24 |
|
29 | | - // try { |
30 | | - // Class.forName("org.postgresql.Driver"); |
31 | | - // } catch (ClassNotFoundException cnfe) { |
32 | | - // System.out.println("Unable to find postgresql driver"); |
33 | | - // return; |
34 | | - // } |
| 25 | + // dataStore holds all of the data that has been provided via HTTP |
| 26 | + // requests |
| 27 | + // |
| 28 | + // NB: every time we shut down the server, we will lose all data, and |
| 29 | + // every time we start the server, we'll have an empty dataStore, |
| 30 | + // with IDs starting over from 0. |
| 31 | + final DataStore dataStore = new DataStore(); |
35 | 32 |
|
36 | | - // conn is a connection to the database. In this simple example, it is |
37 | | - // a local variable, though in a realistic program it might not be |
38 | | - Connection conn = null; |
| 33 | + // GET route that returns all message titles and Ids. All we do is get |
| 34 | + // the data, embed it in a StructuredResponse, turn it into JSON, and |
| 35 | + // return it. If there's no data, we return "[]", so there's no need |
| 36 | + // for error handling. |
| 37 | + Spark.get("/messages", (request, response) -> { |
| 38 | + // ensure status 200 OK, with a MIME type of JSON |
| 39 | + response.status(200); |
| 40 | + response.type("application/json"); |
| 41 | + return gson.toJson(new StructuredResponse("ok", null, dataStore.readAll())); |
| 42 | + }); |
39 | 43 |
|
40 | | - // Connect to the database or fail |
41 | | - System.out.print("Connecting to " + ip + ":" + port); |
42 | | - try { |
43 | | - // Open a connection, fail if we cannot get one |
44 | | - conn = DriverManager.getConnection("jdbc:postgresql://" + ip + ":" + port + "/", user, pass); |
45 | | - if (conn == null) { |
46 | | - System.out.println("\n\tError: DriverManager.getConnection() returned a null object"); |
47 | | - return; |
| 44 | + // GET route that returns everything for a single row in the DataStore. |
| 45 | + // The ":id" suffix in the first parameter to get() becomes |
| 46 | + // request.params("id"), so that we can get the requested row ID. If |
| 47 | + // ":id" isn't a number, Spark will reply with a status 500 Internal |
| 48 | + // Server Error. Otherwise, we have an integer, and the only possible |
| 49 | + // error is that it doesn't correspond to a row with data. |
| 50 | + Spark.get("/messages/:id", (request, response) -> { |
| 51 | + int idx = Integer.parseInt(request.params("id")); |
| 52 | + // ensure status 200 OK, with a MIME type of JSON |
| 53 | + response.status(200); |
| 54 | + response.type("application/json"); |
| 55 | + DataRow data = dataStore.readOne(idx); |
| 56 | + if (data == null) { |
| 57 | + return gson.toJson(new StructuredResponse("error", idx + " not found", null)); |
| 58 | + } else { |
| 59 | + return gson.toJson(new StructuredResponse("ok", null, data)); |
48 | 60 | } |
49 | | - } catch (SQLException e) { |
50 | | - System.out.println("\n\tError: DriverManager.getConnection() threw a SQLException"); |
51 | | - e.printStackTrace(); |
52 | | - return; |
53 | | - } |
54 | | - System.out.println(" ... successfully connected"); |
| 61 | + }); |
55 | 62 |
|
56 | | - System.out.print("Disconnecting from database"); |
57 | | - try { |
58 | | - conn.close(); |
59 | | - } catch (SQLException e) { |
60 | | - System.out.println("\n\tError: close() threw a SQLException"); |
61 | | - e.printStackTrace(); |
62 | | - return; |
63 | | - } |
64 | | - System.out.println(" ... connection successfully closed"); |
| 63 | + // POST route for adding a new element to the DataStore. This will read |
| 64 | + // JSON from the body of the request, turn it into a SimpleRequest |
| 65 | + // object, extract the title and message, insert them, and return the |
| 66 | + // ID of the newly created row. |
| 67 | + Spark.post("/messages", (request, response) -> { |
| 68 | + // NB: if gson.Json fails, Spark will reply with status 500 Internal |
| 69 | + // Server Error |
| 70 | + SimpleRequest req = gson.fromJson(request.body(), SimpleRequest.class); |
| 71 | + // ensure status 200 OK, with a MIME type of JSON |
| 72 | + // NB: even on error, we return 200, but with a JSON object that |
| 73 | + // describes the error. |
| 74 | + response.status(200); |
| 75 | + response.type("application/json"); |
| 76 | + // NB: createEntry checks for null title and message |
| 77 | + int newId = dataStore.createEntry(req.mTitle, req.mMessage); |
| 78 | + if (newId == -1) { |
| 79 | + return gson.toJson(new StructuredResponse("error", "error performing insertion", null)); |
| 80 | + } else { |
| 81 | + return gson.toJson(new StructuredResponse("ok", "" + newId, null)); |
| 82 | + } |
| 83 | + }); |
65 | 84 | } |
66 | 85 | } |
0 commit comments