100% found this document useful (11 votes)
57 views

Complete Download Deploying with JRuby 9k Deliver Scalable Web Apps Using the JVM 1st Edition Joe Kutner PDF All Chapters

Scalable

Uploaded by

meeganlatuz
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (11 votes)
57 views

Complete Download Deploying with JRuby 9k Deliver Scalable Web Apps Using the JVM 1st Edition Joe Kutner PDF All Chapters

Scalable

Uploaded by

meeganlatuz
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 71

Download the full version of the ebook at

https://ebookultra.com

Deploying with JRuby 9k Deliver Scalable Web


Apps Using the JVM 1st Edition Joe Kutner

https://ebookultra.com/download/deploying-with-
jruby-9k-deliver-scalable-web-apps-using-the-
jvm-1st-edition-joe-kutner/

Explore and download more ebook at https://ebookultra.com


Recommended digital products (PDF, EPUB, MOBI) that
you can download immediately if you are interested.

React js Essentials A fast paced guide to designing and


building scalable and maintainable web apps with React js
1st Edition Fedosejev
https://ebookultra.com/download/react-js-essentials-a-fast-paced-
guide-to-designing-and-building-scalable-and-maintainable-web-apps-
with-react-js-1st-edition-fedosejev/
ebookultra.com

Using Docker Developing and Deploying Software with


Containers 1st Edition Adrian Mouat

https://ebookultra.com/download/using-docker-developing-and-deploying-
software-with-containers-1st-edition-adrian-mouat/

ebookultra.com

Developing Web Apps with Haskell and Yesod 2nd Edition


Michael Snoyman

https://ebookultra.com/download/developing-web-apps-with-haskell-and-
yesod-2nd-edition-michael-snoyman/

ebookultra.com

Pro Android Web Apps Develop for Android Using HTML5 CSS3
JavaScript 1st Edition Damon Oehlman

https://ebookultra.com/download/pro-android-web-apps-develop-for-
android-using-html5-css3-javascript-1st-edition-damon-oehlman/

ebookultra.com
Web Application Development with R Using Shiny Beeley

https://ebookultra.com/download/web-application-development-with-r-
using-shiny-beeley/

ebookultra.com

Progressive Web Apps 1st Edition Jason Grigsby

https://ebookultra.com/download/progressive-web-apps-1st-edition-
jason-grigsby/

ebookultra.com

AngularJS Up and Running Enhanced Productivity with


Structured Web Apps 1st Edition Shyam Seshadri

https://ebookultra.com/download/angularjs-up-and-running-enhanced-
productivity-with-structured-web-apps-1st-edition-shyam-seshadri/

ebookultra.com

Server Driven Web Apps with htmx Any Language Less Code
Simpler Code 1st Edition R. Mark Volkmann

https://ebookultra.com/download/server-driven-web-apps-with-htmx-any-
language-less-code-simpler-code-1st-edition-r-mark-volkmann/

ebookultra.com

Beginning Android Web Apps Development 1st ed. Edition Jon


Westfall

https://ebookultra.com/download/beginning-android-web-apps-
development-1st-ed-edition-jon-westfall/

ebookultra.com
Deploying with JRuby 9k Deliver Scalable Web Apps
Using the JVM 1st Edition Joe Kutner Digital Instant
Download
Author(s): Joe Kutner
ISBN(s): 9781680501698, 1680501690
Edition: 1
File Details: PDF, 6.62 MB
Year: 2016
Language: english
Early praise for Deploying with JRuby 9K

Joe has pulled together a great collection of deployment knowledge from his years
of experience building and supporting JRuby applications. He’s an expert on this
subject and Deploying with JRuby 9k is the definitive text for getting JRuby appli-
cations up and running.
➤ Charles Oliver Nutter
JRuby co-lead

Deploying with JRuby 9k answers the most frequently asked questions about real-
world use of JRuby. Whether you’re coming to JRuby from Ruby or Java, Joe fills
in all the gaps you’ll need to deploy JRuby with confidence.
➤ Tom Enebo
JRuby co-lead

I’ve been working with JRuby for years and I still learned several immediately
actionable steps to improve the performance and maintenance of real-world
JRuby apps.
➤ Matt Margolis
director, application development at Getty Images

Deploying with JRuby 9k is full of practical and actionable advice about how to
get the most benefit out of the JVM when running your Ruby app on JRuby.
➤ Chris Seaton
Oracle Labs and JRuby contributor
Deploying with JRuby 9k is the essential guide for anyone building Ruby applica-
tions on the JVM. It’s loaded with tips, tricks, and best practices that newcomers
and experts can learn from.
➤ Terence Lee
Ruby task force member at Heroku

As a developer of MRI, I get super jealous reading about the JVM ecosystem and
tooling. With this book, Joe has finally made that ecosystem approachable for
JRuby applications.
➤ Zachary Scott
Ruby-core member and maintainer of Sinatra
Deploying with JRuby 9k
Deliver Scalable Web Apps Using the JVM

Joe Kutner

The Pragmatic Bookshelf


Raleigh, North Carolina
Many of the designations used by manufacturers and sellers to distinguish their products
are claimed as trademarks. Where those designations appear in this book, and The Pragmatic
Programmers, LLC was aware of a trademark claim, the designations have been printed in
initial capital letters or in all capitals. The Pragmatic Starter Kit, The Pragmatic Programmer,
Pragmatic Programming, Pragmatic Bookshelf, PragProg and the linking g device are trade-
marks of The Pragmatic Programmers, LLC.
Every precaution was taken in the preparation of this book. However, the publisher assumes
no responsibility for errors or omissions, or for damages that may result from the use of
information (including program listings) contained herein.
Our Pragmatic books, screencasts, and audio books can help you and your team create
better software and have more fun. Visit us at https://pragprog.com.

The team that produced this book includes:


Brian P. Hogan (editor)
Potomac Indexing, LLC (index)
Linda Recktenwald (copyedit)
Gilson Graphics (layout)
Janet Furlow (producer)

For sales, volume licensing, and support, please contact [email protected].

For international rights, please contact [email protected].

Copyright © 2016 The Pragmatic Programmers, LLC.


All rights reserved.

No part of this publication may be reproduced, stored in a retrieval system, or transmitted,


in any form, or by any means, electronic, mechanical, photocopying, recording, or otherwise,
without the prior consent of the publisher.

Printed in the United States of America.


ISBN-13: 978-1-68050-169-8
Encoded using the finest acid-free high-entropy binary digits.
Book version: P1.0—July 2016
Contents

Acknowledgments . . . . . . . . . . . ix
Preface . . . . . . . . . . . . . . xi

1. Getting Started with JRuby . . . . . . . . . 1


What Makes JRuby So Great? 2
Preparing Your Environment 4
Introducing Warbler 7
Creating a JRuby Microservice 10
Wrapping Up 15

2. Creating a Deployment Environment . . . . . . . 17


Installing Docker 17
Getting Started with Docker 20
Creating a Docker Image 22
Deploying to the Cloud 24
Wrapping Up 27

3. Deploying a Rails Application . . . . . . . . 29


What Is Traditional Deployment? 29
Porting to JRuby 30
Configuring Rails for Production 34
Creating the Deployment Environment 36
Deploying to the Public Cloud 40
Deploying to Private Infrastructure 41
Wrapping Up 48

4. Consuming Backing Services with JRuby . . . . . 49


What Are Backing Services? 49
Storing Sessions in Memcached 50
Running Background Jobs with Sidekiq 56
Contents • vi

Message Passing with RabbitMQ 62


Wrapping Up 71

5. Deploying JRuby in the Enterprise . . . . . . . 73


What Is an Application Server? 74
Getting Started with TorqueBox 75
Scheduling a Recurring Job 77
Using the Cache 78
Deploying to the Public Cloud 81
Deploying to Private Infrastructure 81
Using a Commercially Supported Server 83
Wrapping Up 86

6. Managing a JRuby Application . . . . . . . . 87


Creating a Memory Leak 87
Inspecting the Runtime with VisualVM 88
Inspecting the Runtime with JMX 93
Invoking MBeans Programmatically 96
Creating a Management Bean 98
Using the JRuby Profiler 100
Analyzing a Heap Dump 103
Wrapping Up 107

7. Tuning a JRuby Application . . . . . . . . 109


Setting the Heap Size 109
Setting Metaspace Size 111
Configuring Heap Generations 112
Choosing a Garbage Collector 114
Benchmarking the Garbage Collector 116
Using invokedynamic 120
Wrapping Up 121

8. Monitoring JRuby in Production . . . . . . . 123


Installing the New Relic Gem 123
Creating a New Relic Alert 126
Handling Errors with Rollbar 127
Customizing Rollbar Reporting 131
Wrapping Up 132

9. Using a Continuous Integration Server . . . . . . 133


Installing Jenkins 133
Installing Jenkins Plugins 134
Contents • vii

Creating a Git Depot 135


Creating a Jenkins Job 136
Enabling Continuous Delivery 139
Wrapping Up 140

Index . . . . . . . . . . . . . . 143
Acknowledgments
Writing a book is a lot like writing code. You need to know the rules, recognize
patterns, and occasionally know when to break the rules. Both writing and
coding are crafts. And like with any craft, you improve by getting advice from
more experienced professionals and being critiqued by your peers. I’m so
fortunate to have had this kind of help.

I’m inexpressibly thankful to those who reviewed this book prior to its publi-
cation. I was humbled by the attention to detail and wise feedback they pro-
vided in making it a finished product. Thank you, Jeff Holland, Margaret Le,
Matt Margolis, Jay McGaffigan, Chris Seaton, and Tim Uckun. I consider you
all to be my friends!

I’d also like to thank the staff at the Pragmatic Bookshelf: Susannah Pfalzer,
Dave Thomas, Andy Hunt, and probably a whole bunch of other people I don’t
know about.

Above all, thank you, Brian P. Hogan, my editor. This is our fourth endeavor
together, and as usual I’ve become a better writer because of it. I look forward
to working on future projects together.

I must also thank the creators of the technologies I’ve written about. This
book would not have been possible without your hard work. Thank you,
Charles Nutter, Thomas Enebo, Karol Buček, Christian Meier, Chris Seaton,
and the rest of the JRuby team. You’re the most amazing group in all of the
open source world. I owe you all my deepest gratitude and a free beverage.

Finally, I’d like to thank my wife and son. I could not have completed this
project without your love and support.

report erratum • discuss


Preface
Your website has just crashed, and you’re losing money. The application is
built on Rails, runs on MRI, and is served up with Unicorn and Apache.
Having this kind of infrastructure means you’re managing more processes
than you can count on two hands.

The background jobs are run with Resque,1 the scheduled jobs are run with
2
cron, and the long-running jobs use Ruby daemons, which are monitored by
monit because they tend to crash.3 It’s going to take some time to figure out
which component is the culprit because you have no centralized management
interface. Standing up a new server will take almost as long because the
infrastructure is so complex. But the website has to get back online if you’re
going to stay in business.

The problem I’ve just described is all too common. It has happened to everyone
from small startups to large companies that use Rails to serve millions of
requests. Their infrastructure is complex, and the myriad components are
difficult to manage because they’re heterogeneous and decentralized in nature.
Even worse, Rubyists have become comfortable with this way of doing things,
and some may think it’s the only way of doing things. But that’s not the case.

The recent growth and increased adoption of the Java Virtual Machine (JVM)
as a platform for Ruby applications has opened many new doors. Deployment
strategies that weren’t possible with MRI Ruby are now an option because of
the JVM’s built-in management tools and support for native operating system
threads. Ruby programmers can leverage these features by deploying their
applications on JRuby.

It’s common for Ruby programmers to think that JRuby deployment will look
identical to deployment with MRI Ruby (that is, running lots of JVM processes

1. https://github.com/resque/resque
2. http://daemons.rubyforge.org/
3. http://mmonit.com/monit/

report erratum • discuss


Preface • xii

behind a load balancer and putting all asynchronous background jobs in a


separate process). On the other hand, Java programmers tend to deploy
JRuby applications the same way they deploy Java applications. This often
requires lots of XML and custom build configurations, which negate many of
the benefits of a more dynamic language such as Ruby. But there are much
better options than both Ruby and Java programmers are used to.

In this book, you’ll explore the most popular and well-supported methods for
deploying JRuby. You have a surprising amount of flexibility in the processes
and platforms to choose from, which allows Ruby and Java programmers to
tailor their deployments to suit many different environments.

The No-Java-Code Promise


You won’t have to write any Java code as you work your way through this
book. That’s not what this book is about. It’s about deploying Ruby applica-
tions on the JVM. The technologies and tools you’ll learn about in this book
hide the XML and Java code from you. As the JRuby core developers like to
say, “[They] write Java so you don’t have to.”4

You may want to include some Java code in your application. Or you may
want to make calls to some Java libraries. That’s entirely your choice. If you
want to write your programs exclusively in Ruby and deploy them on the Java
Virtual Machine—as so many of us do—then go ahead.

There are many reasons to deploy Ruby applications on the JVM, and using
Java libraries and APIs is just one of them. In this book, you’ll learn how to
get the most out of the JVM without writing any Java code.

What’s in This Book?


Over the course of this book, you’re going to work on an application like the
one described at the beginning of the preface. You’ll port it to JRuby, add
some new features, and simplify its infrastructure, which will improve its
ability to scale.

The application’s name is Twitalytics, and it’s a rich Twitter client. (As you
probably know, Twitter is a social networking website that’s used to post
short status updates, called tweets.) Twitalytics tracks an organization’s
tweets, annotates them, and performs analytic computations against data
captured in those tweets to discover trends and make predictions. But it can’t
handle its current load.

4. http://vimeo.com/27494052

report erratum • discuss


What’s in This Book? • xiii

Twitalytics has several background jobs that are used to stream tweets into
the application, perform analytics, and clean up the database as it grows. In
addition, it receives a large volume of HTTP requests for traditional web traffic.
But doing this on MRI means running everything in separate processes, which
consumes more resources than its infrastructure can handle.

You’ll begin working on the app in Chapter 1, Getting Started with JRuby, on
page 1. You’ll learn what makes JRuby a better deployment platform and
why it’s a good fit for this application. Then you’ll extract a microservice from
the Twitalytics monolith, port it to JRuby, and package it into an archive file
with the Warbler gem. But before you can deploy it, you’ll need to create an
environment where it can run.

In Chapter 2, Creating a Deployment Environment, on page 17, you’ll set up


a containerization layer based on Docker and provision it with some essential
components. You’ll also learn how to automate this process to make it more
reliable and reusable. You’ll create a new server for each deployment strategy
used in this book, and being able to reuse your configuration will save you
time and prevent errors. In fact, this environment will apply not only to
Twitalytics but to any JRuby deployment, so you’re likely to reuse it on the job.

Once you’ve completed the production server setup, you’ll be ready to deploy.
You’ll learn how JRuby deployment differs from the more common practice
of traditional Ruby application deployment and how containerization technolo-
gies like Docker can simplify the process. In additional to using Docker, you’ll
deploy to the cloud on the Heroku platform as a service.

The Warbler gem gives you a quick way to get started with JRuby. But it’s
just a stepping-stone on your path to better performance. As the book pro-
gresses, you’ll improve your deployment strategy by running Twitalytics on
some other JRuby web servers.

The next chapter, Chapter 3, Deploying a Rails Application, on page 29, is


dedicated to the Puma web server. Puma allows you to deploy applications
much as you would with MRI-based Rails applications. But you’ll find that
JRuby reduces the complexity of this kind of deployment environment while
increasing its reliability and portability. You’ll deploy the Puma-based Rails
app using both Docker and Heroku. The resulting architecture will be
friendly and familiar to Rubyists.

But you still won’t be making the most of what the JVM has to offer. To do
that, you’ll need a new kind of platform.

report erratum • discuss


Preface • xiv

In Chapter 5, Deploying JRuby in the Enterprise, on page 73, you’ll learn about
a Ruby application server. You’ll use TorqueBox, a server based on the popular
JBoss application server, to run Twitalytics. This kind of deployment is unique
when compared to traditional Ruby deployments because it provides a com-
plete environment to run any kind of program, not just a web application.
You’ll learn how this eliminates the need for external processes. In the end,
you’ll have the most advanced deployment environment available to any Ruby
application.

An overview of each strategy covered in this book is listed here:

Warbler Puma TorqueBox


Internals Jetty Pure-Ruby JBoss AS
Deployment type WAR file Traditional Mixed
Docker deployment Yes Yes Yes
Heroku deployment Yes Yes Yes
Background jobs No No Yes

Deciding on the right platform for each application is a function of these


attributes. But getting an application up and running on one of these platforms
is only a part of the job. You also need to keep it running. Fortunately, one
of the many advantages of JRuby is the built-in JVM tooling.

Chapter 6, Managing a JRuby Application, on page 87 presents some tools


for monitoring, managing, and configuring a deployed JRuby application.
These tools are independent of any deployment strategy and can be used to
monitor the memory consumption, performance, and uptime of any Java
process. The information you gain from these tools can be used to improve
the performance of JRuby, which you’ll learn in Chapter 7, Tuning a JRuby
Application, on page 109. You’ll learn about different kinds of memory and the
various knobs you can turn to optimize how the JVM allocates that memory.
You’ll even learn how to change garbage collectors and benchmark them.

In Chapter 8, Monitoring JRuby in Production, on page 123, you’ll learn how to


capture the same kind of metrics from a production runtime. You’ll use some
third-party apps to instrument your code, capture performance data, and log
errors. Finally, Chapter 9, Using a Continuous Integration Server, on page 133
will introduce a tool for producing reliable and consistent deployments.

Twitalytics is a Rails application, and you’ll use this to your advantage as you
deploy it. But all of the server technologies you’ll use work equally well with

report erratum • discuss


What’s Not in This Book? • xv

any Rack-compliant framework (such as Sinatra5). In fact, the steps you’ll


use to package and deploy Twitalytics would be identical for these other
frameworks. Warbler, Puma, and TorqueBox provide a few hooks that make
deploying a Rails application more concise in some cases (such as automati-
cally packaging bundled gems). But the workflow is the same.

When you encounter Rails-specific features in this book, be aware that this
is only for demonstration purposes and not because the frameworks being
used work exclusively with Rails. Rails works with these servers because it’s
Rack based.

What’s Not in This Book?


This book won’t teach you how to write code in the Ruby language. You’ll
write a bit of Ruby code in the course of this book, but you won’t learn about
specific features of the Ruby language. In particular, this book doesn’t cover
continuations, ObjectSpace, fibers, and other topics that have subtle differences
when applied to JRuby. This book is specifically about deploying JRuby
applications and how JRuby affects your production environments.

Other topics not addressed include zero-downtime deployments, database


migrations, the asset pipeline, and content delivery networks (CDN). These
are important aspects of Ruby web application development, but they’re not
notably different between MRI and JRuby. You can learn about these topics
in books on the Ruby language and Rails. The same concepts will apply to
JRuby.

Who Is This Book For?


This book is for programmers, system administrators, and DevOps6 profes-
sionals who want to use JRuby to power their applications but aren’t familiar
with how this new platform will change their infrastructure.

You’re not required to have any experience with JRuby. This book is written
from the perspective of someone who is familiar with MRI-based Ruby
deployments but wants a modern deployment strategy for their applications.
Some of the concepts we’ll discuss may be more familiar to programmers with
Java backgrounds, but it’s not required that you have any experience with
Java or its associated technologies.

5. http://www.sinatrarb.com/
6. http://en.wikipedia.org/wiki/DevOps

report erratum • discuss


Preface • xvi

Conventions
The examples in this book can be run on Linux, Mac, Windows, and many
other operating systems. But some small changes to the command-line
statements may be required for certain platforms.

We’ll use notation from bash, which is the default shell on Mac OS X and many
Linux distributions. The $ prompt will be used for all command-line examples.
Windows command prompts typically use something like C:\> instead, so when
you see a command like this
$ bundle install

you’ll know not to type the dollar sign and to read it like this:
C:\> bundle install

Most commands will be compatible between Windows and bash systems (such
as cd and mkdir). In the cases where they’re not compatible, the appropriate
commands for both systems will be spelled out. One case in particular is the
rm command, which will look like this:

$ rm temp.txt
$ rm -rf tmp/

On Windows this should be translated to these two commands, respectively:


C:\> del temp.txt
C:\> rd /s /q tmp/

Another Unix notation that’s used in this book is the ~ (tilde) to represent a
user’s home directory. When you see a command like this
$ cd ~/code/twitalytics

you can translate it to Windows 10 as this command:


C:\> cd C:\Users\yourname\code\twitalytics

On earlier versions of Windows, the user’s home directory can be found in


the Documents and Settings directory. You can also use the %USERPROFILE% environ-
ment variable. Its value is the location of the current user’s profile directory.

Other than these minor notation changes, the examples in this book are
compatible with Windows by virtue of the Java Virtual Machine.

Getting the Source Code


You’re ready to set up the Twitalytics application. Start by downloading the
source code from http://pragprog.com/titles/jkdepj2/source_code. Unpack the downloaded

report erratum • discuss


Online Resources • xvii

file and put it in your home directory. This will create a code directory and
inside that will be a twitalytics directory, which contains the baseline code for
the application (in other words, the MRI-based code).

But you’re not quite ready to run this code with JRuby. It needs to be ported
first. You’ll learn how to do that in the coming chapters.

Online Resources
Several online resources can help if you’re having trouble setting up your
environment or running any of the examples in this book.

For Java-related problems, the Java Community has forums7 and numerous
Java-related articles.

For JRuby-related problems, the official JRuby website8 has links to several
community outlets. The most useful of these are the mailing list9 and the
#jruby IRC channel on FreeNode.10

For TorqueBox-related problems, there are a mailing list,11 extensive docu-


mentation,12 and the #torquebox IRC channel on FreeNode.

7. https://community.oracle.com/community/java
8. http://jruby.org/community
9. https://github.com/jruby/jruby/wiki/MailingLists
10. http://freenode.net/
11. http://torquebox.org/community/mailing_lists/
12. http://torquebox.org/documentation/

report erratum • discuss


CHAPTER 1

Getting Started with JRuby


JRuby is a high-performance platform that can scale to meet demand without
the headaches of an MRI-based deployment. Those headaches are often the
result of running a dozen or more processes on a single server that all need
to be monitored, balanced, and occasionally restarted. JRuby avoids these
problems by simplifying the architecture required to run an application. In
this chapter, you’re going to port a microservice to JRuby so that you can
take advantage of this simplicity and scalability. But in order to run the
microservice in production, you’ll need a way to deploy it. For this, you’ll use
Warbler.1

Warbler is a gem used to package source code into an archive file you can
deploy without the need for complicated configuration management scripts.
This makes the process more flexible, portable, and faster.

In Preface, on page xi, you were introduced to Twitalytics, a Ruby on Rails


app that needs help. Its infrastructure is too complex, and it can’t handle the
volume of requests the site is receiving. You don’t have time to port the dae-
mons and background jobs to a new framework, but you need to get one high-
traffic HTTP service deployed on JRuby. If you can do that, you’ll be able to
handle lots of concurrent requests without hogging the system’s memory.
Later in the book, you’ll consume this service from the main Rails app that
makes up the bulk of Twitalytics.

Your time constraints make Warbler a great solution. It won’t maximize your
use of the JVM, but it will allow you to take advantage of the most important
parts. You’ll be able to service all of your site’s web requests from a single
process without changing much code. The drawback is that you’ll have to

1. https://github.com/jruby/warbler

report erratum • discuss


Chapter 1. Getting Started with JRuby •2

make changes to your deployment process, so there’s much to learn. Let’s


begin by discussing why you might want to use JRuby in the first place.

What Makes JRuby So Great?


A production JRuby environment has fewer moving parts than traditional
Ruby environments. This is possible because of the JVM’s support for native
operating system threads. Instead of managing dozens of processes, JRuby
can use multiple threads of execution to do work in parallel. MRI has threads,
but only one thread can execute Ruby code at a time. Recent versions of MRI,
Rails, and other frameworks have improved the platform’s ability to do some
work in parallel. But true concurrency on MRI isn’t possible, and the quest
for better throughput has led to some complicated solutions.

Deployment with MRI usually requires a type of architecture that handles


HTTP requests by placing either Apache2 or a similar web server in front of a
pool of application instances running in separate processes. An example of
this is illustrated in the following figure.

HTTP
Request

Apache/Nginx

MRI MRI

App App

2. http://httpd.apache.org/

report erratum • discuss


What Makes JRuby So Great? •3

There are many problems with this kind of architecture, and those problems
have been realized by Twitter, GitHub, and countless others. They include
the following:

Stuck processes Sometimes the processes will get into a stuck state and
need to be killed by an external tool like god or Monit.

Slow restarts There’s a lot of overhead in starting a new process. Several


instances may end up fighting each other for resources if they’re restarted
at the same time.

Memory growth Each of the processes keeps its own copy of an application,
along with Rails and any supporting gems, in memory. Each new instance
means you’ll also need more memory for the server.

Several frameworks, such as Passenger and Unicorn, have improved on this


model. But they all suffer from the same underlying constraint. A single MRI
process has a scalability ceiling because Ruby code cannot execute in parallel.
Other operations, such as I/O, can be done in parallel, and frameworks such
as EventMachine and Celluloid leverage this to create event-based environ-
ments. But these frameworks also have an upper limit, and that’s why some
of their biggest implementers, including Logstash3 and Venntro,4 still choose
to run them on JRuby.

JRuby enables a similar model to the one used by MRI but with only one JVM
process. Inside this JVM process is a single application instance capable of
handling all of a website’s traffic. This works by allowing the platform to create
many threads that run against the same application instance in parallel. You
can create far more JVM threads than MRI processes because they’re much
lighter in weight. This model is illustrated in the figure on page 4.

Apache is included in the architecture diagram, but its role for a single
instance is greatly reduced. It may be used to serve up static content and
load balance a distributed cluster, but it won’t need to distribute requests
across multiple processes on a single machine.

In the coming chapters, you’ll build an architecture like the one just described
with each of the technologies you use. You’ll start by using Warbler to package
a simple Rack application, which will get you up and running quickly. But
first, you’ll need to install JRuby and a few other pieces of software.

3. https://www.elastic.co/products/logstash
4. http://dev.venntro.com/2013/07/euruko-2013-summary/

report erratum • discuss


Chapter 1. Getting Started with JRuby •4

HTTP
Request

Apache/Nginx

JVM

Thread
App Thread
Thread
Thread

Preparing Your Environment


Four software packages are required to run the examples in the book. They’re
listed here along with the version needed:

• Java Development Kit (JDK) 8 (aka 1.8)


• JRuby 9.0.5.0
• Git 2.5
• Bundler 1.11

Java is supported in one form or another on a wide range of operating systems


including Linux, Mac, Windows, and more. But the installation process will
be different for each platform.

Installing Java
On Debian-based Linux platforms such as Ubuntu, the JVM can be installed
with APT, like this:
$ sudo apt-get install openjdk-8-jdk

report erratum • discuss


Preparing Your Environment •5

On Fedora, Oracle Linux, and Red Hat, the JVM is installed with the yum
command, like this:
$ su -c "yum install java-1.8.0-openjdk"

For Mac OS X and Windows systems, you can download the latest version of
Java 8 directly from Oracle’s website.5

For Windows systems, you’ll need to set the JAVA_HOME variable. (The exact
path may vary.)
C:\> set JAVA_HOME="C:\Program Files\Java\jdk1.8.0_72"

In all cases, you can check that the JVM was installed correctly by running
this command:
$ java -version
java version "1.8.0_72"
Java(TM) SE Runtime Environment (build 1.8.0_72-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.72-b15, mixed mode)

Now that the JVM is ready, you can put JRuby on your machine.

Installing JRuby and Bundler


The preferred method for installing JRuby on Unix and Linux systems requires
the Ruby Version Manager (RVM). It’s preferred not only because it makes
JRuby easy to install but also because it treats JRuby just like any other
Ruby platform. This allows you to use the ruby and gem commands without
putting the j character in front of them or prefixing every other command with
jruby -S. RVM is compatible only with bash systems, which don’t include Win-
dows. Installing JRuby on Windows will be described in a moment. If you’re
using a bash system, run this command to download the GPG key for RVM:
$ gpg --keyserver hkp://keys.gnupg.net \
--recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3

Then run this command to install RVM:


$ \curl -sSL https://get.rvm.io | bash -s stable

The leading backslash in the command disables any aliases you may have
set in your shell and runs the curl binary directly.

You’ll also need to reload your shell. The most dependable way to do this is
by closing your terminal and opening a new one. In the new terminal, use
RVM to install JRuby with this command:

5. http://www.oracle.com/technetwork/java/javase/downloads/index.html

report erratum • discuss


Chapter 1. Getting Started with JRuby •6

$ rvm install jruby-9.0.5.0


Searching for binary rubies, this might take some time.
Unknown ruby string (do not know how to handle): jruby-9.0.5.0.
Found remote file /Users/jkutner/.rvm/archives/jruby-bin-9.0.5.0.tar.gz
Checking requirements for osx.
Requirements installation successful.
jruby-9.0.5.0 - #configure
Unknown ruby string (do not know how to handle): jruby-9.0.5.0.
jruby-9.0.5.0 - #download
jruby-9.0.5.0 - #validate archive
jruby-9.0.5.0 - #extract
jruby-9.0.5.0 - #validate binary
jruby-9.0.5.0 - #setup
jruby-9.0.5.0 - #gemset created /Users/jkutner/.rvm/gems/jruby-9.0.5.0...
jruby-9.0.5.0 - #importing gemset /Users/jkutner/.rvm/gemsets/jruby/gl...
jruby-9.0.5.0 - #generating global wrappers........
jruby-9.0.5.0 - #gemset created /Users/jkutner/.rvm/gems/jruby-9.0.5.0
jruby-9.0.5.0 - #importing gemsetfile /Users/jkutner/.rvm/gemsets/defa...
jruby-9.0.5.0 - #generating default wrappers........
Making gemset jruby-9.0.5.0 pristine.....................................
Making gemset jruby-9.0.5.0@global pristine..............................

Set JRuby as the default Ruby on your platform by running this command:
$ rvm --default use jruby-9.0.5.0
Using /Users/jkutner/.rvm/gems/jruby-9.0.5.0

On Windows, you can install JRuby by downloading and running the Windows
installer from the official JRuby website.6

If you’re using any other kind of system or if you prefer not to use RVM, then
JRuby can be installed manually with these three steps:

1. Download the JRuby binaries from the official website.7

2. Unpack the downloaded file, which will create a jruby-<version> directory.

3. Add jruby-<version>/bin to the PATH.

You can check that JRuby was installed correctly with this command:
$ ruby -v
jruby 9.0.5.0 (2.2.3) 2016-01-26 7bee00d Java HotSpot(TM) 64-Bit
Server VM 25.72-b15 on 1.8.0_72-b15 [darwin-x86_64]

Without RVM, you’ll have to modify the commands used in this book. RVM
lets you invoke JRuby without the jruby or jgem commands, so you’ll need to
change all ruby commands in this book to jruby commands. You’ll also need to

6. http://jruby.org/files/downloads/9.0.5.0/index.html
7. http://jruby.org/files/downloads/9.0.5.0/index.html

report erratum • discuss


Introducing Warbler •7

prefix other commands (such as bundle, gem, and rails) with the jruby -S prefix,
like this:
$ jruby -S bundle install

Of course, before you can run bundle install, you’ll need to install Bundler. If
you’re using RVM, run this command:
$ gem install bundler -v 1.11.2

If you’re not using RVM, run this command:


$ jgem install bundler -v 1.11.2

You will never be asked to run any of the examples in this book with MRI
Ruby. Remember, when you see the ruby, gem, rake, or similar commands,
you’re expected to run them with JRuby.

Let’s move on to the next package.

Installing Git
Git is a source control management tool that allows you to track versions of
your code. You’ll use Git to switch between different versions of Twitalytics
as you deploy it to new platforms. Follow the instructions for downloading
and installing Git from the official website.8

It’s OK to use some other form of version control if you’d prefer, but the
examples in this book will be specific to Git. Most of the examples will even
work without version control software, but that’s not recommended. The
source code for each branch you’ll create is available from http://pragprog.com/
titles/jkdepj2/source_code, so instead of switching branches, you can change to the
directory that corresponds to the chapter you’re reading. If you don’t use Git,
some of the Heroku examples later in the book won’t work.

Now that your software dependencies are installed, let’s move on and run
some actual code.

Introducing Warbler
Warbler is a gem that creates a web application archive (WAR) file from a
Rails- or Rack-based application.

A WAR file is a zip file that follows a few conventions. Warbler takes care of
packaging an application according to these conventions, so all you need to
do is run the Warbler commands.

8. http://git-scm.com/download

report erratum • discuss


Chapter 1. Getting Started with JRuby •8

Joe asks:
What’s in a WAR File?
A WAR file is a special case of Java archive (JAR) file; both are really just zip files.
But a WAR file is structured according to a standard that’s recognized by all Java
web servers. You can take a closer look at this by extracting the WAR file you created
in this chapter with any unzipping tool. Inside it, you’ll find these essential components
(among many other things):

twitalytics.war
|-- index.html
|-- META-INF/
`-- MANIFEST.MF
`-- WEB-INF/
|-- lib/
`-- web.xml

The top-level directory contains all client-accessible content, which is equivalent to


the public directory in a Rails application. This is where you’ll find all of the HTML
files, images, and other static content. The WEB-INF directory contains all the dynamic
content for your web application. This includes your Ruby scripts and the Java
libraries needed to run a JRuby application. The META-INF directory contains basic
metadata about the WAR file, such as who created it and when it was created.

Inside the WEB-INF directory is the web.xml file, which is the most important part of the
archive. It contains a description of how the components in the web application are
put together at runtime. It’s similar to the config/application.rb, config/environment.rb, and
config/routes.rb files of a Rails application all combined into a single descriptor. Fortu-
nately, Warbler handles the creation of this file for you based on the settings in the
config/warbler.rb file.

You can digitally sign a WAR file, which creates a checksum for each file contained
in the archive. This is used by a web server to ensure that no one has tampered with
it or that it has not been corrupted in some way. If the checksums don’t match, then
the server won’t load the files.

The WAR file that Warbler creates will be completely self-contained and ready
to be deployed to a Java web server. Warbler bundles JRuby, your web
framework, a web server, and all of the dependencies needed to adapt a Ruby
web application to the JVM.

To demonstrate Warbler, you’ll create the simplest web application you can.
Create a directory called myapp, and in that directory create a config.ru file. Then
put the following code into it:

report erratum • discuss


Introducing Warbler •9

Warbler/myapp/config.ru

run lambda { |env|


[200, {'Content-Type' => 'text/html'}, 'Hello, World']
}

Install the Warbler gem to your JRuby gem path by running this command:
$ gem install warbler -v 2.0.1
Fetching: rubyzip-1.2.0.gem (100%)
Successfully installed rubyzip-1.2.0
Fetching: jruby-rack-1.1.20.gem (100%)
Successfully installed jruby-rack-1.1.20
Fetching: jruby-jars-9.0.5.0.gem (100%)
Successfully installed jruby-jars-9.0.5.0
Fetching: warbler-2.0.1.gem (100%)
Successfully installed warbler-2.0.1
4 gems installed

Warbler has two JRuby-specific dependencies. The jruby-jars gem includes the
core JRuby code and standard library files. This allows other gems to depend
on JRuby without freezing to a specific version. The other dependency, the
jruby-rack gem, is responsible for adapting the Java web server specification to
the Rack specification.

Next, use the warble command to create the archive file. Run it with the war
option from the same directory as the config.ru file you created earlier.
$ warble war

This creates a myapp.war file. In Chapter 2, Creating a Deployment Environment,


on page 17, you’ll learn about all the different ways you can deploy this WAR
file. For now, you just need to be able to run it so you can see how Warbler
works. To do this, you’ll create an executable WAR file by running the same
command with the executable option.
$ warble executable war

This creates a WAR file capable of running without the need for a freestanding
Java web server like Tomcat. You can run the WAR file with this command:
$ java -jar myapp.war

When the server is started, you’ll be able to access the application at


http://localhost:8080.

That’s all you need to know to get started with Warbler. Now let’s make some
adjustments to the Twitalytics application. It wasn’t built to run on JRuby,
so it has some code that’s specific to MRI. You’re going to fix these parts so
they work on the new platform.

report erratum • discuss


Chapter 1. Getting Started with JRuby • 10

Creating a JRuby Microservice


In the previous section, you packaged a simple Rack application that was
compatible with JRuby, but a real application will require more than just
Rack. In this section, you’ll package a small Sinatra-based microservice into
a WAR file. Warbler is great for small services like this because it produces
a portable lightweight artifact you can deploy quickly without any baggage.

Unfortunately, this service is an integral part of Twitalytics and it’s under


more load than MRI can handle. Porting it to JRuby to will increase its
throughput by allowing the application to process each request asynchronous-
ly. In this way, the request threads won’t block while waiting for external
services or doing data processing. To begin, move into the stock-service
sample code.
$ cd ~/code/stock-service

This directory contains the code for a small pure-Ruby HTTP service. The
service accepts a POST request with some text. It searches the text for the
names of publicly traded companies and then annotates the text with current
stock price quotes for those companies. Open the config.ru file and you’ll see
the handler:
stock-service/config.ru

post '/stockify' do
text = request.body.read.to_s
stocks = Stocks.parse_for_stocks(text)
quotes = Stocks.get_quotes(stocks)
new_text = Stocks.sub_quotes(text, quotes)
end

The first line in the handler for the /stockify route captures the body of the
request. The second line passes the text to the parse_for_stocks function, which
returns a list of symbols matching any company names mentioned in the
text. The third line uses the get_quotes function to retrieve current prices for
the stocks from a Yahoo! API. The last line combines it all by adding the
markup to the text.

Before making any changes, initialize a Git repository and create a branch
by running these commands:
$ git init
$ git add -A
$ git commit -m "initial commit"
$ git checkout -b warbler
Switched to a new branch 'warbler'

report erratum • discuss


Creating a JRuby Microservice • 11

Now you can safely configure Warbler while preserving your master branch.

The first step in porting this service to JRuby is adding Warbler to the appli-
cation’s dependencies. Open the Gemfile and put this code at the end of it:
Warbler/stock-service/Gemfile

group :development do
gem 'warbler', '2.0.1'
end

The Warbler dependency is in a development group because it’s only needed to


build a WAR file. You don’t need it in production.

Now run Bundler to install the service’s dependencies.


$ bundle install --binstubs

You’re ready to package the app into an executable WAR file with Warbler.
Since you don’t want to type the executable directive every time you package
the app, you’ll begin by adding a Warbler configuration file. Create a config/war-
ble.rb file by running this command:

$ bin/warble config

The new file contains a wealth of instructions and examples for the different
configuration options, which are helpful to read because you never know
what you’ll want to change. Don’t worry about preserving its contents. You
can always re-create it by running warble config again. Given that safety net,
replace the entire contents of the config/warble.rb file with this code:
Warbler/stock-service/config/warble.rb

Warbler::Config.new do |config|
config.features = %w(executable)
config.jar_name = "stock-service"
end

Now when you run the warble command, it will detect this configuration and
generate an executable WAR file even when you omit the executable directive
from the command line. Give it a try:
$ bin/warble war

This generates a stock-service.war file, which you can execute by running this
command:
$ java -jar stock-service.war

With the Java process running, test out the service by opening another termi-
nal window and executing this command:

report erratum • discuss


Chapter 1. Getting Started with JRuby • 12

$ curl -d "Hello Apple, a computer company" http://localhost:8080/stockify


"Hello <div class="stock" data-symbol="AAPL"
data-day-high="102.14">Apple</div>, a computer company"

The server responds with an marked-up version of the original text containing
current stock price information. Because it depends on an external API, the
service does a lot of waiting. This causes the threads that are handling
incoming HTTP requests to be blocked. It looks like the following figure.

Client Server Database

Block wait

Now imagine a request thread being freed up to handle other requests instead
of blocking for a single request to finish. It looks like the following figure.
That’s called asynchronous request processing, and it can dramatically
improve throughput in an I/O-constrained application (such as an app that
relies heavily on a database or external service).

Client Server Database

Async wait

report erratum • discuss


Creating a JRuby Microservice • 13

The JVM supports asynchronous I/O in several forms. For this microservice,
you’ll use an asynchronous context, which is a standard feature of Java, with
a background thread to free up your request thread. First, enable the asyn-
chronous capabilities of the web server by adding this line to the config block
in your config/warble.rb file:
Warbler/stock-service/config/warble.rb

config.webxml.servlet_filter_async = true

Then, add these two lines of code to the beginning of the POST handler:
Warbler/stock-service/config.ru

response.headers["Transfer-Encoding"] = "chunked"
async = env['java.servlet_request'].start_async

The first line sets a standard HTTP header that will ensure the client’s request
is kept open while the app does its asynchronous processing. The second line
creates a new asynchronous context. Now wrap the original four lines of the
POST handler in a Thread like this:
Warbler/stock-service/config.ru

text = request.body.read.to_s
Thread.new do
begin
puts "Thread(async): #{Thread.current.object_id}"
stocks = Stocks.parse_for_stocks(text)
quotes = Stocks.get_quotes(stocks)
new_text = Stocks.sub_quotes(text, quotes)
async.response.output_stream.println(new_text)
ensure
async.complete
end
end

The new Thread will allow the processing to happen in the background so the
POST handler can return. And instead of the handler simply returning some
string, it will write the output to the asynchronous context. You’ll also add a
puts statement that logs the ID of the request thread. Add this line to the end
of the POST handler (outside the Thread body).
Warbler/stock-service/config.ru

puts "Thread(main) : #{Thread.current.object_id}"

Now repackage the WAR file and run it again:


$ bin/warble
$ java -jar stock-service.war

report erratum • discuss


Chapter 1. Getting Started with JRuby • 14

And invoke the service with the same curl command as before:
$ curl -d "Text about Apple, a computer company" http://localhost:8080/stockify

The output’s the same, but in the logs you’ll see the different thread identifiers:
Thread(main) : 2332
Thread(async): 2330

Keep in mind that puts is not atomic, so you might get a bit of interweaving
in the output.

This is great, but there’s still a problem with the code. The number of threads
this service can create is unbounded, which could overrun your system. To
make things worse, creating a new thread is an expensive operation. You can
fix both of these issues by using a thread pool executor. This is a great
example of a kind of concurrency issue you must consider when using JRuby.

You can add a thread pool to the application with only a few lines. First, add
a dependency on the concurrent-ruby gem to the Gemfile by adding this code to it:
Warbler/stock-service-thread-pool/Gemfile

gem 'concurrent-ruby', require: 'concurrent'

And run Bundler to install it:


$ bundle install --binstubs

Now modify the config.ru file to use the new gem by creating a thread pool.
Immediately after the end of the App class, add this line of code:
Warbler/stock-service-thread-pool/config.ru

App.set :thread_pool,
Concurrent::ThreadPoolExecutor.new(max_threads: 100)

This uses the ThreadPoolExecutor class to create a cached thread pool and adds
it as a setting on the App class. A cached thread pool will grow organically and
reuse threads as needed. It also prevents thread starvation by setting an
upper bound on the number of threads with the max_thread option.

You can use the thread pool by replacing the Thread.new invocation in the POST
handler with a call to settings.thread_pool.post, as shown here:
Warbler/stock-service-thread-pool/config.ru

settings.thread_pool.post do
begin
puts "Thread(async): #{Thread.current.object_id}"
stocks = Stocks.parse_for_stocks(text)
quotes = Stocks.get_quotes(stocks)

report erratum • discuss


Wrapping Up • 15

new_text = Stocks.sub_quotes(text, quotes)


async.response.output_stream.println(new_text)
ensure
async.complete
end
end

Now run Bundler again, repackage with Warbler, run the app, and make the
curl request a few more times. In the logs, you’ll see that the same thread is
being used for the asynchronous part of the service each time it’s invoked.
Thread(main) : 2332
Thread(async): 2330
Thread(main) : 2334
Thread(async): 2330
Thread(main) : 2336
Thread(async): 2330

In practice, you could make this service even more reactive by using an
asynchronous HTTP client to invoke the Yahoo! service. And if the parse_for_stocks
is going to be expensive or invoke an external service, you could put it in its
own thread. Steps like these further eliminate bottlenecks in the system,
increasing the potential throughput. But they’re possible only with a truly
concurrent platform such as JRuby. You’ll learn to implement some of these
ideas later in the book.

Before moving on, commit your changes to the warbler branch with the git add
and git commit commands:
$ git add Gemfile Gemfile.lock config config.ru
$ git commit -m "Updated for JRuby"

Your microservice is now ready to be deployed to production with Warbler.

Wrapping Up
You packaged a microservice into an archive file. That’s a huge step for this
application because it means you can deploy it to any environment that has
a JVM available. There are many possibilities, including containers that run
in the cloud, containers that run on embedded devices, and containers that
run on a dedicated server.

You also learned how the JVM can simplify a Ruby architecture no matter
what JRuby web framework you use. This will be important as you work your
way through the book and as you continue to develop new applications on
your own.

report erratum • discuss


Chapter 1. Getting Started with JRuby • 16

Joe asks:
What Is Truffle?
If you follow the JRuby project on Twitter or read the JRuby mailing list, you may
have heard about a project called Truffle.

Truffle is a research project sponsored by Oracle Labs.a It’s an implementation of the


Ruby programming language on the JVM using the Graal dynamic compiler and the
Truffle AST interpreter framework.b

In early 2014, Truffle was open sourced and integrated into the larger JRuby project.
The Truffle developers and JRuby developers have been working alongside each other,
sharing code, and even sharing a mailing list for a while now. They’re not so much
competitors as they are contemporaries.

Truffle has the potential to achieve peak performance well beyond what’s possible
with standard JRuby, but it’s not production ready. Major components such as
OpenSSL and networking are yet to be completed. It also requires an experimental
JVM (Graal) and doesn’t work with a standard JVM.

You can learn more about Truffle from the project’s official website,c which is hosted
by its lead developer.

a. http://labs.oracle.com/
b. http://openjdk.java.net/projects/graal/
c. http://chrisseaton.com/rubytruffle/

Having a JRuby application packaged into a WAR file is a good first step, but
you still need to deploy it and consume it. In the coming chapters, you’ll learn
how to get this WAR file into production and how to use JRuby to invoke the
services it exposes. But first, you need to create a production environment
in which it can run.

report erratum • discuss


CHAPTER 2

Creating a Deployment Environment


A production JRuby environment is simpler than you might expect. There
aren’t any C extensions to compile, which means you won’t need to install
any native libraries. And you’ll run your entire app in a single process, which
eliminates the need for tools that do coordination and load balancing. In fact,
many JRuby deployments have only one external dependency: the JVM itself.
For that reason, the steps in this chapter form the basis for every kind of
JRuby app.

In Chapter 1, Getting Started with JRuby, on page 1, you created a small


JRuby microservice. Now you’ll provision a new environment for this service
and package it with the essential software it needs to run in production. But
just because you’re deploying a JRuby application doesn’t mean you have to
turn your world upside down. The tools you’ll use, such as Docker and Heroku,
may be familiar. And you can use them to build environments for any kind
of app. At the end of this chapter, you’ll have a deployment environment that’s
ready to scale up to meet demand and take advantage of everything JRuby
has to offer.

Installing Docker
Deployment is the process of taking code or binaries from one environment
and moving them to a another environment where you execute them. In the
case of a web app case, you’ll move code from your development machine to
a production server. You’ve already configured a development environment,
but you still need to create a production environment you can use as the
target of your deployments. For this, you’ll use Docker,1 which reduces the
process of provisioning a production environment to just a few steps.

1. http://docker.com/

report erratum • discuss


Chapter 2. Creating a Deployment Environment • 18

Docker is a Linux-based containerization platform. It runs processes in iso-


lated environments without the need for a complete visualization layer for
each process. You can use Docker to run multiple isolated processes on the
same host without excessive overhead. You’ll use Docker primarily as a
development tool, allowing you to run a simulated production environment
on a local machine. There is one catch, though. If your local machine isn’t
running Linux, you’ll need a virtual machine to run Docker. Fortunately,
Docker distributes a lightweight headless virtual machine, called Docker
Machine, that provides many advantages over traditional virtualization.

Docker Machine runs on VirtualBox,2 an open source virtualization platform.


If you’re not running Linux, you’ll need to install both of these. If you are
running Linux, you’ll need to install only Docker.

Installing Docker on Mac OS X or Windows


You can install both Docker and Docker Machine on Mac and Windows using
the Docker Toolbox native installer. Open a browser and navigate to the
Docker Toolbox website.3 Select the Installer for Mac and download it. Once
the package is downloaded, open it to run the wizard. Follow the steps in the
wizard to complete the installation as described on the Docker website.4

Now open a terminal. If you’re on Windows, you’ll need to double-click the


Docker CLI shortcut on your Desktop to open a Docker terminal instead of a
standard terminal. If the system displays a User Account Control prompt to
allow VirtualBox to make changes to your computer, choose Yes. From the
terminal, run these commands:
$ docker-machine -v
docker-machine version 0.4.0 (9d0dc7a)

$ docker-machine ls
NAME ACTIVE DRIVER STATE URL
default * virtualbox Running tcp://192.168.99.100:2376

This shows that a single Docker Machine, named default, is running.

On Mac only, you must set a few environment variables so the Docker client
can communicate with the Docker Machine. Run this command:
$ eval "$(docker-machine env default)"

2. https://www.virtualbox.org
3. https://www.docker.com/toolbox
4. http://docs.docker.com/mac/step_one/

report erratum • discuss


Installing Docker • 19

On Windows, those environment variables are set for you when you run the
Desktop app. On Mac, if you don’t want to run that command every time you
open a new terminal, then run this command to add the environment variables
to your profile:
$ docker-machine env default >> ~/.profile

Now you’re ready to use the Docker client. You can move on to Getting Started
with Docker, on page 20.

Installing Docker on Linux


Docker runs natively on Ubuntu, but it requires a 64-bit architecture and a
3.10 kernel version or later. You can check your architecture by running this
command:
$ uname -p
x86_64

And you can check your kernel version with this command:
$ uname -r
3.13.0-57-generic

If the output of either uname command doesn’t match the requirements, then
you’ll need to run Docker on a virtualization layer by installing Docker
Machine.5 Otherwise, you can install Docker natively. To begin the native
installation, update your package manager by running this command:
$ sudo apt-get update

Then install the generic Linux kernel image. This kernel has the advanced
multi-layered unification filesystem (AUFS) built in, which is required to run
Docker.
$ sudo apt-get install linux-image-generic-lts-trusty

Now reboot your machine:


$ sudo reboot

After your computer has restarted, you can install Docker with this command:
$ curl -sSL https://get.docker.com/ | sh

Now you’re ready to use the Docker CLI.

5. http://docs.docker.com/machine/install-machine/

report erratum • discuss


Chapter 2. Creating a Deployment Environment • 20

Getting Started with Docker


Verify that Docker is installed by running this command:
$ docker --version
Docker version 1.10.0, build 590d5108

Now check that Docker can communicate with Docker Machine by running
this command:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED ...

This is an empty list, but you’d see a list of running Docker processes (known
as containers) if there were any. A container represents some isolated process
or processes that are running within the Docker context. They’re isolated
from the rest of the processes on your machine and even from the other
Docker containers. This has many of the same benefits as traditional visual-
ization but with a very different underlying implementation.

In traditional visualization, a host operating system runs a hypervisor that


manages one or more complete guest operating systems. These guest operating
systems are isolated from each other, but they also add a great deal of over-
head. This model is shown in the following figure.

App App App

Guest OS Guest OS Guest OS

Hypervisor

Host OS

With Docker, each container runs natively on the host operating system via
the Docker Engine. They’re isolated from each other, but they still rely on the
host operating system to schedule processes, allocate memory, and do other
things that are common across containers. This model is shown in the figure
on page 21.

report erratum • discuss


Getting Started with Docker • 21

Container Container Container

Docker Engine

Host OS

Each Docker container is based on an image that defines the environment


the container’s processes will run in. Images are packages of software that
are loaded into a container before it runs. You might have images that include
a Java runtime or an image that includes your application’s dependencies.
You use these images as a base for creating an image that includes your
entire application, as shown here.

Docker
Container

Docker Docker
Image Container

Docker
Container

You can list the Docker images available on your machine by running this
command:
$ docker images
REPOSITORY TAG IMAGE ID CREATED ...

The command doesn’t list any images because you haven’t created any since
installing Docker a moment ago. Go ahead and download your first image.
You’ll begin with the heroku/jvm image, which mirrors the cloud environment

report erratum • discuss


Chapter 2. Creating a Deployment Environment • 22

running on the Heroku platform as a service.6 You’ll deploy to Heroku later


in the chapter, so this allows you to replicate that environment locally first.
Run the following command to pull the image (it’s several hundred megabytes,
so this may take some time):
$ docker pull heroku/jvm
Using default tag: latest
latest: Pulling from heroku/jvm
ecf3ac44a558: Pull complete
5c0c6781ba3b: Pull complete
75a40d761c97: Pull complete
c5b21110f7b8: Pull complete
Digest: sha256:a2483cf8906b2d14b7ff6fded15601ee3f00172cbfc21ab1e7d80c45a4ee0cfb

Run the images command again:


$ docker images
REPOSITORY TAG IMAGE ID CREATED ...
heroku/jvm latest 35ecdbd5516b 6 days ago

You now have a local representation of the Heroku stack. This stack includes
a JVM, so it’s perfect for running an executable WAR file. You can inspect
the JVM version by running the following command:
$ docker run -t heroku/jvm java -version
openjdk version "1.8.0_51-cedar14"
OpenJDK Runtime Environment (build 1.8.0_51-cedar14-b16)
OpenJDK 64-Bit Server VM (build 25.51-b03, mixed mode)

Notice that the version of the Java runtime is different from your local Java
installation. The docker run command runs another command inside the context
of a Docker container. The -t option defines the image to load, which in this
case is the heroku/jvm image you downloaded a moment ago. The last part, java
-version, is the command that Docker will run. When Docker ran the java com-
mand, it didn’t use the Java runtime on your host system. It used the Java
runtime contained in the heroku/jvm image.

To use this Java runtime with a Warbler WAR file, you must add the WAR
artifact to the container. For this, you’ll create your own Docker image.

Creating a Docker Image


A Docker image is defined by a Dockerfile, which is a text document containing
instructions Docker follows as it provisions a new container. To create a
Docker image for your WAR file, you must create a Dockerfile in the project.

6. https://heroku.com

report erratum • discuss


Creating a Docker Image • 23

To begin, move into the root directory of the stock-service application you
implemented in Chapter 1, Getting Started with JRuby, on page 1.
$ cd ~/code/stock-service

Then create a Dockerfile in that directory and put the following code in it:
Warbler/stock-service-docker/Dockerfile

FROM heroku/jvm

ADD ./stock-service.war /app/user/

This defines an image that inherits from the heroku/jvm image. It then tells
Docker to add the WAR file from the local machine to the /app/user directory
in the image. This directory is what Heroku considers the root of any Docker-
based application.

Now build the image by running the build command:


$ docker build -t stock-service .
Sending build context to Docker daemon 24.86 MB
Step 0 : FROM heroku/jvm
---> 35ecdbd5516b
Step 1 : ADD ./stock-service.war /app/user/
---> Using cache
---> 103d45860c83
Successfully built 103d45860c83

This creates a new image named stock-service, which is ready to run your
application. Execute the images command again to see it in the list:
$ docker images
REPOSITORY TAG IMAGE ID CREATED
heroku/jvm latest 35ecdbd5516b 6 days ago
stock-service latest 103d45860c83 26 minutes ago

Now run the application in a Docker container:


$ docker run --publish 8080:8080 -t stock-service java -jar stock-service.war
2015-08-15 20:01:58.590:INFO::main: Logging initialized @186ms
2015-08-15 20:01:58.597:INFO:oejr.Runner:main: Runner
2015-08-15 20:01:58.709:INFO:oejs.Server:main: jetty-9.2.9.v20150224
2015-08-15 20:02:03.891:WARN:oeja.AnnotationConfiguration:main: ServletCont...
2015-08-15 20:02:04.204:INFO:/:main: INFO: jruby 9.0.5.0 (2.2.3) 2016-01-26...
2015-08-15 20:02:04.206:INFO:/:main: INFO: using a shared (threadsafe!) run...
2015-08-15 20:02:09.534:INFO:oejsh.ContextHandler:main: Started o.e.j.w.Web...
2015-08-15 20:02:09.543:WARN:oejsh.RequestLogHandler:main: !RequestLog
2015-08-15 20:02:09.557:INFO:oejs.ServerConnector:main: Started ServerConne...
2015-08-15 20:02:09.557:INFO:oejs.Server:main: Started @11155ms

report erratum • discuss


Chapter 2. Creating a Deployment Environment • 24

This command tells Docker to run a container with the java -jar stock-service.war
command, based on the stock-service image, and with port 8080 published to
the host system (so you can access it outside the container). To view the
application, you’ll need to know the hostname of the container. On Linux this
is localhost, but on Mac and Windows it’s the address of the Docker Machine.
Open another terminal and run this command to see it:
$ docker-machine ip default
192.168.99.100

Now you can use curl to make a request to the service just as you did when it
was running locally if you’re on Linux, or with the following command on Mac
and Windows:
$ curl -d "Hi Apple" http://$(docker-machine ip default):8080/stockify
Hi <div class='stock' data-symbol='AAPL' data-day-high='116.14'>Apple Inc.</div>

Your microservice is ready for production! Deploying your Docker image could
involve a docker push command, which uploads the image to a Docker host and
runs it. However, managing your own Docker infrastructure in production
defeats much of the purpose of Docker, which abstracts away the underlying
platform. For that reason, you’ll deploy the stock-service Docker image to a
mature and well-curated platform, Heroku.

But even without deploying to production, the work you’ve done to set up
Docker is still invaluable. It gives you the ability to run a production environ-
ment locally. And in the coming chapters you’ll enhance this environment to
include a database and other services. Having a complete production environ-
ment you can run with a single command is great for debugging, on-boarding
new employees, and scaling. Even better, because the Docker environment
you created is based on the Heroku stack, you can deploy the WAR to Heroku
with a great deal of confidence.

Deploying to the Cloud


Heroku is a cloud-based platform as a service that helps you deploy, run,
and manage applications written in many languages, including Ruby, Java,
and JRuby. You can deploy to Heroku by pushing source code to a Git
repository, by uploading precompiled binaries, or by pushing an app config-
ured for Docker. You’ll start by deploying the stand-alone WAR file you created
with Warbler directly to Heroku. This is the lightest and fastest way to get
your app running in the cloud. Then you’ll deploy the Docker image you cre-
ated a moment ago. Deploying a Docker image is a heavier and slower process
but offers advantages of its own.

report erratum • discuss


Deploying to the Cloud • 25

First, create a free Heroku account by visiting the Heroku website7 and filling
out a few bits of information. You won’t even need a credit card for now.

Once you’ve created a Heroku account, download and install the Heroku
toolbelt.8 This is a command-line interface (CLI) used to create, manage, and
deploy your Heroku apps. You can do most of these things from the web-
based dashboard,9 but you’ll need to use the CLI to deploy your app.

With the toolbelt installed, open a terminal and log in with the credentials
you created earlier:
$ heroku login
Enter your Heroku credentials.
Email: [email protected]
Password:

Authenticating is required to allow both the heroku and git commands to work
with the deployment examples in this book.

Note that if you’re behind a firewall that requires the use of a proxy to connect
with external HTTP/HTTPS services, you should set the HTTP_PROXY or
HTTPS_PROXY environment variable in your local development environment
before running the heroku command.

Once you’re logged in, install the heroku-deploy toolbelt plugin by running
this command:
$ heroku plugins:install https://github.com/heroku/heroku-deploy

This plugin helps you deploy WAR and JAR files from the Heroku CLI. But
first you’ll need an app to deploy to.

Make sure you’re still in the root directory of the stock-service app, and run
the following command to provision a new Heroku app and associate it with
your local app:
$ heroku create
Creating app... done, stack is cedar-14
https://obscure-fjord-4138.herokuapp.com/ | https://git.heroku.com/...

Heroku will randomly assign your app a unique name based on a clever mash-
up of terms. The example used here is obscure-fjord-4138, yours will be different.

Now you need to create one new file that tells Heroku how to run your app.
Create a Procfile in the root directory of the project and put this code in it:

7. http://signup.heroku.com
8. http://toolbelt.heroku.com
9. http://dashboard.heroku.com

report erratum • discuss


Chapter 2. Creating a Deployment Environment • 26

Warbler/stock-service-docker/Procfile

web: java -Xmx384m -Xss512k -jar stock-service.war

This tells Heroku that your application has a single process, called web, and
gives it the command to run for that process. The command uses two options,
Xmx and Xss, to optimize memory usage characteristics of the process for the
Heroku platform. You’ll learn what these mean and how to customize them
in Chapter 7, Tuning a JRuby Application, on page 109. Otherwise, it’s the same
command you ran locally.

Now deploy your app by running this command from the same directory as
the Procfile:
$ heroku deploy:jar --jar stock-service.war
Uploading stock-service.war....
-----> Packaging application...
...
-----> Done

The deploy process will take a minute to package your application and upload
the WAR file to Heroku. When it’s done, you can ensure the process is running
with this command:
$ heroku ps:scale web=1
Scaling dynos... done, now running web at 1:Free.

And you can open the app in a browser like this:


$ heroku open

You’ll see the landing page where you can test out the /stockify service. Notice
that the URL begins with the name of the app and is followed by herokuapp.com.
This is the standard convention for new Heroku apps, but you can always
configure DNS for custom domains.

Return to the terminal, and exercise the /stockify service with curl but replace
obscure-fjord-4138 with the name of your app:

$ curl -d "Hi Apple" http://obscure-fjord-4138.herokuapp.com/stockify


Hi <div class='stock' data-symbol='AAPL' data-day-high='116.14'>Apple Inc.</div>

Deploying only the executable WAR file to Heroku is the quickest way to get
your app running in the cloud. But you can also deploy the entire Docker
image you created earlier. You may prefer this approach if you’re using
Docker to set up some extra dependencies.

Like the toolbelt plugin for WAR files, there’s also a toolbelt plugin for Docker.
Install the heroku-container-tools toolbelt plugin by running this command:

report erratum • discuss


Wrapping Up • 27

$ heroku plugins:install heroku-container-tools

Heroku also needs an app.json file, which is a descriptor containing a little


metadata about your app. You can store many different things in this file,
such as environment variables, a website URL, and more. But only one element
is required for Docker:
Warbler/stock-service-docker/app.json

{
"name": "stock-service"
}

Now you’re ready to initialize the Heroku Docker config. Run this command:
$ heroku container:init --dockerfile Dockerfile

This reads the Dockerfile and Procfile and generates a docker-compose.yml, which
describes the complete environment.

Finally, deploy to the same Heroku app you created earlier by running this
command:
$ heroku container:release
Remote addons: (0)
Local addons: (0)
Missing addons: (0)
Creating local slug...
Building web...
...

The release process will take some time to package your application and
upload the image to Heroku. When it’s done, you can run the open command
again to view the app in a browser. Or you can use curl as before.

Your microservice is running in the cloud and can easily be scaled up to


handle growing demand. When that time comes, you can convert your free
Heroku account to a paid account and rapidly increase the number of
instances using the heroku ps:scale command. Or you can scale vertically
(increase RAM and CPU) with the heroku ps:resize command.

Wrapping Up
You’ve created an environment you can use to run your microservice or any
other JRuby application in production. You’ve also set up Docker, which
allows you to add new components to your infrastructure without running a
bunch of commands or managing a complicated configuration management
codebase. The tools you’ve used are state of the art for the industry, and it’s

report erratum • discuss


Chapter 2. Creating a Deployment Environment • 28

likely that you’ll use them to set up new environments each time you embark
with a new customer or employer.

When you need to scale this environment horizontally, you won’t have to do
much work. You’ll start with the base image and launch Docker containers
from it. Or you can simply scale up your Heroku app.

In the coming chapters, you’ll build on this base Docker image. You’ll add
more components and deploy more complicated web applications. In the next
chapter, you’ll convert a full-blown Rails application to JRuby.

report erratum • discuss


Exploring the Variety of Random
Documents with Different Content
—— des Morts, 503.
—— sur l’Eloquence, 305 sq.
—— sur les Héros de Roman, 292.
Dialogus in Defensionem Poetices, 27, 28.
Dictionnaire Philosophique, 517.
Diderot, 518 sq.
Difesa di Dante, 105.
Digressions sur les Anciens et les Modernes, 506.
Dionysius Areopagita, 22.
Discorsi, Cinthio’s, 581 sq.
—— Summo’s, 108.
—— Tasso’s, 92 sq.
Discours de Réception, Buffon’s, 519 sq.
Discours des Trois Unités, 262 sq.
Discourse of English Poesy, 176 sq.
Discourse on Medals, 439.
—— on Music, Painting, and Poetry, 473 sq.
—— on Satire, 385.
—— on the Grounds of Criticism in Tragedy, 384.
Discoveries, Jonson’s, 198 sq.
Dissertation on Ossian, 464.
—— on Phalaris, 401, 402.
—— on the Rise of Poetry and Music, 474.
Dissertation sur le mot “Vaste,” 269 sq.
Donatus, Ælius, 6 note, 48 and note, 59, 345.
Donne, 199, 489.
Dorset, Earl of, 376 sq., 439.
Douglas, Gavin, 218.
Drant, Thomas (d. 1578?), 162 sq.
Drayton, 199, 498.
Drummond (of Hawthornden), 198 sq., 356 note, 399.
Dryden, John (1631-1700), 56, 93, 119, 121, 144, 232, 237 and
motto, 262, 264, 271, 300, 314 note, 322, 332, 344, 347, 369, 371-
391, 393, 403, 411, 413, 416, 417, 425 sq., 432, 438, 439, 449,
454, 472 note, 485, 489 sq., 503, 560.
Du Bartas, 313, 369.
Du Bellay, Joachim (1524-60), 111-116, 221, 233, 369.
Du Bos, Jean Baptiste, Abbé (1670-1742), 511-513, 542 note.
Dunton, John (1659-1733), 406.
Du Pont, Gratien (fl. c. 1540), 110.
Dyer, Sir Edward, 165.
—— John, 421, 478.

Edgeworth, Miss, 97, 348.


Edwards, Thomas (1699-1757), 497 note.
Ejemplar Poético, 338, 341.
E. K., 224.
Eléments de Littérature, 526 sq.
Elements of Criticism, the, 465-470.
Éloges, D’Alembert’s, 519.
—— Fontenelle’s, 506.
—— Other, 529, 533.
Elton, Professor, 552.
Encina, Juan del (1468-1534), 335.
English Parnassus, the, 426 note.
Entretiens d’Ariste, 308.
Ephemerides of Phialo, 169 note.
Epistle to Augustus, Pope’s, 453 sq.
Epistles, Ovid’s, Dryden’s Preface to, 384.
Epistolæ Obscurorum Virorum, 14 note.
Epitome de la Eloquencia Española, 547, 548.
Erasmus, Desiderius (1467-1536), 9-16, 61, 65, 75, 85, 193, 276,
352 note.
Ercolano, L’, 49.
Eschenbach, Wolfram von, 230.
Espinel, Vicente (1544-1634), 337.
Essai sur la Poésie Epique, 516.
—— sur le Beau, 513 note.
—— sur le Goût, 514, 528.
—— sur les Éloges, 529.
—— sur les Romans, 527.
Essay of Dramatic Poesy, 332, 376-382.
—— of Heroic Plays, 383.
—— on a New Species of Writing, 497 note.
—— on Criticism, 453 sq.
—— on Modern Education, 452.
Essay on Poetry (Temple’s), 401.
—— on the Genius of Shakespeare, 434.
—— on Translated Verse, 404.
—— upon Poetry and Painting, 497 note.
Essays, Collier’s, 404.
—— Critical (Scott’s), 500.
—— Montaigne’s, 138 sq.
—— Moral and Literary, 499.
Estimate of the Manners and Principles of the Times, 476.
Estratto dell’ Arte Poetica d’Aristotile, 546.
Etherege, 463.
Euphuism, 225 sq.
Euripides, 14, 54.
Evening’s Love, An, Preface to, 383.
Examens, Corneille’s, 262 sq.
Expostulatio Spongiæ, 346.

Fables, Dryden’s, Preface to, 386.


Fabri, Pierre (fl. c. 1520), 110.
Fabriano, see Gilio.
Fabricius, Georgius (1515-71), 108, 181, 353-355.
Faerie, Queene, the, 168.
“Fatura,” 63.
Fauchet, Claude (1530-1601), 101, 135.
Feillet, M., 258.
Feltre, Vittorino da, 20.
Fénelon, Francois de Salignac de La Mothe (1651-1715), 241, 272,
301, 304-308.
Feyjóo y Montenegro, Benito Geronimo (1701-64), 549.
“Fidenziano,” 540 note.
Fielding, 349.
Filosofia Antigua Poética, 338-340.
Fingal, 464.
Flaubert, G., 12, 302.
Flecknoe, 377.
Flemming, 556.
Fletcher, 378 sq.
Floriant et Florete, 394 note.
Folengo, 540.
Fontaine, Ch. (1513-88?), 116.
Fontenelle, Bernard le Bovier de (1657-1757), 292, 416, 419, 423
motto, 501-507.
Fracastoro, Jeronimo (1483-1553), 44-46, 67, 88, 90, 214, 217, 219.
Franciade, Preface to the, 120 sq.
Fraunce, Abraham (fl. c. 1590), 186 note, 199.
Fray Gerundio, 550.
Froissart, 141.
Froude, Mr, 5.
Fulgentius, 8, 397.
Fureteriana, 274 note.
Furetière, Antoine (1620-88), 553, 554 note.
“Furor Poeticus,” 97 and note, 267, 268, 295, 340, 410, 420.

“Gallo-Classic,” the term, 411.


Gambara, F. (fl. c. 1580), 107 note, 278 note.
Garbett, Rev. J., 298 note, 372 note.
Garnett, Dr, 546 note.
Gascoigne, George (1525?-77), 162 sq., 177, 226, 429.
Gautier, Th., 282 note, 519 note.
Gayley and Scott, Professors, 195 note, 329 note.
Gellert, Christian Furchtegott (1715-69), 557.
Gentleman’s Magazine, the, 497.
Gerusalemme Liberata, 18, 87 sq.
Gibert, Balthasar (1662-1741), 319, 320.
Gifford, 198 note, 534.
Gildon, Charles (1665-1724), 429, 430.
Gilio da Fabriano Antonio (fl. c. 1580), 104.
Girac, Paul Thomas de (?-1663), 278 note.
Giraldi, Cinthio, see Cinthio.
Giraldus, Lilius, see Lilius.
Goethe, 356, 372, 560.
Goldsmith, Oliver (1728-74), 429, 498.
Gondibert, Preface to, 365, 367-371.
Góngora y Argote, Luis de (1561-1627), 349.
Gongorism, 331, 414.
Gonzales de Salas (fl. c. 1630), 341, 342, 349.
Gorboduc, 173, 206, 374, 503.
Gorgias, the, 82.
Gosson, Stephen (1555-1624), 169-171.
Gottsched, Johann Christopher (1700-66), 552-557.
Gournay, Mlle. de, 251, 253, 254.
Gower, 146 sq., 179 sq.
Gracián, Balthasar (1584-1658?), 349, 350.
Granada, Luis de (1504-81), 336.
Gravina, Gianvincenzo (1664-1718), 272, 324, 513, 538-541.
Gray, 461, 478, 479, 487, 491 sq., 500, 569.
Grazzini, Ant. Francesco ["Il Lasca"] (1403-83), 48, 59.
Grévin, Jacques (1538?-70), 127.
Grimmelshausen, 552.
Grongar Hill, 488, 500.
Grosart, Dr, 196 note.
Grotius, 359.
Grundlicher Bericht des Deutschen Meistergesangs, 360 note.
Guarini, Battista (1537-1612), poet, 107, 199.
Guarino (?-1460), humanist, 18.
Guest, Dr, 178, 188.
Guicciardini, 331.

Habington, 485.
Hamelius, Herr, 425 note, 432 note, 448 note.
Hamilton, Anthony, 502.
Hannay, Mr David, 332 note, 341, 350.
Hardy, Alexandre (1560-1631), 255 note.
Harington, Sir John (1561-1612), 183 note, 186, 199.
Harris, James (1709-80), 473-476.
Harvey, Gabriel (1545-1630), 148, 165 sq.
Hawes, Stephen (?-1523?), 146, 147.
Hazlitt, 145, 219, 372 note, 496.
Heads of an Answer to Rymer, 373 note, 397 note.
Hédelin, see Aubignac.
Hegel, 274, 527 note.
Heinsius, Daniel (1580-1655), 356, 357.
Heldenbuch, 569.
Heliodorus, 77, 131.
Henriade, the, 514 note, 522, 526.
Henry IV., Dennis on, 434.
Herbert, G., 87.
Héricault, M. Ch. d’, 112 note.
Hermaphroditus, 66 note.
Hermes, 473.
Hermogenes, 319, 329.
Hero and Leander, 74.
“Heroic Play,” the, 367 sq.
“Heroic Poem,” the, 367 sq.
Hessus, Eobanus, 14, 28.
Heywood, Thomas, 398 note.
Histoire du Théâtre Français, Fontenelle’s, 505.
—— the Frères Parfait’s, 527.
Historia de las Ideas Estéticas en España, 331-351 passim.
History of the Rise and Progress of Poetry, 476.
—— of the Royal Society, 398.
Hobbes, Thomas (1588-1679), 40, 367-371.
Hoffmanswaldau, 552.
Home, Henry, see Kames.
Homer, 25, 31-35, 47, 52, 74, 86, 99, 122-126, 130-132, 141, 310
sq.
Horace, 6, 9, 129 sq. and passim.
Howard, Edward, 367 note.
—— Henry, see Surrey, Earl of.
—— J., 367 note.
—— Sir Robert (d. 1698: his birth-date and those of his brothers E.
and J. are very uncertain), 376 sq.
Howell’s Letters, 371 note.
Hudibras, 513 note.
Huerta, Vicente Garcia de la (1730?-87), 550 note.
Huet, Pierre Daniel (1630-1721), bishop of Avranches, 274, 275.
Huetiana, 275.
Hugo, Victor, 87.
Hume, Alexander, 209 note.
—— David, 462.
Hunt, Leigh, 372 note.
Hurd, 469.
Hutten, Ulrich von (1488-1523), 352 note.

Iago, Rymer on, 395, 396.


Ibrahim, 265.
Idler, the, 484.
I Fiori della Poesia, 107.
Il Castellano, 40.
“Il Lasca,” see Grazzini.
Il Sogno, 106, 107.
“Imagination,” Addison on, 443-448.
“Imlac,” 484, 485.
Impartial Critic, The, 432.
Indian Emperor, The, Preface to, 382.
Inés de Castro, 507.
Inquiry into the Present State of Polite Learning in Europe, 498.
Institutiones Oratoriæ, Voss’s, 358-360.
—— Poeticæ, Spanmüller’s, 355.
I Romanzi, 63.
Isidore (of Seville), 8, 334.
I Simillimi, 38.
Iskra, Augustinus, 360, 361.
Isla, José Francisco, Father (1703-81), 550.
Istoria del Volgar Poesia, 542.
Italia Liberata, 38.

James the First (1566-1625), 177, 178.


Jerome, St, Erasmus on, 15, 16.
Jeronimo, 235.
Johannes Secundus, 27.
John of Garlandia, 14.
—— of Salisbury, 8.
Johnson, Samuel (1709-84), 145, 375, 429, 434, 437, 458, 465, 474,
477-496, 512, 552, 561, 571.
Jonson, Ben (1573-1637), 42, 71, 138, 144, 156, 185 note, 197-209,
227 sq., 233, 262, 271, 367, 368, 370 sq., 393 sq., 486 note.
Journal des Savants, 316.
Jugements des Savants, 276.
—— —— —— sur les auteurs que ont traité de la Rhétorique, 319,
320.
Julius Cæsar, Rymer on, 396.
—— Dennis on, 434.
Juvenal, Dryden’s Preface to, 385.

Kames, Henry Home, Lord (1696-1782), 465-470.


Käsenbrot, see Olmucensis.
Keats, 280, 412, 485.
Keble, 87, 312 note, 372 note.
Kelly, Mr J. Fitzmaurice, 332 note, 335 note, 348 note, 350.
Kelton, Arthur (fl. c. 1550), 542 note.
Ker, Mr W. P., 93 note, 332 note, 373 sq.
Kingsley, Ch., 124, 161.
Knox, Vicesimus (1752-1821), 499.

La Boétie, E. de, 71.


La Bruyère, Jean de (1645-96), 241, 300-304, 355, 521.
Labyrinthus, 8, 24, 64, 231.
La Casa, 93, 162 note, 512, 540 note.
La Croze, J. Cornand de (not to be confused with his contemporary,
M. Veyssière de la Croze, a learned but fantastic philologist and
antiquary), 406 note.
La Cueva, Juan de (1550-1606), 338, 340, 341, 355.
La Fontaine, 293 sq., 298, 519, 521.
La Harpe, Jean François de (1739-1803), 530-533, 564, 571.
Lamb, Charles, 145, 496.
La Mesnardière, Hippolyte Jules Pelet de (1616-63), 265.
La Monnoye, Bernard de (1641-1728), 273 note, 316 note, 527 note.
La Mothe le Vayer, F. de (1588-1672), 251.
La Motte, A. Houdard de (1672-1731), 321, 507-509.
—— Charles (?-?), Irish divine and critic, 497 note.
Lancelot, 124, 260.
Landi, Ortensio (1501-60), 29.
Langbaine, Gerard (1656-92), 400, 401, 430.
Langlois, M. G., 109 note.
Langhorne, 449.
Langland, 179 sq.
La Place, translator of Shakespeare, 527, 528.
Lasca, Il, see Grazzini.
La Taille, Jacques de (1541?-62?), 127.
—— Jean de (1540?-1608), 127.
Latimer, 150.
Laudun, Pierre de (1575-1629), 127, 128.
Le Bossu, René (1631-80), 300, 314, 315.
Le Clerc, Jean (1657-1736), 276, 277, 363, 364.
Lectures on Rhetoric and Belles Lettres, 462 sq.
Lee, Mr Sidney, 400 note.
Lemaître, M. Jules, 259 note.
Lemercier, N., 530.
Le Moyne, Père, 257, 393, 505.
Lessing, 219, 356, 410.
L’Estrange, 392, 451.
Le Tre Sorelle, 93.
Letter to a Young Clergyman, 452.
Letters on Chivalry, 469.
Letters, Pope’s, 453.
Lettre de M. de la Visclède, 517.
Lettres aux Auteurs de la Gazette Littéraire, 517.
Lettres Galantes et Philosophiques, 510.
Lettres Persanes, 514.
Lettres sur les Anglais, 516.
Lilius Gregorius Giraldus (1478-1552), 63-68, 96 note, 413.
Lilly, William, 65.
L’Infarinato, 92.
“L’Infortuné,” 110.
Lionardi, Alessandro (fl. c. 1550), 47.
Lives of the Poets, Heywood’s, 398 note.
—— Johnson’s, 480 sq., 486 sq.
—— Winstanley’s, 400.
Locke, John (1632-1704), 53, 446 sq., 468.
Lodge, Thomas (1558?-1625), 170, 171.
Logic and Poetry, 20 note.
Lohenstein, 552.
Longfellow, 87.
Longinus, 6, 34, 206, 220, 288 sq., 302, 319, 373, 430, 435.
Longolius (Christophe de Longueil), (1490-1522), 11, 67, 276.
Lope de Vega Carpio, Felix (1562-1635), 332, 343-347, 380 note.
Love’s Labour’s Lost, Collier on, 403.
Lucan, 199.
Lucian, 24 note, 330, 402.
Lucilius, 254 note.
Lucretius, 33, 40, 88, 139, 140, 202.
Lutrin, Le, 290.
Luzan Claramumt de Suelves y Gurrea, Ignacio de (1702-54), 347,
350, 414, 541, 546, 547.
Lycidas, 490, 500.
Lydgate, 146 sq., 179 sq.

Macaulay, 320, 391 sq., 401 sq., 492, 498.


Machiavelli, 54.
“Machines” and “Machinery,” 369 sq., 435.
Mackenzie, Sir George, 320.
Macpherson (Ossian), 464.
Macrobius, 22 note.
Maffei, Francisco Scipione, Marquis (1676-1755), 546.
Maggi, 41, 42.
Mairet, Jean (1604-86), 115.
Maistre, Joseph de, 327.
Malebranche, Nicolas (1638-1715), 279 and note, 514.
Malfilâtre, 519.
Malherbe, François de (1555-1628), 115, 241-251, 257, 283, 303.
Malory, Sir Thomas, 6, 155.
Mambrun, Pierre (1600-61), 266-268, 410.
Manière de Bien Penser dans les Ouvrages d’Esprit, 315, 316.
Manto, 24 sq.
Mantuan, 66.
Marinism and Marino, 331, 393, 414.
Marlowe, 205, 399.
Marmontel, Jean François (1723-99), 287 note, 525-529.
Marot, Clément (1497-1544), 110 note, 137, 281, 304.
Marryat, 34.
Martianus Capella, 42.
Martinus Scriblerus, 452.
Masson, Professor, 195 note.
Matamoros, Alfonso Guida, 336.
Maucroix, François de (1619-1708), 278.
Mayáns y Siscar, Gregorio (1699-1781), 333 note, 549.
Mazzone da Miglionico (fl. c. 1590), 107, 108.
Mazzoni (fl. c. 1550), 105.
Meditation on a Broomstick, 451.
Mémoire sur les Occupations de l’Académie Française, 305 sq.
Ménage, Gilles de (1613-92), 160, 273, 317, 321 note.
Ménagiana, 53 note, 273 sq., 321 note.
Menéndez y Pelayo, Señor, 331-352, passim.
Mercure Galant, 316.
Meres, Francis (1565-1647), 187.
Merry Wives of Windsor, Dennis on, 434.
Mesa, Cristóbal de (1540-1620), 338 note, 346 note.
Meslier, le Curé (1678-1733), 515 note.
Metastasio (Pietro A. D. B. Trapassi), (1698-1782), 545, 546.
Mickle, 449.
Millar, Mr J. H., 486 note.
Milton, John (1608-74), 7, 45, 54, 56, 93, 262, 365, 398, 399, 402,
411 note, 435 sq., 439, 443 sq., 449, 467, 480 sq., 516, 532, 555,
560.
“Minim, Dick,” 484.
Minturno, Ant. Sebastiano (fl. c. 1560), 50-57, 90, 129 and note, 215,
219.
Miscellanies, Dryden’s Preface to, 384 sq.
Mitford, W., 164 note.
Molière, 261, 273, 298, 303, 307, 322 note, 378 sq., 521.
Molinet, Jean (d. 1507), 110.
Mondragon, Hieronimo de, 337 note.
Montagu, Mrs, 240.
Montagu (Lord Halifax), 439.
Montaigne, Michel de (1533-92), 138-142, 205, 232, 254, 279, 514.
Monte-Melone (Chiodino da), 329, 330.
Montesquieu, Charles de Sécondat, baron de la Brède, et de (1689-
1755), 513, 514.
Monthly Review, the, 497.
Moratin, Nicolas Fernandez de (1737-80): to be distinguished from
his son and successor in classicism, Leandro Fernandez de M.,
(1760-1828), 550.
More, Sir T., 63.
Morel-Fatio, M., 50 note, 332 note, 343 note, 346 note.
Morley, Prof. H., 162 note.
Morte d’Arthur, the, 155.
Mulcaster, Richard (1530?-1611), 209 note.
Mulgrave, John Sheffield, Earl of, later Duke of Buckinghamshire
(1649-1721), 402.
“Mumpsimus,” 15.
Muratori, Ludovico Antonio (1672-1750), 80 note, 324, 541, 542.
Musæus, 74.
Mutius, Macarius, 326.
Muzio, G. (fl. c. 1550), 46.

Nasarre y Ferriz, 549.


Naturaleza, 342 sq.
Naugerius sive de Poetica, 45, 214, 217.
Navagero, Andrea (Naugerius) (1483-1529), 45, 66, 81.
Nebrija, Antonio de (Nebrissensis) (fl. c. 1530), 336.
New World Discovered in the Moon, the, 198 note.
Nichols, Mr, 14 note, 15.
Nicolai, Christoph-Frederich (1733-1811), 551 note.
Nisard, D., 114.
Notes of Instruction, 162 sq.
Nueva Idea de la Tragedia Antigua, 341, 342.
Nutricia, 24 sq.

Obscuri Viri, the, 9.


Observateur Littéraire, 527.
Odyssey, the, 58, 267, 532.
Oedipus, the, 263.
Of Studies (Bacon’s), 192.
Ogier, François (fl. c. 1630), 254-256, 259, 346, 347, 409.
Oldys, 457.
Olmucensis, Augustinus Moravus (Käsenbrot, c. 1500), 17 note, 27,
28, 218, 352 note.
Opera, Saint-Evremond on, 271.
Opitz, Martin (1597-1639), 17, 360-363, 556.
Orbecche, 58, 60.
Origenes de la Lengua Española, 333 note.
Origines de la Poésie Française, 101.
Orlando Furioso, 85, and see Ariosto.
Ossian, 464 sq., 532.
Othello, Rymer on, 395.
Ovid, 384.

Panigarola, Francesco (1548-94), 329.


Paradise Lost, 325, 443 sq.
Paradossi, 29.
Paragone della Poesia Tragica, 554.
Parallel of Poetry and Painting, 385.
Parallèle des Anciens et des Modernes, 321 note.
Parfai(c)t, François (1698-1733) and Claude (1701-77), 527.
Paris, M. Gaston, 110 note.
Parnassus, The English, 426 note.
Parrhasiana, 276, 277.
Partenio, B. (fl. c. 1560), 102, 103.
Pascal, Blaise (1623-62), 279 note.
Pasquier, Etienne (1529-1615), 135-138, 224 note, 232.
Pastor Fido, the, 107, 108.
Patin, Gui (1602-72), 272, 273, 316 note.
Patrizzi, Francesco (1529-97) [not to be confused with the Siennese
Bp. of Gaeta, in the generation before, who wrote on politics, &c.],
anti-Peripatetic philosopher and critic (half-title of Bk. IV.), 57, 61,
63, 90, 93, 94-102, 107, 215, 219, 230, 233, 320 note, 329, 413.
Patru, Olivier (1604-81), 277, 291.
Pazzi, Alessandro de (fl. c. 1530), 41.
Peacham, Henry (1576?-1643?), 187.
Pecock, Reginald (1395-1460), 151.
Pellegrino, C., 100.
Pel(l)etier, Jacques (1517-82), Pléiade poet and critic, 117-119.
Pel(l)etier, Jacques (fl. c. 1660), 17th cent. poet, 291.
Pellissier, M. Georges, 110 note, 129 sq.
Pellisson, Paul (1624-93), 273.
Peña, Don P. M., 339 sq.
Pensieri Diversi, Tassoni’s, 326 sq.
Pepys, 377 note, 522.
Perceforest, 160.
Percy, 479.
Peri Bathous, 452.
Perrault, Charles (1628-1703), 285, 293, 321, 418, 419.
—— Claude (1613-88), 285.
—— Pierre (1608-80), 285.
“Person of Quality,” the (who rewrote Spenser), 416 note, 561.
Petit de Julleville, M., 110 note.
Petrarch, 44 and note, 82, 199.
Petronius, 27, 201 note, 254 note, 284.
Phalaris, the Pseudo-, 24 note, 401, 402.
Phillips, Edward (1630-96), 398, 399.
Philological Enquiries, 473 sq.
Philosophia Rationalis, 330.
Philosophical Arrangements, 473.
Philosophy of Rhetoric, 470-473.
Piccolomini, Æneas Sylvius, see that name.
—— Alessandro (1508-78), 103, 104.
Pico della Mirandola (1463-94), 22, 23.
Pigna, Giovanbattista (fl. c. 1550), 58 sq., 62, 63, 81, 84, 155, 214.
Pinciano, Alfonso López, called El. P. (150-?-160-?), 338-340.
Pitt, Christopher (1699-1748), 29 sq.
Plato, 6, 9, 38, 71, 82, 154, 213, 220, 514.
Pléiade, the, 110 sq. and Bk. IV., ch. iv., passim.
Plotinus, 9.
Plutarch, 22, 71, 99, 154.
Poemata Selecta Italorum, 29 note, 45 note.
Poetaster, the, 198.
Poetics (Poetica, Poética, Poétique), of Aristotle, 6 and passim.
—— of Daniello, 42-44.
—— of Denores, 105, 106.
—— of Luzán, 548.
—— of Scaliger, 69-80.
—— of Sibilet, 111, 112.
—— of Trissino, 38-41.
—— of Vida, 29-37.
—— of Viperano, 103.
Poetry and Logic, 20 note.
Poggio Bracciolino (1380-1459), 6 note.
Politian (Angelo Ambrogini, surnamed Poliziano) (1557-94), 15, 23-
26, 66, 402, 455.
Polyeucte, 379.
Pomfret, John, 488, 495.

You might also like