Now that you have an understanding of the web request/response cycle and know how to build a project with Gradle, let's build our first web app. We'll use Spark to accomplish this. Spark is a lightweight web application framework, which will allow us to create web sites using Java. We need it in order to be able to output something to a web page that can be viewed in a browser.

To see how Spark works, we are going to create a website that displays a letter we wrote to our friends when we were on vacation. As we learn how to do more complicated things with Spark, we will add to our letter and make it more dynamic.

To get started, let's create a project folder called friend-letter. Inside of the project folder, create a build.gradle file. We will also need a src/main/java/App.java file. It is typical to call your main Spark class App, but technically you can call it whatever you want.

The build file should look like this:

hello-world/build.gradle
apply plugin: 'java'
apply plugin: 'application'

archivesBaseName = "friend-letter"
version = '1.0'
mainClassName = "App"

repositories {
  mavenCentral()
}

dependencies {
  compile group: 'com.sparkjava', name: 'spark-core', version: '2.3'
  testCompile group: 'junit', name: 'junit', version: '4.+'
}

Note that we've changed the mainClassName in our build.gradle file to "App" for this project because that is where we will be putting our main() method that we want to run when we type gradle run. That main() method will contain all of our Spark routing logic.

Type the following code into the App.java file:

hello-friend/src/main/java/App.java
import static spark.Spark.*;

public class App {
  public static void main(String[] args) {
     get("/hello", (request, response) -> "Hello Friend!");
  }
}

Some things about this code:

  • import static spark.Spark.*; is giving our code base access to the Spark library.
  • Spark gives us the get() method that creates an individual web page and takes 2 arguments. The first argument is "/hello". This refers to the URL path for the page we are creating. When a user navigates to www.yourwebsite.com/hello, they will see this page. The second argument is (request, response) -> "Hello Friend!".
  • (request, response) -> "Hello Friend!" is called a lambda. This is another one of those things I'm going to ask you to not worry about exactly what it's doing. All you need to know is that the string "Hello Friend!" is what gets returned back to the browser in the HTTP response body.

Let's see how this looks in our browser. To start the Spark web server, run:

$ gradle run

The first time you run a project can take a while as Gradle downloads and installs all your dependencies. If you'd like, you can run gradle build when you first get started and have it running in the background while you work on other things.

If all goes well, you should see:

:compileJava
:processResources UP-TO-DATE
:classes
:run
[Thread-0] INFO spark.webserver.SparkServer - == Spark has ignited ...
[Thread-0] INFO spark.webserver.SparkServer - >> Listening on 0.0.0.0:4567
[Thread-0] INFO org.eclipse.jetty.server.Server - jetty-9.0.2.v20130417
[Thread-0] INFO org.eclipse.jetty.server.ServerConnector - Started [email protected]{HTTP/1.1}{0.0.0.0:4567}
>Building 75% > :run

In your browser, go to http://localhost:4567/hello and you should see, in the top left corner, the message "Hello Friend!".

What if we want to write more than just "Hello Friend"? We could write our entire letter to a friend in HTML:

import static spark.Spark.*;

public class App {
  public static void main(String[] args) {
    get("/hello", (request, response) ->
        "<!DOCTYPE html>" +
         "<html>" +
         "<head>" +
           "<title>Hello Friend!</title>" +
           "<link rel='stylesheet' + href='https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css'>" +
         "</head>" +
        "<body>" +
           "<h1>Hello From Afar</h1>" +
           "<p>Dear Friend,</p>" +
           "<p>How are you? I hope that you are having a nice weekend. I'm vacationing in the Iceland while I learn programming! </p>" +
           "<p>Friend, you would not believe how cold it is here. I should have gone to Hawaii instead.</p>" +
           "<p>But I like programming a lot, so I've got that going for me. </p>" +
           "<p>Looking forward to seeing you soon. I'll bring you back a souvenir. </p>" +
           "<p>Cheers,</p>" +
           "<p>Travel Enthusiast Jane</p>" +
         "</body>" +
       "</html>"
    );
  }
}

When we write our response like this, it needs to be in one String. To make it read like an HTML file, we concatenate multiple Strings across multiple lines.

Notice that we included "<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css'>" so that we can use Bootstrap styling on our page.

If we add all of this into our code and refresh the browser, nothing happens. What went wrong? With Spark, we need to recompile our file and restart the server whenever we make a change to our App.java file. You can stop the Spark server by hitting Ctrl + C in the command line. Run gradle run again. Refresh your browser and you should see the letter we added.

Let's go over one more example of creating static pages in a Spark app. We are going to make a couple new folders so we can display images on our website. In your src/main folder, create a resources folder. This folder will store any non-Java related files required to run your application, such as CSS, HTML, images, videos, music, etc. In your resources folder, create a folder called public. The public folder is where you will put things that need to be visible to the outside world. Finally, in the public folder, create an images folder. In here you can put any images that you would like to display on your application. I got some photos from unsplash.com, resized them and saved them in the public/images folder.

Now, let's create a new page in our App.java file.

App.java
public class App {
  public static void main(String[] args) {
    staticFileLocation("/public");

 ….

  get("/favorite_photos", (request, response) ->
      "<!DOCTYPE html>" +
        "<html>" +
        "<head>" +
          "<title>Hello Friend!</title>" +
          "<link rel='stylesheet'  href='https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css'>" +
        "</head>" +
        "<body>" +
         "<h1>Favorite Traveling Photos</h1>" +
            "<ul>" +
              "<li><img src='/images/canyon.jpg' alt='A photo of a canyon.'/></li>" +
              "<li><img src='/images/city.jpg' alt='A photo of a bridge.'/></li>" +
              "<li><img src='/images/mountains.jpg' alt='A photo of a mountain.'/></li>" +
            "</ul>" +
        "</body>" +
        "</html>"
    );
  }
}

One new line of code was added to our main method: staticFileLocation("/public");. This tells Spark to use the public folder we created as the root for all static files. We can now access an image by typing src='/images/canyon.jpg' and Spark will know to look in resources/public/images for canyon.jpg

Now, when you navigate to http://localhost:4567/favorite_photos you should see the photos we added.

So far we have used two paths in our App.java file. What if we wanted our /hello page to be a 'home page' for our website and we wanted to have a link to our photo page from the letter? We don't want our users to have to type /hello at the end of our website's URL to get to the homepage - they should just get there whenever they type http://localhost:4567. Let's change our App.java file to create a root path.

App.java
import static spark.Spark.*;

public class App {
  public static void main(String[] args) {
    staticFileLocation("/public");

    get("/", (request, response) ->
    "<!DOCTYPE html>" +
     "<html>" +
     "<head>" +
       "<title>Hello Friend!</title>" +
       "<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css'>" +
     "</head>" +
     "<body>" +
       "<h1>Hello From Afar</h1>" +
       "<p>Dear Friend,</p>" +
       "<p>How are you? I hope that you are having a nice weekend. I'm vacationing in the Iceland while I learn programming! </p>" +
       "<p>Friend, you would not believe how cold it is here. I should have gone to Hawaii instead.</p>" +
       "<p>But I like programming a lot, so I've got that going for me. </p>" +
       "<p>Looking forward to seeing you soon. I'll bring you back a souvenir. </p>" +
       "<p>Cheers,</p>" +
       "<p>Travel Enthusiast Jane</p>" +
       "<p><a href='/favorite_photos' >P.S. Check out my favorite travel photos here.</a></p>" +
      "</body>"  +
      "</html>"
    );

    get("/favorite_photos", (request, response) ->
    "<!DOCTYPE html>" +
      "<html>" +
      "<head>" +
        "<title>Hello Friend!</title>" +
        "<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css'>" +
      "</head>" +
      "<body>" +
        "<h1>Favorite Traveling Photos</h1>" +
          "<ul>" +
            "<li><img src='/images/canyon.jpg' alt='A photo of a canyon.'/></li>" +
            "<li><img src='/images/city.jpg' alt='A photo of a bridge.'/></li>" +
            "<li><img src='/images/mountains.jpg' alt='A photo of a mountain.'/></li>" +
          "</ul>" +
      "</body>" +
      "</html>"
    );
  }
}

All we did was change /hello to /, and that creates a root path. You can check to make sure this worked by running the application and going to http://localhost:4567 and the letter will be visible. We also added a postscript line with a link to the favorite photos page.