Deploying your web application on Heroku

In this section, we will deploy your application on Heroku for free. We will even use the free Redis instance available to store our session and cache.

Installing the tools

The first thing we need to do to create a Heroku application is to download the command-line tools available at https://toolbelt.heroku.com.

On Mac, you can also install it with brew command:

> brew install heroku-toolbelt

Create an account on Heroku and use heroku login to link the toolbelt to your account:

> heroku login
Enter your Heroku credentials.
Email: [email protected]
Password (typing will be hidden):
Authentication successful.

Then, go to your application root and type heroku create appName --region eu. Replace appName with a name of your choice. If you don't provide a name, it will be generated automatically:

> heroku create appname --region eu
Creating appname... done, region is eu
https://appname.herokuapp.com/ | https://git.heroku.com/appname.git
Git remote heroku added

If you have already created an application with the UI, then go to your application root and simply add the remote heroku git:remote -a yourapp.

What these commands do is add a Git remote called heroku to our Git repository. The process of deploying on Heroku is just pushing one of your branches to Heroku. The Git hooks installed on the remote will take care of the rest.

If you type git remote -v command, you should see the heroku version:

> git remote -v
heroku    https://git.heroku.com/appname.git (fetch)
heroku    https://git.heroku.com/appname.git (push)
origin    https://github.com/Mastering-Spring-MVC-4/mastering-spring-mvc4-code.git (fetch)
origin    https://github.com/Mastering-Spring-MVC-4/mastering-spring-mvc4-code.git (push)

Setting up the application

We need two ingredients to run a Gradle application with Heroku: a task in our build file called stage and a tiny file that contains the command used to run our application, called ProcFile.

Gradle

The Gradle build pack will automatically try to run the ./gradlew stage command on the root of your application.

Note

You can get more information on the Gradle build pack at https://github.com/heroku/heroku-buildpack-gradle.

We do not have a "stage" task yet. Add the following code to your build.gradle file:

task stage(type: Copy, dependsOn: [clean, build]) {
    from jar.archivePath
    into project.rootDir
    rename {
        'app.jar'
    }
}
stage.mustRunAfter(clean)

clean << {
    project.file('app.jar').delete()
}

This will define a task called stage, which will copy the jar generated by Spring Boot at the root of the application and call it app.jar.

The jar be much easier to find this way. The stage task depends on the clean task and the build task, which means that both of them will be executed before the stage task starts.

By default, Gradle will try to optimize the task dependency graph. So, we must provide a hint and force the clean task to be run before stage.

Finally, we add a new instruction to the already existing clean task, which is to delete the generated app.jar file.

Now, if you run ./gradlew stage, it should run the tests and put the packaged app at the root of the project.

Procfile

When Heroku detects a Gradle application, it will automatically run a container with Java 8 installed. So, we have very little configuration to take care of.

We will need a file containing the shell command used to run our application. Create a file named Procfile at the root of your application:

web: java -Dserver.port=$PORT -Dspring.profiles.active=heroku,prod -jar app.jar

There are several things to note here. First, we declare our application as a web application. We also redefine the port on which our application will run using an environment variable. This is very important as your app will cohabit with many others and only one port will be allocated to each one.

Finally, you can see that our application will run using two profiles. The first is the prod profile, which we created in the previous chapter, to optimize the performance, and a new heroku profile that we will create in a moment.

A Heroku profile

We do not want to put sensible information, such as our Twitter app keys, into source control. So, we have to create some properties that will read those from the application environment:

spring.social.twitter.appId=${twitterAppId}
spring.social.twitter.appSecret=${twitterAppSecret}

For this to work, you have to configure the two environment variables, which we discussed earlier, on Heroku. You can do this with the toolbelt:

> heroku config:set twitterAppId=appId

Alternatively, you can go to your dashboard and configure the environment in the settings tab:

A Heroku profile

Running your application

It is now time to run our application on Heroku!

If you haven't already done so, commit all your changes to your master branch. Now, simply push your master branch to the heroku remote with git push heroku master. This will download all the dependencies and build your application from scratch, so it can take a little time:

> git push heroku master
Counting objects: 1176, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (513/513), done.
Writing objects: 100% (1176/1176), 645.63 KiB | 0 bytes/s, done.
Total 1176 (delta 485), reused 1176 (delta 485)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Gradle app detected
remote: -----> Installing OpenJDK 1.8... done
remote: -----> Building Gradle app...
remote:        WARNING: The Gradle buildpack is currently in Beta.
remote: -----> executing ./gradlew stage
remote:        Downloading https://services.gradle.org/distributions/gradle-2.3-all.zip

...

remote:        :check
remote:        :build
remote:        :stage
remote:
remote:        BUILD SUCCESSFUL
remote:
remote:        Total time: 2 mins 36.215 secs
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote:
remote: -----> Compressing... done, 130.1MB
remote: -----> Launching... done, v4
remote:        https://appname.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy.... done.
To https://git.heroku.com/appname.git
* [new branch]      master -> master

Once the application has been built, it will automatically run. Type heroku logs to see the latest logs or heroku logs -t to tail them.

You can see your application running in the console and if all goes as planned, you will be able to connect to http://yourapp.herokuapp.com. As shown in the following screenshot:

Running your application

We are live! It's time to tell your friends!

Activating Redis

To activate Redis in our application, we can choose between a few alternatives. The Heroku Redis add-on is the beta version. It is entirely free with 20 MB of storage, analytics, and logs.

At this stage, you will have to provide your credit card details to proceed.

To install the Redis add-on for your application, type the following:

heroku addons:create heroku-redis:test

Now, that we have activated the add-on, an environment variable called REDIS_URL will be available when our application will be running on Heroku.

You can check that the variable is defined with the heroku config command:

> heroku config
=== masterspringmvc Config Vars
JAVA_OPTS:        -Xmx384m -Xss512k -XX:+UseCompressedOops
REDIS_URL:        redis://x:[email protected]:6439

Since the RedisConnectionFactory class does not understand URIs, we need to tweak it a little bit:

@Configuration
@Profile("redis")
@EnableRedisHttpSession
public class RedisConfig {

    @Bean
    @Profile("heroku")
    public RedisConnectionFactory redisConnectionFactory() throws URISyntaxException {
        JedisConnectionFactory redis = new JedisConnectionFactory();

        String redisUrl = System.getenv("REDIS_URL");
        URI redisUri = new URI(redisUrl);
        redis.setHostName(redisUri.getHost());
        redis.setPort(redisUri.getPort());
        redis.setPassword(redisUri.getUserInfo().split(":", 2)[1]);

        return redis;
    }

    @Bean
         @Profile({"cloud", "heroku"})
    public static ConfigureRedisAction configureRedisAction() {
        return ConfigureRedisAction.NO_OP;
    }
}

We now have two Heroku-specific beans in the RedisConfig class. These beans will only be active if both the redis and heroku profiles are active.

Note that we also deactivated some Spring Session configuration.

Spring Session will normally listen to events associated to destroyed session keys via the Redis Pub/Sub interface.

It will automatically try to configure the Redis environment to activate listeners on startup. In a secured environment like ours, adding listeners is not permitted unless you have an admin access.

These redis listeners are not really important in our case, so we can safely disable this behavior. For more information, visit http://docs.spring.io/spring-session/docs/current/reference/html5/#api-redisoperationssessionrepository-sessiondestroyedevent.

We need to modify our Procfile file so that Heroku runs our application with the redis profile:

web: java -Dserver.port=$PORT -Dspring.profiles.active=heroku,redis,prod -jar app.jar

Commit your change and push the code to Heroku.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.216.151.164