Lesson Weekend

So far we've practiced Java basics, integrating custom classes into Java applications, managing dependencies with Gradle, using Behavior-Driven development, JUnit tests, and basic Spark setup and routing. But it's time to put all the pieces together and build something a bit more sophisticated. Throughout this week we'll walk through building a Blog application using all these concepts and more.

Application Overview

Our application will be a Blog where we can create and organize posts and comments. Not only are Blogs pretty common applications, but the structure it will require is a typical architecture for many different types of applications (ie: Listing all entries, allowing a user to click on an individual entry to view its details, etc.) Therefore, the approach in the next few lessons will be applicable to future projects as well.

Let's think about what we'll need this application to do. For now, we'll start small, and later add more complexity later in the week.

  • First off, we need to be able to create a blog post and add them to a list of blog posts
  • We also need to display a list of all our posts.

Application Setup

Great, let's get started.

  • First, we'll create a project directory named my-epicodus-blog in IntelliJ. You can use this as both the ArtifactId and the GroupId.
  • Make sure you select “Create directories for empty content roots automatically”
  • Feel free to check “Use auto import” as well. It’s up to you.

Let IntelliJ and Gradle do its thing, until you see the src folder.

Make sure you have Spark-Core, Spark-template-Handlebars and Simple Logger (slf4j-simple) in your build.gradle. Get Gradle to download these dependencies. Then, add your .gitignore file.

.gitignore File

Our .gitignore file should contain the same content we've used for previous projects:

my-epicodus-blog/.gitignore
# Compiled source #
############
*.com
*.class
*.dll
*.exe
*.o
*.so
*.bat

# Packages #
############
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip

# Logs and databases #
############
*.log

# OS generated files #
############
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

# Java and Gradle #
############
build/
.gradle/
out/
out
.gradle
gradle
gradlew.bat
gradlew
settings.gradle

# IntelliJ #
############
.idea
.idea/

layout.hbs File

Create a new directory: templates inside src/main/resources Inside templates, create a new layout.hbs file.

Remember, as we learned in this lesson this is the basic HTML that will be loaded for every page of our application. It contains the standard HTML tags, a link to Bootstrap, and the line {{ #block "content" }}{{ /block }} where the Handlebars Template Engine will render the individual, unique HTML pages:

my-epicodus-blog/src/main/resources/templates/layout.hbs
<!DOCTYPE html>
<html>
  <head>
    <title>{{ #block "title" }}Blog{{/block}}</title>

    <link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css'>
  </head>
  <body>
  <!--begin main template-->
    <div class="container">
      {{ #block "content" }}
{{ /block }}

    </div>
    <!--end main template-->
{{ #block "footer" }}
</body>
</html>
{{ /block }}

App.java File

Next, let's go ahead and set up the basics in our App.java file too. Create an App.java file in your src/main/java directory. Remember, App.java is responsible for the front-end user interface of the application. When we created command line interface applications it was responsible for prompting the user through the command line. Now that we're working with Spark, it's responsible for Spark routing.

my-epicodus-blog/src/main/java/App.java
import java.util.HashMap;
import spark.ModelAndView;
import spark.template.handlebars.HandlebarsTemplateEngine;
import static spark.Spark.*;

public class App {
  public static void main(String[] args) { //type “psvm + tab” to autocreate this :)
    staticFileLocation("/public");

  }
}

If you have red squiggly lines, check that you are listing Spark etc as dependencies in your build.gradle!

We won't add any routes yet, but we'll import all the necessary classes at the top of the file, declare our App class and main() method, set the staticFileLocation as "/public".

Setting Up JUnit in Spark Applications

As always, we'll use Behavior-Driven development as we construct our back-end. This means we'll need to get JUnit up and running to handle our automated tests. Even though we're using Spark now, the JUnit setup will be much the same.

Let’s create a new package in src/main/java called models.

Then, create a new Java class called Post.java in models.

Click inside of the empty class, and press Shift + Alt + t. You should see a dialog box open that prompts you to “Create new test”.

intellij-test-prompt

You should then see the following dialog box. Check setUp/@Before and tearDown/@After as we may need these later. Click OK.

IntelliJ-generate-test-annotations.png

IntelliJ will both a.) make a new PostTest file in the right location and b.) create some starter code for us! Pretty sweet, these IDE’s. Now that we've set up the basic requirements for our project we can begin developing!

What are @Before and @After Annotations?

Frequently, it’s necessary for us to perform certain actions before or after every test runs - for example, we might need to connect to a server, download some data, make an object, or, in our case clear a list of where we are storing our objects.

JUnit understands several different kinds of annotations that can help us make our testing process easier and more concise - among them are @Before and @After. As the annotation titles suggest, the @Before annotation runs before a test, the @After afterwards. Any methods defined or called in the annotation will be automatically run, so we do not need to call methods manually.

Behavior-Driven Development in a Spark Application

When developing an application with a web-based front-end user interface, always create and tests your back-end logic first in this way. We'll continue to use the Red, Green, Refactor workflow to create and test each functionality we add to our application.

Note: Last week, when we created projects together, like this Ping Pong Application, we clearly labelled which step of the "Red, Green, Refactor" workflow we were on. Now that we've been practicing BDD for over a week, we'll no longer explicitly announce each step. However, feel free to keep this lesson open as you follow along if you're not yet completely comfortable with the BDD workflow.

As always, we'll begin with the simplest behavior our back-end logic will demonstrate. Remember, whenever you're working with objects the simplest behavior is usually instantiating an instance of the object.

Our application will list individual Posts in our Blog. Each blogpost will be an instance of a Post class. So, our first test will confirm we can successfully instantiate Post objects. Let’s write a test now. Right-click after the @After and choose Generate > Test Method You can now edit the name of the test. Make it match the following below:

my-epicodus-blog/src/test/java/models/PostTest.java
package models;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.*;

public class PostTest {

  @Test
  public void NewPostObjectGetsCorrectlyCreated_true() throws Exception {
     Post post = new Post("Day 1: Intro");
     assertEquals(true, post instanceof Post);
  }
}

Of course you’ll have a lot of red squiggles. We don’t even need to bother running this test right now.

To make it pass let's add our Post class with a constructor that (for now) takes only one argument: Some short content, i.e the future body of the Post we're adding to our Blog:

my-epicodus-blog/src/main/java/models/Post.java
public class Post {

   public Post (String content){
   }
}

Now let’s switch back to PostTest, right click in the titlebar, and choose Run PostTest . Our test runs and we should see a green OK dot. Great! Our first test passes so we know that we can create an instance of a Post. Now let's add a test to make sure we can assign each Post some content and then retrieve it:

my-epicodus-blog/src/test/java/PostTest.java
...
@Test
public void PostInstantiatesWithContent_true() throws Exception {
   Post post = new Post("Day 1: Intro");
   assertEquals("Day 1: Intro", post.getContent());

}
...

Same as before, this test currently fails because we have not yet implemented getContent(). Furthermore, we need to create a member property to hold the Post's content. Then, we need to save the content provided in the constructor to this property.

Let’s move back to our class, and add the line this.content = content to our constructor. Then, place your cursor next to content and when the red lightbulb appears, click on it and choose “create field content” and make it a String.

intellij-generate-field-bulb.png

Then click below the constructor and generate a Getter method for content.

Our code should look like this:

my-epicodus-blog/src/main/java/models/Post.java
public class Post {
  private String content;

  public Post(String content) {
    this.content = content;
  }

  public String getContent() {
    return content;
  }
}

Let’s run our tests again. We should see two green OK dots. Yay!

Great! Now remember, we're starting small. For now, we only need to be able to create new Posts. Therefore, our back-end logic is done. Nice work! In the next lesson we'll walk through creating and routing a Spark front-end user interface to display our Posts in the browser.


Example GitHub Repo for Epicodus Blog