Contents:
In a previous assignment, UW Marketing commissioned you to write a route finder tool. Marketing is pleased with your initial results, but now they've asked for a graphical user interface (GUI) that visually draws routes on a map.
You will build your GUI using React (like in the Connect the Dots assignment) and the Spark Framework. Unlike the pathfinder and Connect the Dots assignments, this time you are building both the frontend and the backend! You will get practice using these tools, event-driven programming, and the model-view-controller (MVC) design pattern. You'll probably write less than 50 lines of Java code and about 250 lines of TypeScript to complete the basic requirements.
You are expected to fix any bugs from previous homeworks that affect the correctness or performance of your application in this assignment. You are also required to fix code quality/organization issues in your pathfinder code.
When you're done, you can show off your awesome looking campus-map-route-finding application to your friends and family!
The above diagram is an overview of the basic structure of the application that you'll be building in this assignment. Note that there are two servers this time around. In the Connect the Dots assignment, you had one client (Google Chrome) and one server (the React Development server). The React development server is a part of our development tooling, not something you needed to write. It was the Development server's job to put all the different parts of your application together before sending it to Google Chrome to be shown to the user. In this application, the Development server has the same job.
The additional interesting part of this assignment is the second server, which is a server you'll be writing in Java using the Spark Java framework. There are many more details in the "Backend" section of this assignment spec, but the main job of the Java server is to allow the React application to access the campus paths data. This might take the form of requesting information about buildings on campus, or asking the server to calculate the shortest path between two buildings and respond with the answer. Fortunately, you've already written all the Java code you need to manage this data and perform those calculations, you just need to create a server the allows clients (like your React app running inside Google Chrome) to make requests for data.
In an effort to give you a clear path to completing this assignment, there is a suggested order listed below. You are not required to complete this assignment in this order, but it might be helpful to.
In designing your React frontend in more detail, it may be helpful to read the React documentation's Thinking in React section (as well as maybe the Lifting State Up section for some more gritty details). The "Thinking in React" section walks you through a simple application built in React, and discusses how a React developer might start with an idea of an application and work her way up to having a completely functional application. You certainly don't need to follow that section step-by-step, but it has some suggestions about what to think about when you're designing at a high-level, and your final application needs to use good React style.
Since you already know the basics of creating a React application from the connect the dots assignment, the
backend is where you'll encounter the majority of the new material for this assignment. Fortunately, Spark is a
very simple Java framework that requires very little code to get a fully-featured Java server running. You saw
Spark in lecture, so we won't be repeating all of the basics here. If you're curious, Spark has some
documentation on their main webpage, and they also offer a complete set of javadocs for the API. We're
providing a class called SparkServer
(inside hw-campuspaths-server/
) with a
main
method that is where you should create all your routes and do any other initialization that
you may need to. (For example, you probably want to create an instance of CampusMap
that you
can use to fulfill requests that are sent to your server.) Note that you should not create a new
CampusMap
each time your server receives a request, because then all the work of loading data and
creating a graph needs to be repeated for each request, slowing your application down.
Creating this application shows us exactly why the Model, View, Controller design pattern is so helpful. You
originally implemented the CampusMap
class to be used with the text user interface from the
pathfinder assignment, but now you'll be able to reuse parts of it for this assignment without having to modify
it much (if at all). Separating the model (all your graph code, pathfinding code, and parsing code) from the
view and controller in the pathfinder application by using CampusMap
(and the ModelAPI
interface that it implements) has made it much easier to reuse all of that code for something completely
different!
You should implement a Spark Java server that allows other applications to make requests to query data and
computation from your preexisting pathfinder application. You're writing this server specifically to support the
React application that you'll be building, so you can design this server to respond to exactly the requests that
your React application will make. Your SparkServer
class shouldn't do much more than contain a the
main
method and define all the different routes in your application - your routes will probably
only do a very small amount of processing and leave most of the work to calling the methods of a
CampusMap
object. You're free to create whatever routes make sense for your overall CampusPaths application, the server
will probably be very minimal. For reference, the staff solution only has two routes, and those two routes do
almost no processing other than call methods inside CampusMap
. You may modify
CampusMap
,
but you probably don't need to in order to fulfill the base requirements of this spec, and you should do so
carefully. In particular, you should not change/break any preexisting functionality - the pathfinder application
should still work as it did before this assignment.
One of the trickiest parts of communicating between two separate programming languages, like Java and JavaScript, is effectively sharing data between them. A Java object works completely different from a JavaScript object, so how are we supposed to send information from the server about paths, and buildings, and other campus data, and have the TypeScript code in your React app be able to understand it? This is where JSON comes in. JSON stands for JavaScript Object Notation: it's a way to take a JavaScript object and turn it into a string that represents it. The powerful thing is that you can also go the other way: take a JSON string and turn it into an actual JavaScript object that you can then pass around, read fields of, and update as you wish. To solve this problem of communication, we're going to have the server always respond to requests by sending a JSON string. That way, the JavaScript/TypeScript code that made the request can just turn the JSON string into an object and read the fields inside that object to get the information it's looking for.
How do we take a Java object inside our server (maybe one that represents a path, or some other data that we want to sent) and turn it into JSON? The folks at Google realized a while back that they had this same problem and invented something called Gson that can do just that. Gson is an extremely powerful and feature-filled Java library, but the basic idea is that it can take a Java object and turn it into a JSON string that contains all the same data. (It can actually go the other direction too, take a JSON string and turn it into a Java object, but that's a much more complicated process and not necessary for this assignment.)
We now know the basic ideas behind this server: when your React application makes a request to it, one of the
routes you defined in your Spark server is run. That route's handle
method should get any
additional info from that request (if there is any), and call methods of CampusMap
to get the
information that was requested. Then, the handle
method will use Gson to turn the response data
into a JSON string, and return that JSON string. Spark will take the String you returned from the
handle
method and send it back to your React application that made the request.
To start your server once you've written some code, use the provided hw-campuspaths-server:runSpark
gradle task. Note that gradle will start the server and then keep running, you won't get a "BUILD SUCCESSFUL"
message until after you stop the server. Also note that, unlike React, if you change any of your Java code, you
won't see the changes right away. You'll need to completely stop and re-start your server to have the new
changes take effect. You'll see in the starter code (SparkServer.main
) that there's a CORSFilter
object that's created, and has the apply
method called on it. You should not remove or modify this
code, and you should leave it at the very top of your main
method. This just sets up some extra
settings to make sure that the React application and the Spark server can talk to each other even though they're
running on different ports. (React is running on port 3000 and Spark on port 4567 – normally this isn't allowed
for web security reasons, but the CORSFilter object tells Google Chrome that this is OK.)
Once you've got some of your server running, you probably want to test it. Fortunately, you don't need to create the whole GUI before you can test it. Since requests to the sever are just made up of web addresses, you can send a request to your server by hand and see what the results are. (Note that you don't need to do any automated or unit testing for the server code you wrote, manually checking that your server is working is enough.) First, make sure you've started your server and that it's running. Then, open Google Chrome and, in the address bar, type:
localhost:4567/YOUR-ROUTE-HERE
You can replace "YOUR-ROUTE-HERE" with any route that you've defined (and optionally add query parameters as described in the slides from lecture) to send a request to your Spark server. The JSON string that your server sends back will be displayed in the browser window as plain text. Try sending a couple requests for paths between buildings on campus and make sure the server looks like it's sending the right thing back. Congratulations, you're now the proud owner of a shiny new Java web server!
Now that you've created this fancy server, it's time to create a React application that'll use it! Here's your chance to get super creative: you can design your GUI application to look however you want, as long as it meets some basic requirements that we're outlining below. Most of your time on the assignment will probably be spent creating the GUI. While this interface is a little more complicated that what you did in the Connect the Dots assignment, and there isn't as much provided starter code, the core concepts are the same. You're encouraged to look back the the code you wrote in the Connect the Dots assignment and the lecture/section slides and demo code about React to remember how to structure a React app and create your own components.
You'll be creating your application in hw-campuspaths/
, most of your code will go in hw-campuspaths/src/
and there is a provided image file of the campus map that you should use in hw-campuspaths/public/
.
You are encouraged to use the provided starter code that loads the image and sets up the canvas to be the same
size as the image. If you want to modify or replace this starter code, you're welcome to, but beware that canvas
sizing can be very tricky to get right. Note that aesthetics do not matter for this assignment.
As long as your interface is easily understandable and usable, it doesn't matter how ugly it looks. You're
welcome and encouraged to make it pretty if you'd like, but wait until you have all the required functionality
complete first before doing so.
Remember the basic commands for getting your React application up and running: npm install
the
first time you start working on this project, and npm start
to get your React development server running. You
should run these commands from hw-campuspaths/
. (To see what directory you're currently inside, use
the pwd
command. To change into a directory, use the cd
command. This means that if
you're in the base directory of your repository, use cd hw-campuspaths
to change into the correct
directory.)
The following are the requirements for your application to get full credit. Note that a lot of these are open-ended: you're free to choose how to implement them and design the interface for doing so yourself. However, it must be easy and intuitive to understand how to use all the features described below.
Your campus paths GUI must:
hw-campuspaths/public/campus_map.jpg
.
alert()
) describing the error and how they might fix it. Your GUI should
never crash or reach a buggy or invalid state. When in doubt, ask your friend/roommate to try their best
to cause an error, and make sure your application can handle anything they can throw at it.
Beyond these requirements as listed, you're allowed to do whatever you'd like to make this application your own. Make sure you've completed the basics of this application before you spend too much time experimenting.
Sometimes your React application will want to send requests to your Spark server to get data to display, this may be in response to some user input, or just as the React application is setting itself up for the first time. TypeScript can make web requests from inside the browser by doing a "fetch".
A fetch is just like a normal request, as if you were typing a URL into your browser address bar and looking at
the output in the window. Instead of using the browser GUI, though, you create the URL to request inside
TypeScript, and the response to the request is returned to you in the TypeScript for you to do whatever you want
with. The fetch documentation has a
few sections that'll be particularly important to check out: "Response/Body", and "Checking that the fetch was
successful". Remember that your application should be able to gracefully handle errors that the server reports
(or if the server never responds, such as if it was never started). Note that the examples in that documentation
use the traditional Promise syntax for TypeScript. You're welcome to use that if you'd like, but we highly
recommend (and support) the async/await syntax for dealing with Promises, which will look different. In
particular, you won't need calls to .then()
or .catch()
, instead using keywords like
await
or try/catch
blocks. See the demo code and slides from class for more
information and examples on using fetch to communicate between the server and your React application.
In the industry, there are some technologies that can be used for testing GUIs. However, they are often complicated and are definitely beyond the scope of this course, so you don't need to worry about any sort of automated testing for your GUI or your TypeScript.
Remember to think about where you are in the React lifecycle whenever you're writing code, and make sure that
what you're doing is always appropriate for that place in the lifecycle. See the Connect the Dots code for
examples of proper lifecycle management. Make sure you're always using good React style: don't use
document.getElementById
or similar methods, the only call to ReactDOM
should be in index.tsx
(we provided it for you), and you should use state
and props
correctly. In the React
documentation, there is a sidebar on the right labelled "Main Concepts." In that sidebar, sections 5 (State and
Lifecycle), 10 (Lifting State Up), and 12 (Thinking in React) might come in handy for this assignment in
particular, and are recommended, though they can be slightly more advanced that we're used to.
You're encouraged to express your creativity with this assignment. Once you have a complete, working version of the basic assignment as described above, commit a final working copy to your repository so you'll always be able to go back to it in case you need to. Then, consider implementing some extra features or improving the visual aesthetic of your application.
The only rule for extra features is this: don't break existing rules or feature requirements. None of the things you add should get in the way of your application satisfying the requirements outlined in this spec: you're still bound by those requirements even if you do extra stuff. Outside of that: go crazy! Some ideas are listed below, in no particular order:
ModelAPI
and/or CampusMap
to allow your server
to send more data to your React app - you'll need some kind of data that has the building names and their
x/y locations so they can be drawn on the map.)
For this assignment, you're allowed to edit hw-campuspaths-server/build.gradle
and/or hw-campuspaths/package.json
if you'd like to add additional libraries to help you implement these extra features only. Be absolutely
sure you know what you're doing, and that you don't change/break any preexisting functionality of those
files. The staff isn't able to support any additional libraries you may add to your application.
If you decide to add any additional features to your application, document them in
hw-campuspaths-server/src/main/java/campuspaths/extras.txt
. If the functionality/features you add show significant effort, you can earn
some extra credit for this assignment! Note that purely aesthetic changes, like changing the font or the
background color, aren't enough to warrant extra credit. Only features documented in extras.txt
will be considered for extra credit. Again, make sure your additional features don't break any of the
functionality that is required above. Extra credit can help you earn back points that you lost elsewhere in this
assignment, or might be considered when determining final grades for this course, but it's ultimately a small
source of additional points.
build.gradle
and package.json
that tell gradle and npm to install them for you. You can skip any
instructions about installation that you might see in their documentation and just import and start using
them in your code.
hw-campuspaths-server:runSpark
gradle task to compile your new Java and restart the server with
the changes.
lsof -i:3000
, where you replace the 3000
with whatever port number is being used that you need to free up. It'll list all the applications
that are using that port, including their PIDs (Process IDs). Find the previous version of the React
or Spark server that you created (the React sever might be called "npm" or "node", the Spark server
might be called "java"), and find it's PID. You can use the kill PID
command to kill
that server, just give it the PID of the process you want to kill. Be careful with
kill, only kill applications that you personally started and you're sure you want to shut
down. It's not a graceful way to stop an application and should be avoided unless absolutely
necessary, but it can sometimes be helpful.
npm start
,
and press Control-C. Remember that you don't need to restart the React development server to see changes you make to
your JS code - changes will be detected automatically by React.
hw-campuspaths-server:runSpark
gradle task. Note that gradle will
probably complain that the "BUILD FAILED" - you can ignore this message if it was caused by you clicking the
stop button. Gradle isn't happy about being stopped in the "middle" of what it was doing, but that's fine
for stopping the server for our purposes.
export
default ...
line at the bottom of your files! (See the provided JS code for examples.)
fetch
, creating a Spark
server, and
more.
You should pull, then commit and push all changes you made to your model, including and especially your CampusMap
class. Include all changes/additions you made to the SparkServer
class. Additionally, make sure to
include any changes you may have made to build.gradle
and/or package.json
, and include
all of the .tsx
and other files that you created in hw-campuspaths/
. Don't
forget to document any extra-credit additions you made in extras.txt
.
You should use the tag hw9-final
for this assignment.
Refer to the assignment submission handout for complete turn in instructions.
There is no GitLab validation for this assignment, so not having a pipeline when you submit the tag is normal.