Saturday, February 18, 2023

Name change! I really, really like the name 'Blahnsense.' For some reason the portmanteau really tickles me. However, I'm not feeling like my life is very 'blah' right now, so I've decided on a name change. The new title was the first thing to pop into my head, and it may change again if I receive any new inspiration.

Working with environment variables in Spring Boot

I'm writing this article because I've recently been sorting out how to access environment variables when using Spring Boot.  Environment variables are important because you don't want to be checking in sensitive information such as secrets and keys into source control by adding them directly to properties files.

At a high level, my development environment involves:

  • Spring Boot
  • Eclipse
  • Heroku
The most convenient way for me to develop is to be able to run the Spring Boot application directly in Eclipse, then build and test on the command-line inside a Heroku container before pushing to production in Heroku. What I have found is that it is not at all straightforward how to access environment variables in these different contexts.

There are multiple ways to access environment variables inside a Spring Boot application. Two pretty straightforward ways are to:
  1. Access the environment variable directly inside application code by wiring the values in with the 'Value' annotation; ex. Value("MY_ENVAR") String myEnvar; 
  2. Parameterize values in the application.properties file; ex. my.envar=${MY_ENVAR} 
Example of parameterizing a mongodb url

The mongodb url can contain admin user and password information. This is definitely not something you want to check into source control, so you don't want this information inside your properties files. There are multiple ways you could parameterize the mongodb url. You could consider adding the entire url to an environment variable and accessing it that way. I chose to add a url template the the Spring Boot application.properties file and populate the user name and password inside the url from environment variables. The mondodb connection uri template is as follows:

mongodb+srv://${MONGODB_USER_NAME}:${MONGODB_PASSWORD}@cluster9.asdf.mongodb.net/muhdb?retryWrites=true&w=majority

The question now becomes; how do you access these parameters as environment variables?

Initially, I set the environment variables at the command line in my local development environment.

set MONGODB_USER_NAME=admin
set MONGODB_PASSWORD=asdf

When running the application inside Eclipse, I received the following error:

Exception authenticating MongoCredential{mechanism=SCRAM-SHA-1, userName='${MONGODB_USER_NAME}', source='admin', password=<hidden>, mechanismProperties=<hidden>}

The reason for this, and maybe a very good one, is that Eclipse doesn't access the environment variables on the local system. Instead, it enables setting environment variables in run configurations.

To fix this, go to Run->Run Configurations->Environment, and add environment variables there.

Next, you'll want to be able to build and run a local deployment of the Spring Boot application because this is much closer to the production deployment than running the application in Eclipse. This requires running gradlew to build the application, and heroku local web to bring up the application locally. Each of these has different mechanisms to access environment variables.

'Gradlew build' simply builds the application and runs tests unless explicitly instructed not to. It is a good idea to run the tests on build. The base Spring Boot test case will bring up a test context that will fail if it does not find the environment variables required by the application. This requires the environment variables to be set on the local system. On windows this can be set via 'set MY_ENVAR=asdf'.

Bringing up a local Heroku deployment accesses environment variables differently. The application is deployed and run inside a local Heroku container, so it would not have access to environment variables on the local system. To provide environment variables for the local Heroku container to access, just add them to a .env file in the project base directory. This .env file will be deployed into the local Heroku container where the environment variables are set based on these values. Be sure to add the .env file to your .gitignore file so it won't be checked into source conrol!

When deploying to Heroku production, you need to get the environment variables set inside the remote Heroku container where the application will be running. The remote production container will not reference the .env file on deployment. To accomplish this you can use the Heroku command line; 'heroku config:set MY_ENVAR=asdf'.

Summary:

Primary ways for a Spring Boot application to access environment variables:
  • Directly wired into application code via the "Value" annotation.
  • Parameterized inside the Spring Boot application.properties file.
Where and how to set environment variables:
  • For running builds inside Eclipse: go to Run->Run Configurations->Environment and add environment variables.
  • For builds run with Gradle: set the environment variables in the local environment. On windows this is accomplished with, 'set MY_ENVAR=asdf'.
  • For local Heroku builds: add the environment variables to a .env file.
  • For remote, production Heroku deployments: set the environment variables in the remote container with 'heroku config:set MY_ENVAR=asdf'.
Additional analysis:

It seems like this is a lot of places to have to keep track of environment variables when developing Spring Boot applications for Heroku in Eclipse. It would be nice if a couple of these sources could be merged. Some possibilities are:
  • Extend the gradle eclipse plugin to be able to update the run configuration with environment variables.
  • Use gradle to set local system environment variables, and maybe reference them when running the eclipse plugin to customize the environment variables in the project specific run configuration.
  • Enable gradle and eclipse to read environment variables from an external file, such as .env.

Sunday, August 7, 2016

cheatsheet: from zero to ‘hello heroku’ using spring boot

this is a cheatsheet that guides the reader through creating a simple hello world web application and deploying the app on heroku with the leanest possible set of steps. it assumes you have eclipse, gradle, git, and the heroku toolbelt installed on your development workstation.

setup

create project directory under workspace

  1. cd [workspace]
  2. mkdir [project name]

create build.gradle

  1. cd [project name]
  2. touch build.gradle
  3. open build.gradle and add:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.3.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'

jar {
    baseName = 'hello'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web") {
        exclude module: "spring-boot-starter-tomcat"
    }
    compile("org.springframework.boot:spring-boot-starter-jetty")
    compile("org.springframework.boot:spring-boot-starter-actuator")
    testCompile("junit:junit")
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.11'
}

  1. run ‘gradle wrapper’
  2. run ‘gradlew build’
    you may see an exception here. just ignore it.
  3. run ‘gradlew eclipse’

import into eclipse

  1. open eclipse
  2. select file->import
  3. select general->existing projects into workspace
  4. browse for root directory [workspace]/[project name]
  5. click ‘finish’
  6. create directory ‘[project name]/src/main/java’
  7. create directory ‘[project name]/src/main/resources’
  8. create directory ‘[project name]/src/test/java’
  9. create directory ‘[project name]/src/test/resources’
  10. rerun ‘gradle eclipse’

create an app

create Application.class

  1. right-click ‘src/main/java’
  2. select ‘new->class’
  3. under ‘Package’ type ‘org.mike’
  4. under ‘Name’ type ‘Application’
  5. click ‘Finish’
  6. add the following to the application class file:

package org.mike;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

create controller

  1. right-click ‘src/main/java’
  2. select ‘new->class’
  3. under ‘Package’ type ‘org.mike.controllers’
  4. under ‘Name’ type ‘HelloController’
  5. click ‘Finish’
  6. add the following to the controller class file:

package org.mike.controllers;

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

@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String index() {
        return "Hello Heroku!";
    }
}

run the app from eclipse

  1. right-click Application.class and select ‘Run As->Java Application’
  2. in browser, visit: http://localhost:8080/hello

git

  1. cd [workspace]/[project name]
  2. run ‘git init’ (initializes new git repo)
  3. touch .gitignore (files for git to ignore)
  4. add to .gitignore:
/build/ 
/bin/ 
/.gradle/ 
/.settings/
  1. run ‘git add -A’ (add all not-ignored files to source control and stage them)
  2. run ‘git commit -m “Initial commit”’ (commit or ‘check-in’ all files in staging area)

heroku

create new heroku app and procfile

  1. cd [workspace]/[project name]
  2. run ‘heroku login’
  3. run ‘heroku create’ (this creates a new ‘app’ on heroku)
  4. add ‘stage’ task to build.gradle
task stage {
  dependsOn build
}
  1. create file named ‘Procfile’ under [workspace]/[project name] (tells heroku how to run app)
  2. add to Procfile:
web: java -Dserver.port=$PORT -jar  build/libs/units-0.1.0.jar
  1. create file named ‘Procfile.windows’ under [workspace]/[project name]
  2. add to Procfile.windows:
web: java -Dserver.port=%PORT% -jar  build/libs/units-0.1.0.jar

run app locally

  1. run ‘gradlew stage’
  2. run ‘heroku local web -f Procfile.windows’ (starts app locally using windows Procfile)
  3. in browser, visit: http://localhost:8080/hello

run app remotely

  1. run ‘git add -A’
  2. run ‘git commit -m “Added heroku support”’
  3. run ‘git push heroku master’ (push branch ‘master’ to heroku remote)
  4. in browser, visit: http://[heroku domain]/hello
et voila!

Tuesday, July 12, 2016

Spring Boot Toot

Overview

This tutorial is intended to be the first in a series that details how to use Spring Boot to build a web application. In the first chapter we will walk through setting up a development environment with Eclipse, Gradle, and Git source control, and getting a basic ‘Hello World’ application up and running locally as well as hosted on Heroku. Future tutorials, should they happen, will delve deeper into Spring Boot by creating a user management framework that supports user registration, login and edit. This is currently a work in progress and any comments/criticizms are welcome.

1.1 Introduction

For just about any web project, you need a login and user framework. By the end of this tutorial, you are left with a usable login and user framework. Being a Java guy, two thoughts came to mind. One, why wasn’t there a framework assembled for the Java stack that was as complete and elegant as Rails? All of the projects I have worked on were cobbled together technologies. Two, why wasn’t there a guide for a Java stack as useful and complete as the Rails Tutorial? In an attempt to answer the first question, I embarked on an effort to create a Java framework by going through the Rails Tutorial and implementing each section as closely as I could with a Java stack. I came close, but some things are just done differently in Java. What I was left with after some considerable effort was an initial stab at creating a framework, so I abandoned the work for another initiative. In my exploration I discovered a few Java stacks that attempted to be more complete bundles for web apps. Grails is one, but this requires the developer to forgo Java for Groovy. Dropwizard was another and I implemented a small project with it. I liked it. Dropwizard has a large community, however, it seems to be off by itself and is built on Jersey. The functionality of Dropwizard is quite comprehensive, but it too seems cobbled together. Spring Boot is another rapid deployment framework that leverages everything Spring.

After abandoning the first initiative to create my own framework, I set out to resolve the second question of why there was no resource comparable to the Rails Tutorial for a Java stack. I needed to develop a web front end for a project, and decided to implement the product of Rails Tutorial using Spring Boot, and to cover the progress in my own tutorial… and here we are!

1.2 Up and running

1.2.1 Development environment

I have used the Eclipse IDE professionally now for several years. It is an amazingly functional free resource. Eclipse is well suited for use with Spring Boot projects built with Gradle as Gradle can configure the project for compatibility with Eclipse, and Eclipse is able to build and run and debug a Spring Boot application from within the IDE. Debugging your Spring Boot application from within Eclipse is a tremendous convenience.

Go to the eclipse site (https://eclipse.org/) and download the installer for you your system. My OS is 64-bit Windows. Open the installer and choose the ‘Eclipse IDE for Java EE Developers’ distribution for installation. Eclipse has many distributions for various programming languages and purposes. Next, select an installation location. The default location is [your user subdirectory]\eclipse\jee-mars. For the purposes of this tutorial the default location will suffice. Click the orange ‘Install’ button.

You can manage your installation directories any way you like, but I like to have a version specific directory so I can install and use multiple versions of Eclipse. This is because I may want to use the specific version of Eclipse a was developed with so I can put off upgrading the project to work with a newer version of Eclipse. This rarely becomes a problem, but this is a defensive measure to resolve any compatibility conflicts that may occur. Plus, you may have an arbitrary number of plugins added to an Eclipse installation and you may not need or want some of these in your new installation but a project may depend on one or more of them.

Once the installer has installed Eclipse, you can open it. Click on the large green ‘LAUNCH’ button. In the future you can launch eclipse from the desktop icon which should be named ‘Eclipse Jee Mars’ or from the application menu. The first time you open Eclipse, you will be prompted for a workspace location. This is where you your projects will be stored. I usually create a workspace folder under my named subfolder called ‘workspace.’ This is also the default. Go ahead and create [user dir]/workspace. Select the ‘Use this as the default and do not ask again.’ checkbox to remember this decision. You can always switch workspaces from inside Eclipse if you need to.

The first time you open Eclipse, you will be presented with a ‘Welcome’ tab. This is not an Eclipse tutorial, so any further explorations of this capable IDE are left to the reader. Go ahead and close the welcome tab. Now you should see what is called the ‘Java EE’ perspective and a series of grouped views. We won’t be creating a project from inside Eclipse for this tutorial as we will be automating our build with Gradle. In the next sections we will be detailing how to create a project with Gradle and import it into Eclipse.

1.2.2 Build with Gradle

I’ve chosen Gradle as the build automation system. I have chosen this over Maven (or other build tool) as it seems to be more flexible than Maven, and it dispenses with the verbose xml syntax. Plus, it seems to be having some uptake in the industry, and Spring Boot guides all have a section on building with Gradle. I am going to halt discussing Gradle now, as I want to introduce another concept before describing a basic Gradle build script.

1.2.3 Gradle Wrapper

Gradle Wrapper is an ingenious little mechanism that wraps the Gradle command line. With Gradle Wrapper, the developer merely declares what version of gradle to use to build the project. When a user invokes a build with Gradle Wrapper, the declared version of Gradle is downloaded and installed in a separate space and used to build the project. The reason this is useful is twofold. One, if you have multiple projects that were built with differing versions of Gradle, you don’t need to seek out and maintain separate versions, Gradle Wrapper does this for you. A build file with the required version of Gradle is checked into source control and anyone who checks out that source has all they need to build the project. Secondly, since you do not need to download and install Gradle yourself, you are freed up to use the latest version of Gradle on any projects you may be working on, and Gradle can evolve more freely without the need to satisfy any desires for backward compatibility. Interestingly, you install the wrapper using Gradle, so we’ll talk about getting and installing Gradle, and working with Gradle Wrapper in the next section.

1.2.4 Back to Gradle

Now that we have learned about Gradle Wrapper, lets install Gradle and the Wrapper, and put together a gradle build file to see the everything in action.

Go to the Gradle web site (http://gradle.org/) and download Gradle. At the time of this writing, the latest version is 2.11. Download the complete distribution. Unzip the downloaded archive to a location on your computer. I usually extract it to the version specific directory in my named subfolder, so in this case, [user dir]/gradle-2.11. Next, add the ‘bin’ folder to your path. On Windows 10 you can edit your path by:

  1. right-click on the start button, selecting ‘System’ and then ‘Advanced system settings’ in the left-hand navigation menu.
  2. On the ‘System Properties’ dialog, under the ‘Advanced’ tab, click ‘Environment Variables…’
  3. Find the ‘path’ variable under User or System variables. I just add it to my User path variable. Select the path variable and click ‘Edit…’
  4. Click ‘New’ and enter ‘C:\Users[user dir]\gradle-2.11.’
  5. Click ‘Ok’ and exit out of all of the dialog boxes.

Now when you type ‘gradle’ at the command prompt you should see a welcome message. For a command prompt, I use an application called ConEmu (https://conemu.github.io/), as this adds a lot of linux-like functionality over the legacy windows command prompt. It does seem the new Windows command prompt has added a lot of this functionality, but ConEmu is still nicer on the eyes out of the box. I have also installed Vim so I can easily modify text files through my command prompt, but you may edit files with any application you like.

Now lets add Gradle Wrapper to a project:

  1. Open your command prompt and change directory to C:\Users[user dir]\workspace.
  2. Create a new directory to hold the project we will be using for this tutorial. Call it ‘spring_boot_tutorial.’ Cd to the new directory.
  3. Run the command ‘gradle wrapper’

This creates some files and subdirectories in your project directory. From this point on we will invoke build operations through Gradle Wrapper.

Next, we need to create some of the project directories, and the ‘gradle.build’ file that will contain instructions on dependencies and how to build our application.

In the project base directory, ‘C:\Users[user dir]\workspace\spring_boot_tutorial’, create a file called ‘build.gradle’. This is the gradle build file. Through ConEmu, you can just type ‘touch build.gradle,’ but it should be straight forward to create this file using any method you like. In build.gradle, add the following:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.3.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'

jar {
    baseName = 'spring-boot-tut'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web") {
        exclude module: "spring-boot-starter-tomcat"
    }
    compile("org.springframework.boot:spring-boot-starter-jetty")
    compile("org.springframework.boot:spring-boot-starter-actuator")
    testCompile("junit:junit")
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.11'
}

Below are some explanations of the various sections in the gradle build file.

The ‘buildscript’ block defines the repository and dependencies required by the build script itself. This may seem confusing and redundant given mavenCentral is given as a repository some lines below this block. The difference is that the build script itself is a Groovy program that potentially has its own dependencies exclusive of the application being built. Here, the spring-boot-gradle-plugin includes various purpose built tasks required by Gradle to build and run a Spring Boot application. This plugin can be found in the Maven Central repository.

The ‘apply’ notation is a method call that adds several plugins to the build.

  • The ‘java’ plugin adds several new tasks, domain objects, and conventions to the project. For example, thanks to this plugin, we know that all source should be located under src/main/java.
  • The ‘eclipse’ plugin enables us to prep the project with files and configuration needed for Eclipse to see our project as an Eclipse project. This configures the source directories and classpaths needed to build the project within Eclipse. Once the project is configured for Eclipse, you will be able to build, run and even debug the project from within Eclipse.
  • The ‘idea’ plugin is similar to the ‘eclipse’ plugin, only for the Idea IDE. It is needed here as it adds some tasks that are useful even if you are not using the Idea IDE.
  • The ‘spring-boot’ plugin adds several features to help packaging and running Spring Boot applications.

The ‘jar’ block merely sets a couple of properties that tell Gradle what the name and version of the jar file produced by the build should be.

The ‘repositories’ block denotes the Maven Central repository which is the location of several project dependencies.

The ‘dependencies’ block declares what jars to download and include in the build. When you run a Gradle build the dependencies listed here will be downloaded and added to the classpath of the build. If you run the ‘eclipse’ task, as we’ll see later, these dependencies will be added to the Eclipse project classpath so no configuration is necessary from within Eclipse.

Finally, the ‘task wrapper’ block sets a property that tells Gradle wrapper what version of Gradle to download and use to build the project. This block actually adds code to the wrapper task run from the command line.

Now go to the command line and type ‘gradlew build.’ You will see several jars downloaded from the maven repository. The build should also fail as you have not yet added a main class.

Next run ‘gradlew eclipse.’ This downloads the dependencies and assembles the eclipse classpath. You should now be able to import the project into Eclipse. Any time you make changes to the directory structure or dependencies, you should rerun the ‘eclipse’ task to update the Eclipse configuration.

To import the new project into Eclipse;

  1. Open Eclipse and select ‘File->Import…’
  2. Select ‘General->Existing Projects into Workspace,’ and click ‘Next’
  3. Click ‘Browse’ and navigate to the ‘spring_boot_tutorial’ directory we created earlier. Click ‘Ok.’ You should see a ‘spring_boot_turtorial’ selection in the ‘Projects’ list. This is recognizable as an Eclipse project due to the ‘eclipse’ task we ran previously.
  4. Click ‘Finish’

Now you should see a project in the left hand pane titled ‘Project Explorer’ named ‘spring_boot_tutorial.’ Expanding the project should display the dependencies, a build directory, a gradle directory, some gradlew scripts, and the gradle.build file. If you right click on the project and select ‘Build Path->Configure Build Path…’ you will see one of Eclipse’s primary configuration dialogs. If you click on the ‘Libraries’ tab, you will see each of the libraries downloaded and assembled by the ‘eclipse’ task. Without the ‘eclipse’ task, each of these dependencies would have to be added to the Eclipse classpath manually. If you click on the ‘Source’ tab, you can see there are no source folders configured on the build path yet. We’ll work on that next.

Gradle requires source files to be in specific directories so it can find them come build time. Many of these are configurable, but the default locations suffice for a new project. The important source file locations are:

  • src/main/java - All Java source belongs in this directory.
  • src/main/resources - Resources, such as view templates and properties files belong in this directory.
  • src/test/java - Test code goes here. This is helpful when testing package private classes and methods as the test package structure can mirror the main package structure. Also, test cases in this directory are only compiled and executed when tests are run during a build. They are not included in the final production build.
  • src/test/resources - Resources required specifically for test cases.

Let’s add these directories to the project. Create each directory in the list above directly under the ‘workspace\spring_boot_tutorial’ directory and rerun ‘gradlew eclipse’.

Now go back to Eclipse, right-click on the project and select ‘Refresh.’ You should see the directories you just created appear under the expanded project in the Project Explorer. You can also see the icons to the left of each folder appear as an open folder with a small ‘package’ inside. Eclipse includes a lot of detail in these icons that can help you determine what you are looking at with just a glance. Here we can see that these directories are packages which implies they are available on the build path. If you right-click the project and and select ‘Build Path->Configure Build Path…’ and select the ‘Source’ tab, you should see four new entries in the ‘Source folders on build path’ list. Again, the gradle eclipse plugin has done this for us.

1.3 Let’s make an app!

1.3.1 A brief overview

The most brief overview of Spring Boot is MVC. In fact, Spring Boot is Spring MVC at its core. MVC stands for ‘Model-View-Controller.’ Spring’s implementation of MVC is fairly straightforward and simplified through the use of annotations. We’ll get into the details of MVC and Springs MVC implementation in later chapters. For now we just want to get the most basic application up and running.

1.3.2 Hello world!

We will now create a basic ‘Hello World’ application that displays the text ‘Hello World’ in the browser. We will build and run this application from within Eclipse and from the command line with Gradle in order to introduce you to the different ways to build and deploy applications with Spring Boot and Gradle.

To run any Spring Boot application, you need an ‘Application’ class. This class contains a ‘main’ method that will start your application and wire together all the beans required to bring up a basic web application. Many defaults are provided so that very little configuration is necessary to get started. To start, create the following ‘Application’ class under ‘src/main/java/org/mike/Application.java.’ Within Eclipse right-click on ‘src/main/java’ and select ‘New->Class.’ In the ‘Package’ field, type ‘org.mike’ (or whatever package name you like) and in the ‘Name’ field ‘Application’. Click ‘Finish’. You should now see a new tab labeled ‘Application.java’ in the edit pane. Add the following code to the new Application class:

package org.mike;

import java.util.Arrays;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Again, this should bring up a basic web application with a default configuration. This may be all you ever need, or you may find it necessary to have more fine grained control in which case you can add to this class to provide more detailed configuration. We will see an example of this in later chapters of this tutorial.

The heart of Spring is a somewhat mysterious object called the ‘ApplicationContext’. You will see reference to this throughout the Spring documentation. This tutorial will attempt to reduce some of the confusion you may have around this object.

The @SpringBootApplication annotation is a convenience annotation that enables several features. It enables this Application class to serve as a configuration object that will provide bean definitions to the application context, and it enables this to happen automatically. The annotation also denotes this application as a Spring MVC application, which initiates all the necessary plumbing for such an application. Additionally, component scan is enabled which scans the ‘org.mike’ package for other components, configurations and services. This supplants the need to define your beans and controllers in an external configuration file.

The entire web application is brought up with the execution of the run() method on the SpringApplication class. This starts an embedded web server and deploys the application within it exposing any endpoints defined in your application.

The functional object of our new application is the ‘Controller’. Create the following controller class under ‘src/main/java/org/mike/controllers/HelloController.java.’

package org.mike.controllers;

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

@RestController
public class HelloController {
    @RequestMapping("/")
    public String index() {
        return "Hello World!";
    }
}

In this case the @RestController annotation is used to identify this method as a REST endpoint. The significance of this is that web requests to the ‘/’ endpoint will return data instead of a view. Had we annotated this method with @Controller, then the application would attempt to locate and resolve a view with the name ‘Hello World!’ after the ‘index’ method returns. In subsequent parts of this tutorial we will work heavily with the @Controller annotation, but it is worth noting that Spring Boot can also expose REST endpoints.

Given that we configured the application for automatic bean discovery in the ‘org.mike’ package, this controller class will be discovered when the Spring Boot application is started and wired in as a Spring MVC controller.

The @RequestMapping annotation maps the path ‘/’ to the ‘index()’ method.

1.3.3 Run it

Let’s run the application. First, let’s run the application from within Eclipse. Simply right-click on the Application.java class in the left hand Project Explorer pane and select ‘Run As->Java Application.’ In the Console tab in the bottom pane you should see several log statements ending with a line that says ‘Started Application…’

Now open a browser and type localhost:8080 in the url bar. You should see the text ‘Hello World!’ in the browser.

Some analysis of the console output is below.

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.3.3.RELEASE)

2016-03-04 12:12:28.297  INFO 5784 --- [           main] org.mike.Application                     : Starting Application on broadbear-PC with PID 5784 (C:\Users\broadbear\workspace_tut\spring_boot_tutorial\bin started by broadbear in C:\Users\broadbear\workspace_tut\spring_boot_tutorial)
2016-03-04 12:12:28.300  INFO 5784 --- [           main] org.mike.Application                     : No active profile set, falling back to default profiles: default
2016-03-04 12:12:28.350  INFO 5784 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@16267862: startup date [Fri Mar 04 12:12:28 PST 2016]; root of context hierarchy
2016-03-04 12:12:28.986  INFO 5784 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'beanNameViewResolver' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]]
2016-03-04 12:12:29.836  INFO 5784 --- [           main] e.j.JettyEmbeddedServletContainerFactory : Server initialized with port: 8080
2016-03-04 12:12:29.839  INFO 5784 --- [           main] org.eclipse.jetty.server.Server          : jetty-9.2.15.v20160210
2016-03-04 12:12:29.943  INFO 5784 --- [           main] application                              : Initializing Spring embedded WebApplicationContext
2016-03-04 12:12:29.944  INFO 5784 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1597 ms
2016-03-04 12:12:30.392  INFO 5784 --- [           main] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2016-03-04 12:12:30.395  INFO 5784 --- [           main] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'metricFilter' to: [/*]
2016-03-04 12:12:30.395  INFO 5784 --- [           main] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'characterEncodingFilter' to: [/*]
2016-03-04 12:12:30.396  INFO 5784 --- [           main] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2016-03-04 12:12:30.396  INFO 5784 --- [           main] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2016-03-04 12:12:30.396  INFO 5784 --- [           main] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'requestContextFilter' to: [/*]
2016-03-04 12:12:30.396  INFO 5784 --- [           main] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'webRequestLoggingFilter' to: [/*]
2016-03-04 12:12:30.396  INFO 5784 --- [           main] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'applicationContextIdFilter' to: [/*]
2016-03-04 12:12:30.588  INFO 5784 --- [           main] o.e.jetty.server.handler.ContextHandler  : Started o.s.b.c.e.j.JettyEmbeddedWebAppContext@f973499{/,file:/C:/Users/broadbear/AppData/Local/Temp/jetty-docbase.3392512236555004143.8080/,AVAILABLE}
2016-03-04 12:12:30.589  INFO 5784 --- [           main] org.eclipse.jetty.server.Server          : Started @3188ms
2016-03-04 12:12:30.783  INFO 5784 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@16267862: startup date [Fri Mar 04 12:12:28 PST 2016]; root of context hierarchy
2016-03-04 12:12:30.849  INFO 5784 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto public java.lang.String org.mike.controllers.HelloController.index()
2016-03-04 12:12:30.853  INFO 5784 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2016-03-04 12:12:30.853  INFO 5784 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2016-03-04 12:12:30.884  INFO 5784 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-03-04 12:12:30.884  INFO 5784 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-03-04 12:12:30.915  INFO 5784 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-03-04 12:12:31.445  INFO 5784 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/health || /health.json],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(java.security.Principal)
2016-03-04 12:12:31.446  INFO 5784 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/env/{name:.*}],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String)
2016-03-04 12:12:31.447  INFO 5784 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/env || /env.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-03-04 12:12:31.447  INFO 5784 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/trace || /trace.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-03-04 12:12:31.448  INFO 5784 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/mappings || /mappings.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-03-04 12:12:31.448  INFO 5784 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/info || /info.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-03-04 12:12:31.451  INFO 5784 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-03-04 12:12:31.451  INFO 5784 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/dump || /dump.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-03-04 12:12:31.452  INFO 5784 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/autoconfig || /autoconfig.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-03-04 12:12:31.452  INFO 5784 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/configprops || /configprops.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-03-04 12:12:31.453  INFO 5784 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/metrics/{name:.*}],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String)
2016-03-04 12:12:31.453  INFO 5784 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/metrics || /metrics.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-03-04 12:12:31.553  INFO 5784 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2016-03-04 12:12:31.562  INFO 5784 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 0
2016-03-04 12:12:31.639  INFO 5784 --- [           main] application                              : Initializing Spring FrameworkServlet 'dispatcherServlet'
2016-03-04 12:12:31.639  INFO 5784 --- [           main] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2016-03-04 12:12:31.649  INFO 5784 --- [           main] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 10 ms
2016-03-04 12:12:31.674  INFO 5784 --- [           main] o.eclipse.jetty.server.ServerConnector   : Started ServerConnector@42c28305{HTTP/1.1}{0.0.0.0:8080}
2016-03-04 12:12:31.676  INFO 5784 --- [           main] .s.b.c.e.j.JettyEmbeddedServletContainer : Jetty started on port(s) 8080 (http/1.1)
2016-03-04 12:12:31.680  INFO 5784 --- [           main] org.mike.Application                     : Started Application in 3.867 seconds (JVM running for 4.28)

From this console output we can see that the default embedded web server is Jetty. We can see all of the filter and controller mappings. We can also see several maintenance and monitoring endpoints that exposed by the application. You can try some of these endpoints yourself in the browser. Type: ‘localhost:8080/health’ to see the health status of your application. If you are using Chrome, you can add the JSONView extension that will automatically format the output of these endpoints.

Alternatively, you can start the application with Gradle Wrapper. At the comman prompt, from the ‘workspace/spring_boot_tutorial’ directory, type:

./gradlew bootRun

You will see some compile/build steps followed by similar console output seen when we ran the application from within Eclipse. You should also be able to access our new endpoint from the browser. While running the application from Eclipse is a great convenience, it is worth familiarizing yourself with the Gradle command prompt as it is a powerful and easy to use build tool, and this will help us when we need to deploy to a production server on Heroku.

1.4 Source control with Git

Source control is an integral part of any software development project and it behooves you to integrate a good source control solution into your development process. There are two primary reasons source control is so important. For one, it provides a history of your changes. This means you can check in a working set of source files and continue working without worrying about permanently breaking anything. If you decide you don’t like your changes, you can always revert to a previous check-in and undo your changes. Secondly, source control enables you to host your source files remotely. This enables you to check your source files out on different devices, and even others to access and contribute to your source files. Plus, if others are working on your source, you can see changes they have made to try to identify problems that have arisen. This guide will give you some of the basics for working with source control and future sections will continue to use source control as you would on a normal development project.

For source control, I use Git. There are a couple of Git source control hosting services that offer free repositories. Two popular Git hosing providers are GitHub and BitBucket. GitHub is great for when I want to build a community around some software, but private repositories are not free. BitBucket offers free private repositories and charges for groups of collaborators that exceed a certain number. I am not totally concerned with privacy with this code, but for the purposes of this tutorial it may be of more use to you to start using BitBucket as you may want to move on to other projects that you do not wish to make publicly available.

1.4.1 Get Git

To work with Git and BitBucket, it is necessary to install Git locally on your development workstation.

Download the git installation executable compatible with your development workstation and install it.

Once Git is installed you should be able to type ‘git’ at the command line and see a list of list of commands.

To start, you should set a couple of configuration properties in git:

$ git config --global user.name "Your Git Username"
$ git config --global user.email your.email@example.com
$ git config --global push.default current
$ git config --global alias.co checkout
$ git config --global alias.st status

The above commands include the ‘–global’ flag which means these values will be available to all repos. If you wish a configuration to be local to a repo, go to that repo’s base directory and run the ‘git config’ command without the ‘–global’ flag.

The user.name and user.email values will be used with every Git commit.

The ‘push.default current’ setting ensures only the staged changes on the branch you are currently working on will be pushed. Without this, changes on every branch would be pushed. This could get confusing, especially at first, so I am setting this to ‘current’ so only changes will be pushed on the current working branch.

The alias setting is an indispensable way to save a lot of typing. I use the status command countless times throughout the day. I usually go one step further and create a system alias, ‘gs’ or something, to avoid even having to type ‘git.’ This example just shows you how to set up a git alias. I leave further alias configuration up to the preference of the reader.

To view all of your settings you can run

git config --global --list
git config --list

The first command lists all global configurations and the second the configurations associated with the current repo.

Create a repo

To store your source files in source control, you need to set up a repository (repo). A repo is a unit of source control. You would likely have separate repos for each project. To set up a Git repo for the Spring Boot Tutorial project go to the base directory of your project, ‘workspace/spring_boot_tutorial’ and type:

git init

You will see a ‘.git’ directory appear in the base directory of your project.

Next, start tracking all the project files. You will need to create a ‘.gitignore’ file in the base directory of your project in order to avoid checking in compiled classes and the like. If you run:

git status

you will see a list of untracked files in the current repository. You should ignore everything under the /bin and /build directories, as well as some gradle and settings files. To do this, create a file, ‘.gitignore’, and add the following entries:

/build/
/bin/
/.gradle/
/.settings/

This tells Git to ignore the listed directories and all files and directories under them. Now when you run ‘git status’ you will not see these directories in the list of untracked files.

Now we need to track these files. Run:

git add -A

If you run ‘git status’ again, you will see the files have moved from an ‘Untracked’ section to a ‘Changes to be committed’ section. Git has the concept of a ‘staging’ area for files to be committed. The files you just added are now in the staging area. When you commit, all of these files will be committed.

Go ahead and commit these files by running:

git commit -m "Initial commit"

This commits all files in the staging area, and adds the provided message after the -m flag to the commit.

To see a list of your commits, type:

git log

What you have just committed is local to your workstation. You now have full source control on your local workstation, but it is not hosted remotely for sharing to multiple workstations or other team members. This is where BitBucket comes in. We will describe setting up BitBucket in the next section.

1.4.2 A drop in the BitBucket (HAR HAR HARRRRR!)

Open an account on BitBucket.

Log in and create a new repo. BitBucket does a pretty good job of guiding you through setup. For instance, after creating a repo, click ‘I have an existing project’. You will see some command line help like the following:

cd C:\Users\[user dir]\workspace\spring_boot_tutorial
git remote add origin https://[username]@bitbucket.org/[user name]/spring_boot_tutorial.git
git push -u origin --all # pushes up the repo and its refs for the first time
git push -u origin --tags # pushes up any tags

Your user name will be auto-populated. A brief explanation of the previous commands follows. In order to transfer your source code from your local workstation to your new BitBucket repository, you have to add a ‘remote’ on your local workstation. A ‘remote’ is basically a uri, or in this case a url, that identifies the remote location. Once you have added a remote, you can push your code to the BitBucket repository.

Follow this guidance to add a remote and push your code to your BitBucket repository.

1.4.3 Common git activities

1.4.3.1 Branch

git checkout -b test-branch

This creates a branch with the -b flag named ‘test-branch,’ checks out that branch, and switches to it.

1.4.3.2 Edit

touch Readme

Add explanatory text to the Readme file. Then:

git add -A

‘-A’ add all new files to the staging area.

1.4.3.3 Commit

git commit -a -m "Added readme"

‘-a’ commit all modifications to existing files. Must still add new files.

1.4.3.4 Merge

git checkout master

Switch to the master branch.

git merge test-branch

Merge the test-branch into master. There should be no conflicts.

git branch -d test-branch

Remove the branch if desired. A lot of ‘feature’ branches’ can be cleaned up afterwards. Changes are recorded in the commit and can be backed out with the commit id, so it is not necessary to keep the branch around. Sometimes it is helpful to keep a branch if it represents a release, although releases can also be tagged. To remove a branch that has not been merged into the master branch, use -D instead of -d.

1.4.3.5 Rebase

If you are like me your branch will contain several frivolous commits. It can be helpful to simplify this by ‘squashing’ the branch.

1.4.3.6 Push

git push

Now your changes are on BitBucket!

1.5 Making the application available on Heroku

Heroku is a hosting service that provides a limited free instance for users to release their applications. Though limited, it does enable you to attach whatever domain name to the service you like, so an application deployed on the free instance can be accessed just as any production application would. The free instance is mainly limited in resources such as memory and space, and the instance goes to sleep when the application is inactive. You will notice a considerable lag when opening an application you have not visited in a while. Though limited, this is a great way to put together a functioning prototype or MVP and make it available to the public.

Another aspect of Heroku is that it seems to abstract away the system aspect of deploying and hosting an application. Other hosting providers I have worked with simply provided a virtual OS instance that you could log into via ssh and configure at will. Heroku attempts to create an abstract environment driven off source control. You deploy an application on Heroku by pushing your code to Heroku. Heroku then checks out your code, builds it, and deploys it for you. This may sound strange at first but it is really quite brilliant. For one thing, Heroku provides a common environment that can be tested locally on your development workstation. You can bring up an application locally as if it were deployed on a remote Heroku instance. Another advantage is that the developer must focus on getting the build script right so some other service can properly build and deploy the application. It is all too common that developers run their applications locally, working around some development environment dependency, or worse, some individual developer’s workstation specific dependency, and discover some inconsistency after deploying to staging and or production. Heroku’s process really encourages the single-click-build concept that helps to iron out bugs introduced by environment inconsistencies.

1.5.1 Setting up the environment

Create an account on Heroku.

Download and install the Heroku toolbelt for Windows.

Run the following commands at the command line:

heroku login
heroku create

Update the build file

Heroku requires a ‘stage’ task added to the Gradle build file. This task will run by default. Add the following to gradle.build:

task stage {
  dependsOn build
}

Create a Procfile

The Procfile tells Heroku how to run your app.

Add the following to the Procfile:

web: java -Dserver.port=$PORT -jar  build/libs/spring-boot-tut-0.1.0.jar

If you are on Windows, you should create an additional Procfile.windows and change the ‘$PORT’ reference to ‘%PORT%.’

The -D arg is passed to the embedded web server by heroku to tell it what port to listen on. In order to run locally you will need to set this in the heroku config. The following commands help you do that:

heroku config - to view configs
heroku config:get PORT - to view config for specific config variable
heroku config:set PORT=[port num] - to set a config variable

1.5.2 Deploying a Spring Boot application

Run the app locally. I love this feature of Heroku. This lets you deploy your app locally so you can work out configuration problems locally instead of continually redeploying to Heroku. Type the following from the command line:

./gradlew stage
$ heroku local web

To use an alternate Procfile, in order to run on Windows for instance, add the the -f flag followed by the name of the alternate Procfile.

$ heroku local web -f Procfile.windows

To publish and run your app on Heroku, run the following commands:

git add -A
git commit -a -m "Added Procfile"
git push heroku master

If you have configured everything properly, you should see ‘BUILD SUCCESSFUL’ and ‘Verifying deploy…. done.’ There should also be a message containing the url at the bottom of the output. In my case it is ‘https://boiling-cliffs-45288.herokuapp.com/ deployed to Heroku.’ Copy paste this url into a browser, and you should see:

Hello World!

Written with StackEdit.

Sunday, January 25, 2015

Implementing Rails with Java and Jersey

Overview


The code for this little diversion has been submitted to github at: https://github.com/broadbear/login. Is is somewhat raw, with plenty of TODO's still present throughout. The intricacies of the code are not detailed in this article, however, if you are familiar with Rails conventions, you should be able to find your way around my code.

I have been developing a new user login model for my web apps. I am at somewhat of a crossroads as to what technologies to use. I was tempted to learn something new, like Node.js, or Rails. Node.js interests me as a technology, as it represents a full JavaScript stack for webapps, and might be a revolutionary concept in itself. However, Rails is hugely popular in the start-up community, so I started tinkering with that instead. Needless to say, I was amazed at how elegant Rails is. I have worked primarily with Java stack frameworks, such as Struts/2, Jersey, etc. As I went through the Rails Guides and the Rails Tutorial book, I couldn't believe how easy web development could be. I must admit, when I first heard of Rails' popularity, I thought it was a flash in the pan. I considered it somewhat limited and didn't think it would gain traction. I have heard mutterings of agreement with this perspective. Now I am left wondering why some would have it in for Rails. It is not at all limited, and is a breeze to work with.

It is possible that some in the Java community reject Rails because they do not know anything about it. One tremendous advantage of Rails is that it is a self contained ecosystem. With Java, you are left cobbling together libraries and plugins to accomplish a task. I used to think this was an advantage. You can access a vast universe of technologies to help you build your applications. However, it is quite common for some component to only accomplish part of what you need, or to break things altogether. With Rails, much functionality is bundled together with the core product, or accessible through highly vetted Gems. One case in point is rake and DB migrations. In Java, you are left seeking a solution to enable multiple developers to submit changes to a single DB instance. With Rails, this is built right in. I will touch on this in a subsequent section.

While I was quite taken with Rails, it still represented a considerable technological jump for me, and I wanted to continue to exercise my Java skills.

I like Jersey. It is Oracle's reference implementation of the jax-rs spec, and is a fairly simple little framework for developing RESTful API's in Java. I also discovered that it has the ability to return templated pages (html) instead of JSON or XML representations. This gave me the MVC ability that I needed to build out a complete web application as opposed to just a REST API. Having worked with Struts and Struts 2, I was pleased with Jersery's simple approach to MVC. It seems Struts is a framework built primarily to implement MVC. Struts 2 has JSON and REST plugins that allow you to create a RESTful interface, but they are still done in a Strutsy way. Jersey REST is very straight forward. Just create a method and annotate it with a path. The most difficult aspect of Jersey is its scant, poorly written, documentation and its somewhat raw API. Its MVC capabilities are extremely minimal in comparison to Struts. With this minimization comes simplicity. Any method can return a reference to a template (a Viewable instance), and a single 'model' instance. The model can be any bean. If you need access to anything else, you can stash it in the session, or any other scoped object floating around in the Servlets ecosystem. The Viewable can reference a few different template types, including JSP, which is interesting. It gives you another perspective on Servlets/JSPs. It left me wondering, how much functionality do you really need? Do the advantages of all the additional functionality of Servlets/JSPs, Struts, etc. outweigh the added complexity?

Rails excels at exemplary documentation. The Rails Tutorial is an amazing, free(ish) resource that steps you through building an almost fully functional user activation/login/reset implementation. This is something that can be applied to almost any web project. If nothing else, it is a terrific collection of requirements for user login that any web site needs. If you sat down to try to piece all of these use cases together from imagination or trial and error, you would certainly forget some things, and have to stamp out plenty of bugs.

Seriously? Every web framework should have a version of Rails Tutorial customized for their specific language and platform.

In addition, a lot of what makes Rails so pleasant to use is convention. The names of paths, controllers, view templates, and tables all follow a rigid convention that you can deviate from if you really want to.

So I had this idea. Why not go through the Rails Tutorial and attempt to build my webapp login apparatus in Java/Jersey? Sure, Java and Ruby are quite different, but perhaps I can benefit from attempting to adhere to their model, doing things in a Java way when required. In the end, even if I abandoned doing things like Rails/Ruby, at least I would end up with a user login interface that would enable users to activate accounts and reset passwords.

This article recounts some of my experiences during the process of implementing my user login interface using Java and Jersey (and Bootstrap, Gradle, Heroku, ...).

ActiveRecord


I have seen attempts to create objects that do too many things. This goes against my understanding of Software Engineering best practice. Basically, I have seen people create objects that represent a bean-like entity, and then add methods that perform operations on that entity. I don't like this pattern as it seems to violate separation of concerns. You end up with beans that contain a lot of additional code, and often nebulous methods that do things to or with that bean. This also differs from the well known Java Enterprise pattern, the DAO. With DAO, beans are essentially value objects, and the DAO abstracts the persist. Beans are fetched and stored via the DAO.

With ActiveRecord, the bean inherits from a super class that has methods that enable the bean to be created, saved, updated, deleted in persist. I was skeptical at first, but learned that this pattern was championed by none other than Martin Fowler of Refactoring fame.

As my persist is MongoDB, I implemented the ActiveRecord pattern with the MongoDB Java driver, and eventually incorporated Morphia to simplify interaction with the data store. I implemented generic create, save, etc... methods myself. This has gone well, but I doubt my code is flexible enough in its current state. As I continue, I foresee considerable more implementation of my ActiveRecord will be required. Instead I am pondering bringing Spring into the project and gutting the ActiveRecord code with JPA. JPA has concepts like relationships between entities built in. This is something also included with Rails' implementation, but my implementation will require additional development to support this as transparently as the others. JPA would also move me in the direction of separation of concerns comparable to DAO's with JPA's Repository concept.

Having errors stored in the ActiveRecord object is very neat. This way you can attempt to validate the ActiveRecord object, and return the object itself to the view as the model. If there are any validation errors, they are present in the object, and therefore through the model. This has proven to be a powerful convention that simplifies so much in comparison to Servlets/JSPs and even Struts.

Validation


Jersey provides some validation capabilities, however, Rails embeds validation in the ActiveRecord object. This enables the ActiveRecord instance to encapsulate the error collection so it is accessible through the model by the view template. Jersey validation is handled by annotations on the resource method and arguments of that method. This means validation occurs before the resource method is invoked, so errors need to be caught, and the proper view template managed in a different place. Instead of researching further into the resource life-cycle, I chose to implement a similar convention to Rails, and added Hibernate Validator to the save and updateAttributes methods of ActiveRecord. Hibernate Validator is essentially an implementation of JSR 349 - Bean Validation 1.1, and is what Jersey uses to perform its own validations. This was somewhat complicated as the API is somewhat dense, but I ultimately came to a decent solution. Validation is driven off of annotations on properties of a model class. Hibernate Validator also allows you to define your own annotations, including cross parameter validations.  This enabled me to create a 'Unique' annotation to ensure user defined ids are unique, and a 'Matches' annotation that ensures the password and password confirmation match. These seem like simple things to perform in code, but enabling the validation to occur in one step, and having errors propagated to a single collection really simplifies validation as a whole. With Hibernate Validator, errors are propagated to a Set of ConstraintViolations. I found ConstraintViolations difficult to instantiate, and the Set difficult to work with. Adding non-conforming validations, such as comparing two strings, to the validation step gets messy. While not as flexible as I would like, Hibernate Validator enabled me tuck validation away in approximately the same places as Rails, and to populate an error collection on the ActiveRecord instance. If errors are detected, the resource method can re-render the form, and errors can be detected by the view template and populated in the final result.

Routes


I basically lifted the crud URL templates from the Rails Tutorial. Routes are declared and managed in a separate Ruby file. In Jersey, Paths are defined by annotations on the class and methods. I quite like defining paths with annotations, so there is no complaint there. However, in Rails, these paths/routes are referenced via methods that seem to magically be available anywhere; in the controllers, even the view templates. This presented somewhat of a challenge in Java. My solution was to define a Routes class and have methods that return the the paths as Strings. The Routes class can also be stashed in the session, making it available to the templates. Usage is somewhat more gaudy than Rails, but having the routes retrievable this way helps standardize the paths you will inevitably reference throughout your application. I was able to unify path declaration inside the Routes class. Annotations accept constant parameters, and getter methods can perform some simple string replace on the path templates. These getter methods are callable from expression language (since Servlet 3.0), and thus are accessible from JSP view templates.

Rendering vs Redirecting vs ... JSON!


The Rails guide shows how easy it is to distinguish between returning HTML and returning JSON. I ran into some complications with Jersey, but nothing too terrible. Rails makes it easy to add a .json suffix to your path which you can decipher in your controller, and return a JSON representation as opposed to an HTML representation. Something like this can be done in Jersey, although, I had to resort to something akin to regular expressions in my path declarations, and ran into a naming conflict that I could only work around by adding similar regular expressions to resource methods that did not require them.

Rendering and redirecting is where Jersey gets a little vague. Jersey enables you to build up a Response instance. The problem with this is that it is too general. It can be difficult to figure out how to get it to do exactly what you need it to do when you need it done. There are some convenience conventions, such as being able to return a Viewable instance, or a bean instance, but these were too restrictive. I found it best to stick with Response return types, and work with the ambiguities of the Response object. This is one of the few areas where I felt the need to add code to the ApplicationController super class that all of my resource classes inherit from. This convention comes directly from Rails. I was able to wrap most of the Response building functionality in two methods, one for redirecting, one for 'rendering' and my code looks somewhat similar to the Ruby code in this respect. So far I have not needed much more flexibility than these two methods. This plus the ActiveRecord pattern has lead to some fairly concise code.

With good JSON serialization support via Jackson, you just have to return an object in the Response and it will be automatically serialized to JSON.

Here is some example code demonstrating the conciseness (with the path format regular expression to detect JSON return format):

@Path("users/{id}{format:(.json)?}")
@GET
public Response show(@PathParam("id") String id,
                  @PathParam("format") String format) {
    User user = User.find(User.class, id);
    if (StringUtils.contains(format, "json")) {
        return Response.ok(user).build();
    }
    else {
        return render("/users/show.jsp", user);
    }
}

You can see, retrieving a user is a single line of code, called with a param parsed from the path via an annotation. Another path param determines the representation type to be returned. If JSON is required, a simple Response is built passing the user instance as the entity. The user instance is auto-serialized into JSON via Jackson and added to the HTTP response body. If an html representation is desired, the 'render' method is called with the path to the view template and the user instance as the model. This is not quite as concise as Rails, but we are certainly approaching it.

Although Rails supports suffix content negotiation (appending the path with .json or other), I have read literature that discourages this (RESTful Web Services Cookbook). However, the reason cited in the literature may not be particularly relevant for most projects, and that is probably why Rails continues to support content negotiation in this way.

The Cookbook recommends supporting content negotiation via the Accepts header. The Jersey developers seem to agree. Jersey supports content negotiation via the @Produces annotation. When the choice is between XML or JSON, two media types can be included in an annotation, and the final representation format will be based on information in the request Accepts header. When there is a greater disparity between formats, such as JSON vs html, you can declare multiple methods with that same path annotation, but different @Produces annotations. The correct method will be selected based on information in the Accepts request header. The advantage to this form of content negotiation is that it is more formal, and Jersey parses the Accepts header for you. Parsing the Accepts header can be somewhat complicated. The downside is that the code becomes littered with more, albeit simpler, methods. Below is an example that converts the initial path based content negotiation code listed above to be driven off of an Accepts header:

@Path(Routes.USER_PATH)
@GET
@Permissions({"view-user"})
@Produces(MediaType.TEXT_HTML)
public Response show(@PathParam("id") String id) {
    User user = User.find(User.class, id);
    return render("/users/show.jsp", user);
}

@Path(Routes.USER_PATH)
@GET
@Permissions({"view-user"})
@Produces(MediaType.APPLICATION_JSON)
public Response showAsJson(@PathParam("id") String id) {
    User user = User.find(User.class, id);
    return Response.ok(user).build();
}

You can see the original method has been split into two separate methods that return different formats. If a request arrives with an Accepts header of 'text/html', the show() method will be invoked and an HTML representation added to the response. If a request arrives with an Accepts header of 'application/json', the showAsJson() method will be invoked, and a JSON representation added to the response.

The Flash


I added a Rails flash-like concept to the HttpSession that is easily accessible to Jersey resources as well as JSPs. This allows you to pass messages to pages after a redirect.

Permissions


Permissions are implemented in a centralized location, on the session helper, so they are accessible from resources as well as views. A Permissions annotation was created for use in the controllers, while permission checking is available to views directly through the session helper.

Additional topics


Rake is really cool. Managing DB updates on a team can be very tricky, especially with relational databases. On one project we used Liquibase, which somewhat reminds me of what Rails has included. With Rake, you can generate a 'db migration' script. The migration script is in a 'domain specific language' and not just SQL. This saves you from having to seek out a solution yourself and bolt it on to a project the way we did. Liquibase worked, but you had to create the scripts yourself, and you were writing in SQL, which limited your flexibility if you wanted to switch out the data store, even among different relational database types. And, if you didn't do the scripts just right, Liquibase wouldn't handle them properly, and your scripts might go ignored, or worse, irreparably break something. Having DB migrations integrated tightly with Rails is a very good thing.

Of course, with a schema-less data store like MongoDB, this is somewhat easier to manage, so I have gone without addressing this little aspect of Rails.

Code generation and scaffolding was pretty cool as well. A similar concept could probably be implemented with Java/Jersey as well, but it was not immediately necessary.

I haven't found a particularly elegant way of implementing Rails' before_action concept in the controllers. Rails enables you to define one or more a 'before_action' command in a controller, and declare what controller methods it applies to. This is basically how the author of the Rails Tutorial restricts method invocation to logged in, admin users, etc. With ActiveRecord, I just added some template methods in the base class that the subclass can optionally implement. With the resources (controllers), I initially attempted to implement them as filters attachable via an annotation. This may come in handy, for instance, with permissions, but it is not as concise as before_action in Rails. Filters actually added so much annotation 'noise' I decided not to use them and just repeated the code in each relevant resource method. I am assuming there could be some sort of solution in AspectJ or something, but this will come later as it is time to press on.

Future


I will need some way to internationalize. I am not sure of Jersey's support for this. This was well supported in Struts. I'm sure Rails has something as well.

Basically, when I started, I was like 'how will I do all this stuff with Jersey.' Following Rails Tutorial, I was able to tuck a lot of functionality away in nice little convention methods and classes that mimic Rails. There were some successes and some failures, but in all it is nice to have a structure imposed on my Jersey app that I can intuitively carry through the entire app. Is it a new framework? No, not yet. Could it be? Possibly. Java on Rails?