Thursday, October 1, 2015

Building a To-Do list in Spring Boot and AngularJS (springdo-1)

What are we going to do?

TLDR Jump to Starting the project
In this series of tutorials, we will be building a simple application, a dynamic website with Spring Boot in the back end and AngularJS in the front end. You can apply this knowledge easily to another front end, such as backbone or react.
This tutorial is written for people who are relatively new to Spring and maybe even to Java. I have written it in such a way that it should be easy to skip parts if you have a background in this. I aim to make short video clips that show the most complex steps in more detail than I can write about them.
There are many tutorials out there on Spring and websites. What sets this one apart?
  • Focus on current state (2015): Using Spring Boot not plain Spring; no XML files but annotations; using Angular 1.4 (even though 2.0 is out), using IntelliJ 14 (but Eclipse, STS will also work).
  • Focus on story based work, we create a small backlog of stories and will deal with them in turn.
  • Test driven development: Even though this is our aim we had to stay away from this a little bit to not overcomplicate this project. We will try to test the Spring part of the application rigorously, but the Angular parts will be tested more informally.
  • Warts and all: Instead of showing the "best soution" right away, the tutorial will also highlight various caveats and not so good solutions. After all, knowing what not to do will save you time.
  • Lots of links: I'll try to keep this document short by linking to more in depth content throughout.

Conventions

"Too long; didn't read" is often abbreviated TLDR here and has an interesting background. I use "TLDR <short verson> / <long paragraph>" to help you navigate the content; It is an example of bottom line up front, if you want.
Lesson Learned marks a discussion of the path we have chosen here. In a few places, our first choices were not optimal but we kept them to also show you how not to do this. In these 'side bars', we discuss the other alternatives and optionally point to where we will later convert to a better solution.
User Story Development should be driven by the requirements of the end user. For a tutorial, this does not hold true completely, but where possible I will start and finish a user story to make it clear what functionality we are trying to implement.

Let's put that into practice: background reading

If you are new to Angular and Spring, it may be good to read up on your terminology. The very top of this Angular help page has a great table with key terms like Controller, Model, Dependency injection etc.
Dependency injection is so important that you should read this Wikipedia article about it. If that leaves things a little abstract, don't worry we will deal with that shortly. Don't google dependency injection in Angular now, as it looks confusing but is super easy to use.
You could read up on this conceptual overview of Spring MVC, but I started without that knowledge. If you read this you will notice that Spring's official documentation is good but hard to read for beginners: Very long pages, not enough separation between core content and 'also interesting', and lots of jargon. Once you know Spring better, these pages can be very helpful.
I like Gradle better than Maven, but Maven is the standard for Spring right now. You can do the tutorial with Gradle but expect some googling. You can easily convert to gradle at any time.

Caveats about Spring

TLDR do not use XML files. / Spring has been around for a long time and has evolved quite a bit. The major example would be the use of XML files to glue code together: Once required, now superceded by the @Controller@Autowired etc annotations.
TLDR Look for recent internet hits only. / This means that looking for help on Spring can be frustrating, as you will find hints that no longer apply with a more modern approach. A terrible experience is guaranteed when you modify your project to match the help you found, you will end up with an outdated Spring setup that will give you headaches. So leave major parts of the application (like the main application class) alone if you can.
There is often only more than one way to do something in Spring. In fact, there seem to be countless ways.

Starting the project

TLDR We use start.spring.io to start a project / Let's get started. There are a number of ways to start a Spring project (as with all things Spring).
  • The Spring 'Initializr' at start.spring.io will create a download for you, this is what we will use
  • IntelliJ provides a wizard for a Spring project. We found that it didn't set up some things right (even though it uses start.spring.io under the hood)
  • STS has a start wizard which should work fine
  • You can start from a maven or gradle file, but that is too complicated for us.
  • You can install and run Spring Command line, which is great but too complicated.
So go to http://start.spring.io and type in some details for your project
  • Give your project a nice name, we use Springdo. Enter this name under 'name' and 'artifact' (the name of the jar you will be making)
  • Use a reverse domain name, like 'org.demo' or 'io.pivotal'. Enter this under 'group' and 'package name' (confusing terminology there).
  • Choose a 'maven project' as the 'type'
  • Under dependencies, check 'Web', 'JPA', 'HSQLDB'
Video Using initializr Springdo-1-v1

Spring Boot

What is the difference between Spring Boot and plain Spring? Spring Boot is built on top of Spring as a runtime configuration utility. Spring will look in your environment (classpath) and automatically configure the project for you. However,
  1. Spring Boot only works when you have not supplied configuration yourself,
  2. Spring Boot uses runtime configuration (via dependency injection)
So if you run your project and it does not specify a webserver to use, Spring Boot will take the first webserver it can find on your classpath and make your project use it. Spring Boot does not create any configuration files, which means you can add a webserver configuration at any time and Spring Boot will stop supplying one.
In this project, we will not specify a webserver. One of the project dependencies (checkbox 'Web') will pull in Tomcat, which will be autoconfigured by Boot. Similarly, we will not write any configuration for a database, but because we selected 'HSQLSB' as a dependency, Spring Boot will configure that database for us, using 'JPA' as an interface.

Import and run

Next, open IntelliJ and import the project by choosing 'import' and navigating to the pom.xml. Make sure to have the Idea/IntelliJ project automatically read the maven projects (checkbox) and to automatically download the sources (checkbox). I prefer the 'ipr based' project format.
On the next page, check the one project that can be imported. On the page after that, ensure there is a JVM to use, and that it is java 1.8. Install Java and point IntelliJ to it if this step is not set up right (Tip: on a Mac, use or google brew cask install java). In this example, I store the new project in a different location (Documents/localcode) from where I imported it from (Downloads).
Once the project has been imported, we want to run it. The easiest way to set up a 'run configuration' is to find the main application, right click it and choose Run with the Spring icon (a pointy leaf). The server will start at localhost:8080 but it will only give us the standard error page (whitelabel error page) as we haven't done any coding yet.
Video Opening the IntelliJ project and start Spring Springdo-1-v2

A first controller

User Story When I open the site, I want to see a list of my todo items
An error page hardly counts as content, so let's write a first controller. A controller is a piece of code that creates a view. A view is something that the users sees in their browser. As there are no todo items yet, we can simply present the user with an empty page. (At this point, we assume there is only one user and no login process. We will fix that later).
A controller is a class, and this controller is responsible for the list of items at the main page. We annnotate the class with @RestController, which does a couple of things:
  • This is a controller, so it will be responsible for endpoints such as //about and similar
  • As a controller, it is requesting dependency injection. We will talk about that when it comes in (not yet)
  • A normal @Controller will always output an html template that needs to be filled in. A @RestController is made for JSON output, and the templating engine is not used. We abuse that here to render raw HTML as a string, something you would only do in a demo.
The method mainPage is reponsible for the main page at localhost:8080/. It is a function without arguments that returns some raw html. Above it, we tell Spring to which endpoint this will be connected. If you are coming from Rails or Django, it may seem strange to mix the code (mainPage) and the routing (/ maps to mainPage) in the same file.
package io.pivotal;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ListOfItemsController {

    @RequestMapping(value = "/", method= RequestMethod.GET)
    public String mainPage() {
 return "<html><body><h1>List of ToDO items</h1></body></html>";
    }
}
If you refresh your browser you should now see an empty todo list. Congratulations! User story finished.

1 comment:

  1. "I like Gradle better than Maven, but Maven is the standard for Spring right now. You can do the tutorial with Gradle but expect some googling. You can easily convert to gradle at any time."
    Maybe expand in general on what Gradle and Maven are. For someone entirely new, they may not know what you're talking about.

    Why did you decide to use @RestController rather than @Controller? Maybe expand on this a bit

    ReplyDelete