100% found this document useful (2 votes)
12 views

Spring REST: Building Java Microservices and Cloud Applications Balaji Varanasi download

The document provides an overview of the book 'Spring REST: Building Java Microservices and Cloud Applications' by Balaji Varanasi and Maxim Bartkov, detailing its content and structure. It includes chapters on REST principles, Spring Web MVC, error handling, and security among others, aimed at helping readers build Java microservices and cloud applications. Additionally, it offers links to other related eBooks and resources for further learning.

Uploaded by

kawkareany3k
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 (2 votes)
12 views

Spring REST: Building Java Microservices and Cloud Applications Balaji Varanasi download

The document provides an overview of the book 'Spring REST: Building Java Microservices and Cloud Applications' by Balaji Varanasi and Maxim Bartkov, detailing its content and structure. It includes chapters on REST principles, Spring Web MVC, error handling, and security among others, aimed at helping readers build Java microservices and cloud applications. Additionally, it offers links to other related eBooks and resources for further learning.

Uploaded by

kawkareany3k
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/ 78

Spring REST: Building Java Microservices and

Cloud Applications Balaji Varanasi install


download

https://ebookmeta.com/product/spring-rest-building-java-
microservices-and-cloud-applications-balaji-varanasi/

Download more ebook from https://ebookmeta.com


We believe these products will be a great fit for you. Click
the link to download now, or visit ebookmeta.com
to discover even more!

Practical Spring LDAP: Using Enterprise Java-Based LDAP


in Spring Data and Spring Framework 6 2nd Edition
Balaji Varanasi

https://ebookmeta.com/product/practical-spring-ldap-using-
enterprise-java-based-ldap-in-spring-data-and-spring-
framework-6-2nd-edition-balaji-varanasi/

Beginning Spring Boot 3: Build Dynamic Cloud-Native


Java Applications and Microservices - Second Edition K.
Siva Prasad Reddy

https://ebookmeta.com/product/beginning-spring-boot-3-build-
dynamic-cloud-native-java-applications-and-microservices-second-
edition-k-siva-prasad-reddy/

Building Modern Business Applications: Reactive Cloud


Architecture for Java, Spring, and PostgreSQL 1st
Edition Peter Royal

https://ebookmeta.com/product/building-modern-business-
applications-reactive-cloud-architecture-for-java-spring-and-
postgresql-1st-edition-peter-royal-2/

Learning pandas Python Data Discovery and Analysis Made


Easy Heydt Michael

https://ebookmeta.com/product/learning-pandas-python-data-
discovery-and-analysis-made-easy-heydt-michael/
A Cold Night With Hot Santa The Story of Mrs Claus 1st
Edition Sloane Peterson

https://ebookmeta.com/product/a-cold-night-with-hot-santa-the-
story-of-mrs-claus-1st-edition-sloane-peterson/

Adsensory Financialisation 1st Edition Pamela Odih

https://ebookmeta.com/product/adsensory-financialisation-1st-
edition-pamela-odih/

Undercover Reaper Eerie Valley Supernaturals 1 1st


Edition Rashelle Workman Workman Rashelle

https://ebookmeta.com/product/undercover-reaper-eerie-valley-
supernaturals-1-1st-edition-rashelle-workman-workman-rashelle/

The Complete Air Fryer Cookbook for Beginners Most


Affordable Quick Easy Ingredients 559 Air Fryer Recipes
1st Edition Dr Nettie Berry

https://ebookmeta.com/product/the-complete-air-fryer-cookbook-
for-beginners-most-affordable-quick-easy-ingredients-559-air-
fryer-recipes-1st-edition-dr-nettie-berry/

Beyond PTSD Helping and Healing Teens Exposed to Trauma


1st Edition Ruth Gerson Patrick Heppell Bruce D Perry

https://ebookmeta.com/product/beyond-ptsd-helping-and-healing-
teens-exposed-to-trauma-1st-edition-ruth-gerson-patrick-heppell-
bruce-d-perry/
Learning and Researching with Case Studies: A Student
Companion for Business and Management Research 1st
Edition Scott Andrews

https://ebookmeta.com/product/learning-and-researching-with-case-
studies-a-student-companion-for-business-and-management-
research-1st-edition-scott-andrews/
Spring REST
Building Java Microservices and
Cloud Applications

Second Edition

Balaji Varanasi
Maxim Bartkov
Spring REST
Building Java Microservices
and Cloud Applications
Second Edition

Balaji Varanasi
Maxim Bartkov
Spring REST: Building Java Microservices and Cloud Applications

Balaji Varanasi Maxim Bartkov


Salt Lake City, UT, USA Kharkov, Ukraine

ISBN-13 (pbk): 978-1-4842-7476-7 ISBN-13 (electronic): 978-1-4842-7477-4


https://doi.org/10.1007/978-1-4842-7477-4
Copyright © 2022 by Balaji Varanasi and Maxim Bartkov
This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of the
material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation,
broadcasting, reproduction on microfilms or in any other physical way, and transmission or information
storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now
known or hereafter developed.
Trademarked names, logos, and images may appear in this book. Rather than use a trademark symbol with
every occurrence of a trademarked name, logo, or image we use the names, logos, and images only in an
editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the
trademark.
The use in this publication of trade names, trademarks, service marks, and similar terms, even if they are not
identified as such, is not to be taken as an expression of opinion as to whether or not they are subject to
proprietary rights.
While the advice and information in this book are believed to be true and accurate at the date of publication,
neither the authors nor the editors nor the publisher can accept any legal responsibility for any errors or
omissions that may be made. The publisher makes no warranty, express or implied, with respect to the
material contained herein.
Managing Director, Apress Media LLC: Welmoed Spahr
Acquisitions Editor: Steve Anglin
Development Editor: James Markham
Coordinating Editor: Mark Powers
Cover designed by eStudioCalamar
Cover image by Joel Holland on Unsplash (www.unsplash.com)
Distributed to the book trade worldwide by Apress Media, LLC, 1 New York Plaza, New York, NY 10004,
U.S.A. Phone 1-800-SPRINGER, fax (201) 348-4505, e-mail orders-ny@springer-sbm.com, or visit
www.springeronline.com. Apress Media, LLC is a California LLC and the sole member (owner) is Springer
Science + Business Media Finance Inc (SSBM Finance Inc). SSBM Finance Inc is a Delaware corporation.
For information on translations, please e-mail booktranslations@springernature.com; for reprint,
paperback, or audio rights, please e-mail bookpermissions@springernature.com.
Apress titles may be purchased in bulk for academic, corporate, or promotional use. eBook versions and
licenses are also available for most titles. For more information, reference our Print and eBook Bulk Sales
web page at http://www.apress.com/bulk-sales.
Any source code or other supplementary material referenced by the author in this book is available to
readers on GitHub via the book’s product page, located at www.apress.com/9781484274767. For more
detailed information, please visit http://www.apress.com/source-­code.
Printed on acid-free paper
Table of Contents
About the Authors���������������������������������������������������������������������������������������������������� ix

About the Technical Reviewer��������������������������������������������������������������������������������� xi


Acknowledgments������������������������������������������������������������������������������������������������� xiii

Introduction�������������������������������������������������������������������������������������������������������������xv

Chapter 1: Introduction to REST������������������������������������������������������������������������������� 1


What Is REST?������������������������������������������������������������������������������������������������������������������������������� 1
Understanding Resources������������������������������������������������������������������������������������������������������������� 3
Identifying Resources�������������������������������������������������������������������������������������������������������������� 3
URI Templates�������������������������������������������������������������������������������������������������������������������������� 4
Representation������������������������������������������������������������������������������������������������������������������������������ 5
HTTP Methods������������������������������������������������������������������������������������������������������������������������������� 6
Safety�������������������������������������������������������������������������������������������������������������������������������������� 6
Idempotency���������������������������������������������������������������������������������������������������������������������������� 7
GET������������������������������������������������������������������������������������������������������������������������������������������ 7
HEAD���������������������������������������������������������������������������������������������������������������������������������������� 9
DELETE������������������������������������������������������������������������������������������������������������������������������������ 9
PUT���������������������������������������������������������������������������������������������������������������������������������������� 10
POST�������������������������������������������������������������������������������������������������������������������������������������� 12
PATCH������������������������������������������������������������������������������������������������������������������������������������ 13
HTTP Status Codes���������������������������������������������������������������������������������������������������������������������� 14
Richardson’s Maturity Model������������������������������������������������������������������������������������������������������ 16
Level Zero������������������������������������������������������������������������������������������������������������������������������ 17
Level One������������������������������������������������������������������������������������������������������������������������������� 17
Level Two������������������������������������������������������������������������������������������������������������������������������� 18
Level Three���������������������������������������������������������������������������������������������������������������������������� 18

iii
Table of Contents

Building a RESTful API����������������������������������������������������������������������������������������������������������������� 18


Summary������������������������������������������������������������������������������������������������������������������������������������ 19

Chapter 2: Spring Web MVC Primer������������������������������������������������������������������������ 21


Spring Overview�������������������������������������������������������������������������������������������������������������������������� 21
Dependency Injection������������������������������������������������������������������������������������������������������������ 23
Aspect-Oriented Programming���������������������������������������������������������������������������������������������� 23
Spring Web MVC Overview���������������������������������������������������������������������������������������������������������� 24
Model View Controller Pattern����������������������������������������������������������������������������������������������� 24
Spring Web MVC Architecture������������������������������������������������������������������������������������������������ 25
Spring Web MVC Components����������������������������������������������������������������������������������������������� 27
Summary������������������������������������������������������������������������������������������������������������������������������������ 44

Chapter 3: RESTful Spring�������������������������������������������������������������������������������������� 45


Generating a Spring Boot Project������������������������������������������������������������������������������������������������ 46
Installing a Build Tool������������������������������������������������������������������������������������������������������������� 46
Generating a Project Using start.spring.io����������������������������������������������������������������������������� 48
Generating a Project Using STS��������������������������������������������������������������������������������������������� 56
Generating a Project Using the CLI���������������������������������������������������������������������������������������� 62
Accessing REST Applications������������������������������������������������������������������������������������������������������ 63
Postman�������������������������������������������������������������������������������������������������������������������������������� 64
RESTClient����������������������������������������������������������������������������������������������������������������������������� 65
Summary������������������������������������������������������������������������������������������������������������������������������������ 66

Chapter 4: Beginning QuickPoll Application����������������������������������������������������������� 67


Introducing QuickPoll������������������������������������������������������������������������������������������������������������������ 67
Designing QuickPoll�������������������������������������������������������������������������������������������������������������������� 69
Resource Identification���������������������������������������������������������������������������������������������������������� 69
Resource Representation������������������������������������������������������������������������������������������������������ 71
Endpoint Identification����������������������������������������������������������������������������������������������������������� 74
Action Identification��������������������������������������������������������������������������������������������������������������� 75
QuickPoll Architecture����������������������������������������������������������������������������������������������������������������� 78

iv
Table of Contents

Implementing QuickPoll�������������������������������������������������������������������������������������������������������������� 79
Domain Implementation�������������������������������������������������������������������������������������������������������� 82
Repository Implementation��������������������������������������������������������������������������������������������������� 85
Embedded Database������������������������������������������������������������������������������������������������������������� 88
API Implementation��������������������������������������������������������������������������������������������������������������� 88
Summary���������������������������������������������������������������������������������������������������������������������������������� 101

Chapter 5: Error Handling������������������������������������������������������������������������������������� 103


QuickPoll Error Handling����������������������������������������������������������������������������������������������������������� 103
Error Responses������������������������������������������������������������������������������������������������������������������������ 107
Input Field Validation����������������������������������������������������������������������������������������������������������������� 112
Externalizing Error Messages��������������������������������������������������������������������������������������������������� 121
Improving RestExceptionHandler���������������������������������������������������������������������������������������������� 124
Summary���������������������������������������������������������������������������������������������������������������������������������� 127

Chapter 6: Documenting REST Services��������������������������������������������������������������� 129


Swagger������������������������������������������������������������������������������������������������������������������������������������ 130
Integrating Swagger����������������������������������������������������������������������������������������������������������������� 133
Swagger UI�������������������������������������������������������������������������������������������������������������������������������� 135
Customizing Swagger��������������������������������������������������������������������������������������������������������������� 136
Configuring Controllers������������������������������������������������������������������������������������������������������������� 140
Summary���������������������������������������������������������������������������������������������������������������������������������� 145

Chapter 7: Versioning, Paging, and Sorting���������������������������������������������������������� 147


Versioning��������������������������������������������������������������������������������������������������������������������������������� 147
Versioning Approaches�������������������������������������������������������������������������������������������������������� 148
Deprecating an API�������������������������������������������������������������������������������������������������������������� 150
QuickPoll Versioning������������������������������������������������������������������������������������������������������������ 151
SwaggerConfig�������������������������������������������������������������������������������������������������������������������� 154
Pagination��������������������������������������������������������������������������������������������������������������������������������� 157
Page Number Pagination����������������������������������������������������������������������������������������������������� 157
Limit Offset Pagination�������������������������������������������������������������������������������������������������������� 158
Cursor-Based Pagination����������������������������������������������������������������������������������������������������� 158

v
Table of Contents

Time-Based Pagination������������������������������������������������������������������������������������������������������� 159


Pagination Data������������������������������������������������������������������������������������������������������������������� 159
QuickPoll Pagination������������������������������������������������������������������������������������������������������������ 160
Changing Default Page Size������������������������������������������������������������������������������������������������ 163
Sorting�������������������������������������������������������������������������������������������������������������������������������������� 165
Sort Ascending or Sort Descending������������������������������������������������������������������������������������� 165
QuickPoll Sorting����������������������������������������������������������������������������������������������������������������� 166
Summary���������������������������������������������������������������������������������������������������������������������������������� 167

Chapter 8: Security����������������������������������������������������������������������������������������������� 169


Securing REST Services������������������������������������������������������������������������������������������������������������ 169
Session-Based Security������������������������������������������������������������������������������������������������������ 170
HTTP Basic Authentication�������������������������������������������������������������������������������������������������� 171
Digest Authentication���������������������������������������������������������������������������������������������������������� 172
Certificate-Based Security��������������������������������������������������������������������������������������������������� 174
XAuth����������������������������������������������������������������������������������������������������������������������������������� 174
OAuth 2.0����������������������������������������������������������������������������������������������������������������������������� 176
Spring Security Overview��������������������������������������������������������������������������������������������������������� 179
Securing QuickPoll�������������������������������������������������������������������������������������������������������������������� 183
cURL������������������������������������������������������������������������������������������������������������������������������������ 185
User Infrastructure Setup���������������������������������������������������������������������������������������������������� 185
UserDetailsService Implementation������������������������������������������������������������������������������������ 189
Customizing Spring Security����������������������������������������������������������������������������������������������� 191
Securing URI������������������������������������������������������������������������������������������������������������������������ 192
Summary���������������������������������������������������������������������������������������������������������������������������������� 197

Chapter 9: Clients and Testing������������������������������������������������������������������������������ 199


QuickPoll Java Client����������������������������������������������������������������������������������������������������������������� 199
RestTemplate���������������������������������������������������������������������������������������������������������������������������� 201
Getting Polls������������������������������������������������������������������������������������������������������������������������ 202
Creating a Poll��������������������������������������������������������������������������������������������������������������������� 205
PUT Method������������������������������������������������������������������������������������������������������������������������� 206

vi
Table of Contents

DELETE Method������������������������������������������������������������������������������������������������������������������� 206


Handling Pagination������������������������������������������������������������������������������������������������������������ 207
Handling Basic Authentication��������������������������������������������������������������������������������������������� 209
Testing REST Services�������������������������������������������������������������������������������������������������������������� 211
Spring Test��������������������������������������������������������������������������������������������������������������������������� 211
Unit Testing REST Controllers���������������������������������������������������������������������������������������������� 214
Integration Testing REST Controllers����������������������������������������������������������������������������������� 220
Summary���������������������������������������������������������������������������������������������������������������������������������� 222

Chapter 10: HATEOAS�������������������������������������������������������������������������������������������� 223


HATEOAS����������������������������������������������������������������������������������������������������������������������������������� 224
JSON Hypermedia Types����������������������������������������������������������������������������������������������������������� 227
JSON Hypermedia Types����������������������������������������������������������������������������������������������������� 227
HAL�������������������������������������������������������������������������������������������������������������������������������������� 228
HATEOAS in QuickPoll��������������������������������������������������������������������������������������������������������������� 230
Summary���������������������������������������������������������������������������������������������������������������������������������� 236

Index��������������������������������������������������������������������������������������������������������������������� 237

vii
About the Authors
Balaji Varanasi is a software development manager, author,
speaker, and technology entrepreneur. He has over 14 years
of experience designing and developing high-­performance,
scalable Java and .NET mobile applications. He has worked
in the areas of security, web accessibility, search, and
enterprise portals. He has a master’s degree in computer
science from Utah State University and serves as adjunct
faculty at the University of Phoenix, teaching programming
and information system courses. He has authored Apress’s
Practical Spring LDAP and has coauthored Introducing
Maven.

Maxim Bartkov is a staff engineer with more than seven


years of commercial experience in Java. Maxim specializes
in building architecture for high-load systems. He is skilled
in the development of distributed high-load systems,
microservice architecture, Spring Framework, and system
architecture. In his spare time, he writes articles for the Java
community.

ix
About the Technical Reviewer
Rohan Walia is a senior software consultant with extensive
experience in client-server, web-based, and enterprise
application development. He is an Oracle Certified ADF
Implementation Specialist and a Sun Certified Java
programmer. Rohan is responsible for designing and
developing end-to-end applications consisting of various
cutting-edge frameworks and utilities. His areas of expertise
are Oracle ADF, Oracle WebCenter, Fusion, Spring,
Hibernate, and Java/J2EE. When not working, Rohan loves
to play tennis, hike, and travel. Rohan would like to thank
his wife, Deepika Walia, for using all her experience and
expertise to review this book.

xi
Acknowledgments
This book would not have been possible without the support of several people, and we
would like to take this opportunity to sincerely thank them.
Thanks to the amazing folks at Apress; without you, this book would not have seen
the light of day. Thanks to Mark Powers for being patient and keeping us focused.
Thanks to Steve Anglin for his constant support and the rest of the Apress team involved
in this project.
Huge thanks to our technical reviewer Rohan Walia for his efforts and attention to
detail. His valuable feedback has led to many improvements in the book.
Finally, we would like to thank our friends and family for their constant support and
encouragement.

xiii
Introduction
Spring REST serves as a practical guide for designing and developing RESTful APIs
using the popular Spring Framework. This book begins with a brief introduction to
REST, HTTP, and web infrastructure. It then provides detailed coverage of several
Spring portfolio projects such as Spring Boot, Spring MVC, Spring Data JPA, and
Spring Security. The book walks through the process of designing and building a
REST application while taking a deeper look into design principles and best practices
for versioning, security, documentation, error handling, paging, and sorting. It also
discusses techniques for building clients that consume REST services. Finally, it covers
Spring MVC Test frameworks for creating unit and integration tests for REST API.
After reading the book, you will have learned

• About REST fundamentals and web infrastructure

• About Spring technologies such as Spring Boot and Spring Data JPA

• How to build REST applications with Spring technologies

• How to identify REST resources and design their representations

• Design principles for versioning REST services

• How to document REST services using Swagger


• Strategies for handling errors and communicating meaningful
messages

• Techniques for handling large datasets using pagination

• Securing REST services using “Basic Auth”

• How to build REST clients using RestTemplate

• How to test REST services using the Spring MVC Test framework

xv
Introduction

How Is This Book Structured?


Chapter 1 starts with an overview of REST. We cover REST fundamentals and
abstractions such as resources and representations. We then discuss web infrastructure
such as URIs, HTTP methods, and HTTP response codes. We also cover Richardson’s
Maturity Model, which provides a classification of REST services.
Chapter 2 provides detailed coverage of Spring Web MVC. We begin with a
gentle introduction to the Spring Framework and cover its two important concepts—
dependency injection and aspect-oriented programming. Then we take a deeper look at
the different components that make up Spring Web MVC.
Chapter 3 introduces Spring Boot, a Spring project that simplifies the bootstrapping
of Spring applications. We then use Spring Boot to build a Hello World REST application.
Finally, we look at some tools that can be used to access REST applications.
Chapter 4 discusses the beginnings of a RESTful application named QuickPoll. We
analyze the requirements and design resources and their representations. Using Spring
MVC components, we implement a set of RESTful services.
Chapter 5 covers error handling in REST services. Well-designed, meaningful
error responses play an important role in the adoption of REST services. We design
a custom error response for QuickPoll and implement the design. We also add
validation capabilities to the inputs provided by users. Finally, we look at techniques for
externalizing the error messages to property files.
Chapter 6 begins with an overview of the Swagger specification and its associated
tools/frameworks. We then implement Swagger in QuickPoll to generate interactive
documentation. We also customize Swagger and Swagger UI to meet our application
requirements.
Chapter 7 covers the different strategies for versioning a REST API. We then look at
implementing versioning in QuickPoll using the URI versioning approach. We also review
the different approaches for dealing with large datasets using pagination and sorting.
Chapter 8 begins with a discussion of different strategies for securing REST services.
We provide a detailed treatment of OAuth2 and review its different components. We then
use the Spring Security framework to implement Basic Authentication in the QuickPoll
application.
Chapter 9 covers building REST clients and testing REST APIs. We use Spring’s
RestTemplate features to build a REST client that works with different versions of the
QuickPoll API. We then take a deeper look into the Spring MVC Test framework and
examine its core classes. Finally, we write unit and integration tests to test the REST API.
xvi
Introduction

Chapter 10 discusses the HATEOAS constraint that allows developers to build


flexible and loosely coupled REST services. It also covers the HAL hypermedia format.
We then modify the QuickPoll application such that the Poll representations are
generated following HATEOAS principles.

T arget Audience
Spring REST is intended for enterprise and web developers using Java and Spring who
want to build REST applications. The book requires a basic knowledge of Java, Spring,
and the Web but no prior exposure to REST.

Downloading the Source Code


The source code for the examples in this book can be downloaded via the Download
Source Code button located at www.apress.com/9781484274767.
The downloaded source code contains a number of folders named ChapterX, in
which X represents the corresponding chapter number. Each ChapterX folder contains
two subfolders: a starter folder and a final folder. The starter folder houses a
QuickPoll project that you can use as a basis to follow along the solution described in
the corresponding chapter. Even though each chapter builds on the previous one, the
starter project allows you to skip around the book. For example, if you are interested
in learning about security, you can simply load the QuickPoll application under the
Chapter8\starter folder and follow the solution described in Chapter 8. As the name
suggests, the final folder contains the expected end state for that chapter.
Chapters 1 and 2 don’t have any associated code. Therefore, the corresponding
ChapterX folders for those chapters contain empty starter and final folders. In
Chapter 3, we build a Hello World application, so Chapter 3’s starter and final folders
contain the hello-rest application. Starting from Chapter 4, the starter and final
folders contain QuickPoll project source code.

C
 ontacting the Authors
We always welcome feedback from our readers. If you have any questions or suggestions
regarding the contents of this book, you can contact the authors at Balaji@inflinx.com
or Maxgalayoutop@gmail.com.

xvii
CHAPTER 1

Introduction to REST
In this chapter, we will learn the following:
• REST fundamentals

• REST resources and their representations

• HTTP methods and status codes

• Richardson’s Maturity Model

Today, the Web has become an integral part of our lives—from checking statuses
on Facebook to ordering products online to communicating via email. The success and
ubiquity of the Web have resulted in organizations applying the Web’s architectural
principles to building distributed applications. In this chapter, we will take a deep dive
into REST, an architectural style that formalizes these principles.

What Is REST?
REST stands for REpresentational State Transfer and is an architectural style for
designing distributed network applications. Roy Fielding coined the term REST in his
PhD dissertation1 and proposed the following six constraints or principles as its basis:
• Client-server—Concerns should be separated between clients
and servers. This enables client and server components to evolve
independently and in turn allows the system to scale.

• Stateless—The communication between client and server should


be stateless. The server need not remember the state of the client.
Instead, clients must include all of the necessary information in the
request so that the server can understand and process it.

1
https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm.

1
© Balaji Varanasi and Maxim Bartkov 2022
B. Varanasi and M. Bartkov, Spring REST, https://doi.org/10.1007/978-1-4842-7477-4_1
Chapter 1 Introduction to REST

• Layered system—Multiple hierarchical layers such as gateways,


firewalls, and proxies can exist between client and server. Layers can
be added, modified, reordered, or removed transparently to improve
scalability.

• Cache—Responses from the server must be declared as cacheable


or noncacheable. This would allow the client or its intermediary
components to cache responses and reuse them for later requests.
This reduces the load on the server and helps improve the
performance.

• Uniform Interface—All interactions between client, server, and


intermediary components are based on the uniformity of their
interfaces. This simplifies the overall architecture as components
can evolve independently as long as they implement the agreed-
on contract. The Uniform Interface constraint is further broken
down into four subconstraints: resource identification, resource
representations, self-descriptive messages, and Hypermedia as the
Engine of Application State, or HATEOAS. We will examine some of
these guiding principles in the later sections of this chapter.

• Code on demand—Clients can extend their functionality by


downloading and executing code on demand. Examples include
JavaScript scripts, Java applets, Silverlight, and so on. This is an
optional constraint.

Applications that adhere to these constraints are considered to be RESTful. As you


might have noticed, these constraints don’t dictate the actual technology to be used
for developing applications. Instead, adherence to these guidelines and best practices
would make an application scalable, visible, portable, reliable, and able to perform
better. In theory, it is possible for a RESTful application to be built using any networking
infrastructure or transport protocol. In practice, RESTful applications leverage features
and capabilities of the Web and use HTTP as the transport protocol.
The Uniform Interface constraint is a key feature that distinguishes REST
applications from other network-based applications. Uniform Interface in a REST
application is achieved through abstractions such as resources, representations,
URIs, and HTTP methods. In the next sections, we will look at these important REST
abstractions.

2
Chapter 1 Introduction to REST

U
 nderstanding Resources
The key abstraction of information in REST is a resource.
—Roy Fielding

Fundamental to REST is the concept of resource. A resource is anything that can be


accessed or manipulated. Examples of resources include “videos,” “blog entries,” “user
profiles,” “images,” and even tangible things such as persons or devices. Resources
are typically related to other resources. For example, in an ecommerce application, a
customer can place an order for any number of products. In this scenario, the product
resources are related to the corresponding order resource. It is also possible for a
resource to be grouped into collections. Using the same ecommerce example, “orders” is
a collection of individual “order” resources.

I dentifying Resources
Before we can interact and use a resource, we must be able to identify it. The Web
provides the Uniform Resource Identifier, or URI, for uniquely identifying resources. The
syntax of a URI is

scheme:scheme-specific-part

The scheme and the scheme-specific-part are separated using a semicolon.


Examples of a scheme include http or ftp or mailto and are used to define the
semantics and interpretation of the rest of the URI. Take the example of the URI—
http://www.apress.com/9781484208427. The http portion of the example is the
scheme; it indicates that an HTTP scheme should be used for interpreting the rest of
the URI. The HTTP scheme, defined as part of RFC 7230,2 indicates that the resource
identified by our example URI is located on a machine with host name apress.com.
Table 1-1 shows examples of URIs and the different resources they represent.

2
http://tools.ietf.org/html/rfc7230.

3
Chapter 1 Introduction to REST

Table 1-1. URI and Resource Description


URI Resource description

http://blog.example.com/posts Represents a collection of blog post resources.


http://blog.example.com/ Represents a blog post resource with identifier “1”; such
posts/1 resources are called singleton resources.
http://blog.example.com/ Represents a collection of comments associated with the
posts/1/comments blog entry identified by “1”; collections such as these that
reside under a resource are referred to as subcollections.
http://blog.example.com/ Represents the comment resource identified by “245.”
posts/1/comments/245

Even though a URI uniquely identifies a resource, it is possible for a resource to


have more than one URI. For example, Facebook can be accessed using URIs https://
www.facebook.com and https://www.fb.com. The term URI aliases is used to refer to
such URIs that identify the same resources. URI aliases provide flexibility and added
convenience such as having to type fewer characters to get to the resource.

U
 RI Templates
When working with REST and a REST API, there will be times where you need to
represent the structure of a URI rather than the URI itself. For example, in a blog
application, the URI http://blog.example.com/2014/posts would retrieve all the blog
posts created in the year 2014. Similarly, the URIs http://blog.example.com/2013/
posts, http://blog.example.com/2012/posts, and so forth would return blog
posts corresponding to the years 2013, 2012, and so on. In this scenario, it would be
convenient for a consuming client to know the URI structure http://blog.example.
com/year/posts that describes the range of URIs rather than individual URIs.
URI templates, defined in RFC 6570 (http://tools.ietf.org/html/rfc6570),
provide a standardized mechanism for describing URI structure. The standardized URI
template for this scenario could be
http://blog.example.com/{year}/posts

4
Chapter 1 Introduction to REST

The curly braces {} indicate that the year portion of the template is a variable, often
referred to as a path variable. Consuming clients can take this URI template as input,
substitute the year variable with the right value, and retrieve the corresponding year’s
blog posts. On the server side, URL templates allow the server code to parse and retrieve
the values of the variables or selected portions of URI easily.

Representation
RESTful resources are abstract entities. The data and metadata that make a RESTful
resource need to be serialized into a representation before it gets sent to a client. This
representation can be viewed as a snapshot of a resource’s state at a given point in time.
Consider a database table in an ecommerce application that stores information about
all the available products. When an online shopper uses their browser to buy a product
and requests its details, the application would provide the product details as a web page
in HTML. Now, when a developer writing a native mobile application requests product
details, the ecommerce application might return those details in XML or JSON format. In
both scenarios, the clients didn’t interact with the actual resource—the database record-
holding product details. Instead, they dealt with its representation.

Note REST components interact with a resource by transferring its


representations back and forth. They never directly interact with the resource.

As noted in this product example, the same resource can have several
representations. These representations can range from text-based HTML, XML, and
JSON formats to binary formats such as PDFs, JPEGs, and MP4s. It is possible for the
client to request a particular representation, and this process is termed as content
negotiation. Here are the two possible content negotiation strategies:

• Postfixing the URI with the desired representation—In this strategy,


a client requesting product details in JSON format would use the URI
http://www.example.com/products/143.json. A different client
might use the URI http://www.example.com/products/143.xml to
get product details in XML format.

5
Chapter 1 Introduction to REST

• Using the Accept header—Clients can populate the HTTP Accept


header with the desired representation and send it along with the
request. The application handling the resource would use the Accept
header value to serialize the requested representation. The RFC 26163
provides a detailed set of rules for specifying one or more formats
and their priorities.

Note JSON has become the de facto standard for REST services. All of the
examples in this book use JSON as the data format for requests and responses.

H
 TTP Methods
The “Uniform Interface” constraint restricts the interactions between client and server
through a handful of standardized operations or verbs. On the Web, the HTTP standard4
provides eight HTTP methods that allow clients to interact and manipulate resources.
Some of the commonly used methods are GET, POST, PUT, and DELETE. Before we
delve deep into HTTP methods, let’s review their two important characteristics—safety
and idempotency.

Note The HTTP specification uses the term method to denote HTTP actions such
as GET, PUT, and POST. However, the term HTTP verb is also used interchangeably.

S
 afety
A HTTP method is said to be safe if it doesn’t cause any changes to the server state.
Consider methods such as GET or HEAD, which are used to retrieve information/
resources from the server. These requests are typically implemented as read-only
operations without causing any changes to the server’s state and, hence, considered safe.

3
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1.
4
https://www.ietf.org/rfc/rfc2616.txt.

6
Chapter 1 Introduction to REST

Safe methods are used to retrieve resources. However, safety doesn’t mean that the
method must return the same value every time. For example, a GET request to retrieve
Google stock might result in a different value for each call. But as long as it didn’t alter
any state, it is still considered safe.
In real-world implementations, there may still be side effects with a safe operation.
Consider the implementation in which each request for stock prices gets logged in a
database. From a purist perspective, we are changing the state of the entire system.
However, from a practical standpoint, because these side effects were the sole
responsibility of the server implementation, the operation is still considered to be safe.

Idempotency
An operation is considered to be idempotent if it produces the same server state whether
we apply it once or any number of times. HTTP methods such as GET, HEAD (which are
also safe), PUT, and DELETE are considered to be idempotent, guaranteeing that clients
can repeat a request and expect the same effect as making the request once. The second
and subsequent requests leave the resource state in exactly the same state as the first
request did.
Consider the scenario in which you are deleting an order in an ecommerce
application. On successful completion of the request, the order no longer exists on the
server. Hence, any future requests to delete that order would still result in the same
server state. By contrast, consider the scenario in which you are creating an order using a
POST request. On successful completion of the request, a new order gets created. If you
were to re-“POST” the same request, the server simply honors the request and creates a
new order. Because a repeated POST request can result in unforeseen side effects, POST
is not considered to be idempotent.

GET
The GET method is used to retrieve a resource’s representation. For example, a GET on
the URI http://blog.example.com/posts/1 returns the representation of the blog post
identified by 1. By contrast, a GET on the URI http://blog.example.com/posts retrieves
a collection of blog posts. Because GET requests don’t modify server state, they are
considered to be safe and idempotent.

7
Chapter 1 Introduction to REST

A hypothetical GET request to http://blog.example.com/posts/1 and the


corresponding response are shown here.

GET      /posts/1 HTTP/1.1
Accept:  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.5
Connection: keep-alive
Host: blog.example.com

Content-Type: text/html; charset=UTF-8


Date: Sat, 10 Jan 2015 20:16:58 GMT
Server: Apache
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
      <head>
         <title>First Post</title>
      </head>
      <body>
           <h3>Hello World!!</h3>
      </body>
</html>

In addition to the representation, the response to GET requests includes metadata


associated with the resource. This metadata is represented as a sequence of key value
pairs called HTTP headers. Content-Type and Server are examples of the headers that
you see in this response. Because the GET method is safe, responses to GET requests can
be cached.
The simplicity of the GET method is often abused, and it is used to perform
operations such as deleting or updating a resource’s representation. Such usage violates
standard HTTP semantics and is highly discouraged.

8
Chapter 1 Introduction to REST

HEAD
On occasions, a client would like to check if a particular resource exists and doesn’t
really care about the actual representation. In another scenario, the client would like to
know if a newer version of the resource is available before it downloads it. In both cases,
a GET request could be “heavyweight” in terms of bandwidth and resources. Instead, a
HEAD method is more appropriate.
The HEAD method allows a client to only retrieve the metadata associated with a
resource. No resource representation gets sent to the client. This metadata represented
as HTTP headers will be identical to the information sent in response to a GET
request. The client uses this metadata to determine resource accessibility and recent
modifications. Here is a hypothetical HEAD request and the response.

HEAD     /posts/1 HTTP/1.1
Accept:  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.5
Connection: keep-alive
Host: blog.example.com

Connection:  Keep-Alive
Content-Type: text/html; charset=UTF-8
Date: Sat, 10 Jan 2015 20:16:58 GMT
Server: Apache

Like GET, the HEAD method is also safe and idempotent and responses can be
cached on the client.

DELETE
The DELETE method, as the name suggests, requests a resource to be deleted. On
receiving the request, a server deletes the resource. For resources that might take a long
time to delete, the server typically sends a confirmation that it has received the request
and will work on it. Depending on the service implementation, the resource may or may
not be physically deleted.

9
Chapter 1 Introduction to REST

On successful deletion, future GET requests on that resource would yield a


“Resource Not Found” error via HTTP status code 404. We will be covering status codes
in just a minute.
In this example, the client requests a post identified by 1 to be deleted. On
completion, the server could return a status code 200 (OK) or 204 (No Content),
indicating that the request was successfully processed.

Delete /posts/1  HTTP/1.1
Content-Length: 0
Content-Type: application/json
Host: blog.example.com

Similarly, in this example, all comments associated with post #2 get deleted.

Delete /posts/2/comments HTTP/1.1


Content-Length: 0
Content-Type: application/json
Host: blog.example.com

Because DELETE method modifies the state of the system, it is not considered to
be safe. However, the DELETE method is considered idempotent; subsequent DELETE
requests would still leave the resource and the system in the same state.

PUT
The PUT method allows a client to modify a resource state. A client modifies the state of
a resource and sends the updated representation to the server using a PUT method. On
receiving the request, the server replaces the resource’s state with the new state.
In this example, we are sending a PUT request to update a post identified by 1. The
request contains an updated blog post’s body along with all of the other fields that make
up the blog post. The server, on successful processing, would return a status code 200,
indicating that the request was processed successfully.

PUT /posts/1     HTTP/1.1

Accept: */*
Content-Type: application/json

10
Chapter 1 Introduction to REST

Content-Length: 65
Host: blog.example.com

BODY

{"title": "First Post","body": "Updated Hello World!!"}

Consider the case in which we just wanted to update the blog post title. The
HTTP semantics dictate that as part of the PUT request, we send the full resource
representation, which includes the updated title as well as other attributes such as blog
post body and so on that didn’t change. However, this approach would require that
the client has the complete resource representation, which might not be possible if the
resource is very big or has a lot of relationships. Additionally, this would require higher
bandwidth for data transfers. So, for practical reasons, it is acceptable to design your API
that tends to accept partial representations as part of a PUT request.

Note To support partial updates, a new method called PATCH has been added
as part of RFC 5789 (http://www.ietf.org/rfc/rfc5789.txt). We will be
looking at the PATCH method later in this chapter.

Clients can also use PUT method to create a new resource. However, it will only be
possible when the client knows the URI of the new resource. In a blogging application,
for example, a client can upload an image associated with a blog post. In that scenario,
the client decides the URL for the image as shown in this example:

PUT http://blog.example.com/posts/1/images/author.jpg

PUT is not a safe operation, as it changes the system state. However, it is considered
idempotent, as putting the same resource once or more than once would produce the
same result.

11
Chapter 1 Introduction to REST

POST
The POST method is used to create resources. Typically, it is used to create resources
under subcollections—resource collections that exist under a parent resource. For
example, the POST method can be used to create a new blog entry in a blogging
application. Here, “posts” is a subcollection of blog post resources that reside under a
blog parent resource.

POST /posts      HTTP/1.1

Accept: */*
Content-Type: application/json
Content-Length: 63
Host: blog.example.com

BODY

{"title": "Second Post","body": "Another Blog Post."}

Content-Type: application/json
Location: posts/12345
Server: Apache

Unlike PUT, a POST request doesn’t need to know the URI of the resource. The
server is responsible for assigning an ID to the resource and deciding the URI where
the resource is going to reside. In the previous example, the blogging application will
process the POST request and create a new resource under http://blog.example.com/
posts/12345, where “12345” is the server generated id. The Location header in the
response contains the URL of the newly created resource.
The POST method is very flexible and is often used when no other HTTP method
seems appropriate. Consider the scenario in which you would like to generate a
thumbnail for a JPEG or PNG image. Here we ask the server to perform an action on the
image binary data that we are submitting. HTTP methods such as GET and PUT don’t
really fit here, as we are dealing with an RPC-style operation. Such scenarios are handled
using the POST method.

12
Chapter 1 Introduction to REST

Note The term “controller resource” has been used to describe executable


resources that take inputs, perform some action, and return outputs. Although
these types of resources don’t fit the true REST resource definition, they are very
convenient to expose complex operations.

The POST method is not considered safe, as it changes system state. Also, multiple
POST invocations would result in multiple resources being generated, making it
nonidempotent.

P
 ATCH
As we discussed earlier, the HTTP specification requires the client to send the entire
resource representation as part of a PUT request. The PATCH method proposed as
part of RFC 5789 (http://tools.ietf.org/html/rfc5789) is used to perform partial
resource updates. It is neither safe nor idempotent. Here is an example that uses PATCH
method to update a blog post title.

PATCH /posts/1   HTTP/1.1

Accept: */*
Content-Type: application/json
Content-Length: 59
Host: blog.example.com

BODY

{"replace": "title","value": "New Awesome title"}

The request body contains a description of changes that need to be performed on


the resource. In the example, the request body uses the "replace" command to indicate
that the value of the "title" field needs to be replaced.
There is no standardized format for describing the changes to the server as part of a
PATCH request. A different implementation might use the following format to describe
the same change:

{"change" : "name", "from" : "Post Title", "to" : "New Awesome Title"}

13
Chapter 1 Introduction to REST

Currently, there is a work in progress (http://tools.ietf.org/html/draft-ietf-


appsawg-json-patch) for defining a PATCH format for JSON. This lack of standard has
resulted in implementations that describe change sets in a simpler format, as shown
here:

{"name" : "New Awesome Title"}

CRUD AND HTTP VERBS

Data-driven applications typically use the term CRUD to indicate four basic persistence
functions—Create, Read, Update, and Delete. Some developers building REST applications
have mistakenly associated the four popular HTTP verbs GET, POST, PUT, and DELETE with
CRUD semantics. The typical association often seen is

Create -> POST


Update -> PUT
Read -> GET
Delete -> DELETE

These correlations are true for Read and Delete operations. However, it is not as
straightforward for Create/Update and POST/PUT. As you have seen earlier in this chapter, PUT
can be used to create a resource as long as idempotency constraint is met. In the same way,
it was never considered non-RESTful if POST is used for update (http://roy.gbiv.com/
untangled/2009/it-is-okay-to-use-post). It is also possible for a client to use PATCH
for updating a resource.
Therefore, it is important for API designers to use the right verbs for a given operation than
simply using a 1-1 mapping with CRUD.

HTTP Status Codes


The HTTP status codes allow a server to communicate the results of processing a client’s
request. These status codes are grouped into the following categories:

• Informational codes—Status codes indicating that the server has


received the request but hasn’t completed processing it. These
intermediate response codes are in the 100 series.
14
Chapter 1 Introduction to REST

• Success codes—Status codes indicating that the request has been


successfully received and processed. These codes are in the
200 series.

• Redirection codes—Status codes indicating that the request has


been processed but the client must perform an additional action to
complete the request. These actions typically involve redirecting
to a different location to get the resource. These codes are in the
300 series.
• Client error codes—Status codes indicating that there was an error or
a problem with client’s request. These codes are in the 400 series.

• Server error codes—Status codes indicating that there was an error


on the server while processing the client’s request. These codes are in
the 500 series.

The HTTP status codes play an important role in REST API design as meaningful
codes help communicate the right status, enabling the client to react appropriately.
Table 1-2 shows some of the important status codes into which you typically run.

Table 1-2. HTTP status codes and their descriptions


Status code Description

100 (Continue) Indicates that the server has received the first part of the request and
the rest of the request should be sent.
200 (OK) Indicates that all went well with the request.
201 (Created) Indicates that request was completed and a new resource got created.
202 (Accepted) Indicates that request has been accepted but is still being processed.
204 (No Content) Indicates that the server has completed the request and has no entity
body to send to the client.
301 (Moved Permanently) Indicates that the requested resource has been moved to a new
location and a new URI needs to be used to access the resource.
400 (Bad Request) Indicates that the request is malformed and the server is not able to
understand the request.
(continued)

15
Chapter 1 Introduction to REST

Table 1-2. (continued)

Status code Description

401 (Unauthorized) Indicates that the client needs to authenticate before accessing the
resource. If the request already contains client’s credentials, then a 401
indicates invalid credentials (e.g., bad password).
403 (Forbidden) Indicates that the server understood the request but is refusing to
fulfill it. This could be because the resource is being accessed from a
blacklisted IP address or outside the approved time window.
404 (Not Found) Indicates that the resource at the requested URI doesn’t exist.
406 (Not Acceptable) Indicates that the server is capable of processing the request; however,
the generated response may not be acceptable to the client. This
happens when the client becomes too picky with its accept headers.
500 (Internal Server Error) Indicates that there was an error on the server while processing the
request and that the request can’t be completed.
503 (Service Unavailable) Indicates that the request can’t be completed, as the server is
overloaded or going through scheduled maintenance.

Richardson’s Maturity Model


The Richardson’s Maturity Model (RMM), developed by Leonard Richardson, classifies
REST-based web services on how well they adhere to REST principles. Figure 1-1 shows
the four levels of this classification.

16
Chapter 1 Introduction to REST

Figure 1-1. RMM levels

RMM can be valuable in understanding the different styles of web service and their
designs, benefits, and trade-offs.

Level Zero
This is the most rudimentary maturity level for a service. Services in this level use HTTP
as the transport mechanism and perform remote procedure calls on a single URI.
Typically, POST or GET HTTP methods are employed for service calls. SOAP- and
XML-RPC-based web services fall under this level.

Level One
The next level adheres to the REST principles more closely and introduces multiple URIs,
one per resource. Complex functionality of a large service endpoint is broken down into
multiple resources. However, services in this layer use one HTTP verb, typically POST, to
perform all of the operations.

17
Chapter 1 Introduction to REST

L evel Two
Services in this level leverage HTTP protocol and make the right use of HTTP verbs and
status codes available in the protocol. Web services implementing CRUD operations are
good examples of level two services.

L evel Three
This is the most mature level for a service and is built around the notion of Hypermedia
as the Engine of Application State, or HATEOAS. Services in this level allow
discoverability by providing responses that contain links to other related resources and
controls that tell the client what to do next.

Building a RESTful API


Designing and implementing a beautiful RESTful API is no less than an art. It takes time,
effort, and several iterations. A well-designed RESTful API allows your end users to
consume the API easily and makes its adoption easier. At a high level, here are the steps
involved in building a RESTful API:

1. Identify resources—Central to REST are resources. We start


modeling different resources that are of interest to our consumers.
Often, these resources can be the application’s domain or entities.
However, a one-to-one mapping is not always required.
2. Identify endpoints—The next step is to design URIs that map
resources to endpoints. In Chapter 4, we will look at best practices
for designing and naming endpoints.

3. Identify actions—Identify the HTTP methods that can be used to


perform operations on the resources.

4. Identify responses—Identify the supported resource


representation for the request and response along with the right
status codes to be returned.

In the rest of the book, we will look at best practices for designing a RESTful API and
implementing it using Spring technologies.

18
Chapter 1 Introduction to REST

Summary
REST has become the de facto standard for building services today. In this chapter, we
covered the fundamentals of REST and abstractions such as resources, representations,
URIs, and HTTP methods that make up REST’s Uniform Interface. We also looked at
RMM, which provides a classification of REST services.
In the next chapter, we will take a deep dive into Spring and its related technologies
that simplify REST service development.

19
CHAPTER 2

Spring Web MVC Primer


In this chapter, we will discuss the following:
• Spring and its features

• The Model View Controller pattern

• Spring Web MVC and its components

The Java ecosystem is filled with frameworks such as Jersey and RESTEasy, which
allow you to develop REST applications. Spring Web MVC is one such popular web
framework that simplifies web and REST application development. We begin this
chapter with an overview of the Spring Framework and take a deep dive into Spring Web
MVC and its components.

Note This book doesn’t give a comprehensive overview of Spring and Spring
Web MVC. Refer to Pro Spring and Pro Spring MVC and WebFlux (both published by
Apress) for detailed treatment of these concepts.

S
 pring Overview
The Spring Framework has become the de facto standard for building Java/Java EE-­
based enterprise applications. Originally written by Rod Johnson in 2002, the Spring
Framework is one of the suites of projects owned and maintained by Pivotal Software
Inc. (http://spring.io). Among many other things, the Spring Framework provides a
dependency injection model1 that reduces plumbing code for application development,
supports aspect-oriented programming (AOP) for implementing crosscutting concerns,

1
http://martinfowler.com/articles/injection.html.

21
© Balaji Varanasi and Maxim Bartkov 2022
B. Varanasi and M. Bartkov, Spring REST, https://doi.org/10.1007/978-1-4842-7477-4_2
Chapter 2 Spring Web MVC Primer

and makes it easy to integrate with other frameworks and technologies. The Spring
Framework is made up of different modules that offer services such as data access,
instrumentation, messaging, testing, and web integration. The different Spring
Framework modules and their groupings are shown in Figure 2-1.

Figure 2-1. Spring Framework modules

As a developer, you are not forced to use everything that the Spring Framework has
to offer. The modularity of the Spring Framework allows you to pick and choose the
modules based on your application needs. In this book, we will be focusing on the web
module for developing REST services. Additionally, we will be using a few other Spring
portfolio projects such as Spring Data, Spring Security, and Spring Boot. These projects
are built on top of the infrastructure provided by the Spring Framework modules and are
intended to simplify data access, authentication/authorization, and Spring application
creation.
Developing Spring-based applications requires a thorough understanding of two
core concepts—dependency injection and aspect-oriented programming.

22
Chapter 2 Spring Web MVC Primer

Dependency Injection
At the heart of the Spring Framework lies dependency injection (DI). As the name
suggests, dependency injection allows dependencies to be injected into components
that need them. This relieves those components from having to create or locate their
dependencies, allowing them to be loosely coupled.
To better understand DI, consider the scenario of purchasing a product in an online
retail store. Completing a purchase is typically implemented using a component such
as an OrderService. The OrderService itself would interact with an OrderRepository
that would create order details in a database and a NotificationComponent that would
send out the order confirmation to the customer. In a traditional implementation, the
OrderService creates (typically in its constructor) instances of OrderRepository and
NotificationComponent and uses them. Even though there is nothing wrong with this
approach, it can lead to hard-to-maintain, hard-to-test, and highly coupled code.
DI, by contrast, allows us to take a different approach when dealing with
dependencies. With DI, you let an external process such as Spring create dependencies,
manage dependencies, and inject those dependencies into the objects that need them.
So, with DI, Spring would create the OrderRepository and NotificationComponent and
then hand over those dependencies to the OrderService. This decouples OrderService
from having to deal with OrderRepository/NotificationComponent creation, making it
easier to test. It allows each component to evolve independently, making development
and maintenance easier. Also, it makes it easier to swap these dependencies with
different implementations or use these components in a different context.

Aspect-Oriented Programming
Aspect-oriented programming (AOP) is a programming model that implements
crosscutting logic or concerns. Logging, transactions, metrics, and security are some
examples of concerns that span (crosscut) different parts of an application. These
concerns don't deal with business logic and are often duplicated across the application.
AOP provides a standardized mechanism called an aspect for encapsulating such
concerns in a single location. The aspects are then weaved into other objects so that the
crosscutting logic is automatically applied across the entire application.
Spring provides a pure Java-based AOP implementation through its Spring AOP
module. Spring AOP does not require any special compilation nor changes to the class
loader hierarchy. Instead, Spring AOP uses proxies for weaving aspects into Spring beans

23
Chapter 2 Spring Web MVC Primer

at runtime. Figure 2-2 provides a representation of this behavior. When a method on the
target bean gets called, the proxy intercepts the call. It then applies the aspect logic and
invokes the target bean method.

Figure 2-2. Spring AOP proxy

Spring provides two-proxy implementations—JDK dynamic proxy and CGLIB proxy.


If the target bean implements an interface, Spring will use JDK dynamic proxy to create
the AOP proxy. If the class doesn't implement an interface, Spring uses CGLIB to create a
proxy.
You can read more about JDK dynamic proxy in the official documentation:
https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html

Spring Web MVC Overview


Spring Web MVC, part of the Spring Framework’s web module, is a popular technology
for building web-based applications. It is based on the model-view-controller
architecture and provides a rich set of annotations and components. Over the years, the
framework has evolved; it currently provides a rich set of configuration annotations and
features such as flexible view resolution and powerful data binding.

Model View Controller Pattern


The Model View Controller, or MVC, is an architectural pattern for building decoupled
web applications. This pattern decomposes the UI layer into the following three
components:

Model—The model represents data or state. In a web-based


banking application, information representing accounts,
transactions, and statements are examples of the model.

24
Chapter 2 Spring Web MVC Primer

View—Provides a visual representation of the model. This is what


the user interacts with by providing inputs and viewing the output.
In our banking application, web pages showing accounts and
transactions are examples of views.

Controller—The controller is responsible for handling user actions


such as button clicks. It then interacts with services or repositories
to prepare the model and hands the prepared model over to an
appropriate view.
Each component has specific responsibility. The interaction between them is shown
in Figure 2-3. The interaction begins with the Controller preparing the model and
selecting an appropriate view to be rendered. The View uses the data from the model for
rendering. Further interactions with the View are sent to the Controller, which starts the
process all over again.

Figure 2-3. Model View Controller interaction

Spring Web MVC Architecture


Spring’s Web MVC implementation revolves around the DispatcherServlet—an
implementation of the FrontController Pattern2 that acts as an entry point for handling
requests. Spring Web MVC’s architecture is shown in Figure 2-4.

2
http://www.oracle.com/technetwork/java/frontcontroller-135648.html.

25
Chapter 2 Spring Web MVC Primer

Figure 2-4. Spring Web MVC's architecture

The different components in Figure 2-4 and their interactions include the following:

1. The interaction begins with the DispatcherServlet receiving the


request from the client.

2. DispatcherServlet queries one or more HandlerMapping to figure


out a Handler that can service the request. A Handler is a generic
way of addressing a Controller and other HTTP-based endpoints
that Spring Web MVC supports.

3. The HandlerMapping component uses the request


path to determine the right Handler and passes it to the
DispatcherServlet. The HandlerMapping also determines a list
of Interceptors that need to get executed before (Pre-) and after
(Post-) Handler execution.

4. The DispatcherServlet then executes the Pre-Process Interceptors


if any are appropriate and passes the control to the Handler.

5. The Handler interacts with any Service(s) needed and prepares


the model.

26
Chapter 2 Spring Web MVC Primer

6. The Handler also determines the name of the view that needs to
get rendered in the output and sends it to DispatcherServlet. The
Post-Process Interceptors then get executed.

7. This is followed by the DispatcherServlet passing the logical view


name to a ViewResolver, which determines and passes the actual
View implementation.

8. The DispatcherServlet then passes the control and model to the


View, which generates response. This ViewResolver and View
abstraction allow the DispatcherServlet to be decoupled from a
particular View implementation.

9. The DispatcherServlet returns the generated response over


to the client.

Spring Web MVC Components


In the previous section, you were introduced to Spring Web MVC components such as
HandlerMapping and ViewResolver. In this section, we will take a deeper look at those as
well as additional Spring Web MVC components.

Note In this book, we will be using Java configuration for creating Spring beans.
Contrary to XML-based configuration, Java configuration provides compile-­time
safety, flexibility, and added power/control.

C
 ontroller
Controllers in Spring Web MVC are declared using the stereotype org.
springframework.stereotype.Controller. A stereotype in Spring designates roles or
responsibilities of a class or an interface. Listing 2-1 shows a basic controller.

27
Chapter 2 Spring Web MVC Primer

Listing 2-1. HomeController Implementation

@Controller
public class HomeController {
        @GetMapping("/home.html")
        public String showHomePage() {
                return "home";
        }
}

The @Controller annotation designates the HomeController class as a MVC


controller. The @GetMapping is a composed annotation that acts as a shortcut for ­@
RequestMapping(method = RequestMethod.GET). @GetMapping annotation maps
web requests to handler classes and handler methods. In this case, the @GetMapping
indicates that when a request for home.html is made, the showHomePage method should
get executed. The showHomePage method has a tiny implementation and simply returns
the logical view name home. This controller did not prepare any model in this example.

M
 odel
Spring provides the org.springframework.ui.Model interface that serves as holder for
model attributes. Listing 2-2 shows the Model interface with the available methods. As
the names suggest, the addAttribute and addAttributes methods can be used to add
attributes to the model object.

Listing 2-2. Model Interface


public interface Model {

        Model addAttribute(String attributeName, Object attributeValue);

        Model addAttribute(Object attributeValue);

        Model addAllAttributes(Collection<?> attributeValues);

        Model addAllAttributes(Map<String, ?> attributes);

        Model mergeAttributes(Map<String, ?> attributes);

28
Chapter 2 Spring Web MVC Primer

        boolean containsAttribute(String attributeName);

        Map<String, Object> asMap();

        Object getAttribute(String attributeName);

The easiest way for a controller to work with a model object is by declaring it as
a method parameter. Listing 2-3 shows the showHomePage method with the Model
parameter. In the method implementation, we are adding the currentDate attribute to
the model object.

Listing 2-3. showHomePage with Model Attribute

@GetMapping("/home.html")
public String showHomePage(Model model) {
        model.addAttribute("currentDate", new Date());
        return "home";
}

The Spring Framework strives to decouple our applications from the framework’s
classes. So, a popular approach for working with model objects is to use a java.util.
Map instance as shown in Listing 2-4. Spring would use the passed-in Map parameter
instance to enrich the model that gets exposed to the view.

Listing 2-4. showHomePage with Map Attribute

@GetMapping("/home.html")
public String showHomePage(Map model) {
        model.put("currentDate", new Date());
        return "home";
}

V
 iew
Spring Web MVC supports a variety of view technologies such as JSP, Velocity,
FreeMarker, and XSLT. Spring Web MVC uses the org.springframework.web.servlet.
View interface to accomplish this. The View interface has two methods, as shown in
Listing 2-5.

29
Chapter 2 Spring Web MVC Primer

Listing 2-5. View Interface API

public interface View


{
        String getContentType();

        void render(Map<String, ?> model, HttpServletRequest request,


HttpServletResponse response) throws Exception;
}

Concrete implementations of the View interface are responsible for rendering the
response. This is accomplished by overriding the render method. The getContentType
method returns the generated view's content type. Table 2-1 shows important View
implementations that Spring Web MVC provides out of the box. You will notice that all
of these implementations reside inside the org.springframework.web.servlet.view
package.

Table 2-1. Spring Web MVC View Implementations


Class name Description

org.springframework.web.servlet.view. View implementation that encodes model


json.MappingJackson2JsonView attributes and returns JSON
org.springframework.web.servlet.view. View implementation that performs XSLT
xslt.XsltView transformation and returns the response
org.springframework.web.servlet.view. View implementation that delegates the request
InternalResourceView to a JSP page inside the web application
org.springframework.web.servlet.view. View implementation that uses Apache Tiles
tiles2.TilesView configuration for Tile definition and rendering
org.springframework.web.servlet.view. Specialized implementation of
JstlView InternalResourceView that supports JSP
pages using JSTL
org.springframework.web.servlet.view. View implementation that redirects to a different
RedirectView (absolute or relative) URL

30
Chapter 2 Spring Web MVC Primer

Listing 2-6 shows the reimplementation of the HomeController that we looked at


earlier. Here we are creating an instance of JstlView and setting the JSP page that we
need to be rendered.

Listing 2-6. HomeController View Implementation

@Controller
public class HomeController {
        @RequestMapping("/home.html")
        public View showHomePage() {
                JstlView view = new JstlView();
                view.setUrl("/WEB-INF/pages/home.jsp");
                return view;
        }
}

Controller implementations typically don't deal with view instances. Instead, they
return logical view names, as shown in Listing 2-1, and let view resolvers determine
and create view instances. This decouples the controllers from tying to a specific view
implementation and makes it easy to swap view implementations. Also, the controllers
no longer need to know intricacies such as the location of the views.

@
 RequestParam
The @RequestParam annotation is used to bind Servlet request parameters to handler/
controller method parameters. The request parameter values are automatically
converted to the specified method parameter type using type conversion. Listing 2-­7
shows two usages of @RequestParam. In the first usage, Spring looks for a request
parameter named query and maps its value to the method parameter query. In the
second usage, Spring looks for a request parameter named page, converts its value to an
integer, and maps it to the pageNumber method parameter.

31
Chapter 2 Spring Web MVC Primer

Listing 2-7. RequestParam Usage

@GetMapping("/search.html")
public String search(@RequestParam String query, @RequestParam("page") int
pageNumber) {
        model.put("currentDate", new Date());
        return "home";
}

When a method parameter is annotated using @RequestParam, the specified request


parameter must be available in the client request. If the parameter is missing, Spring will
throw a MissingServletRequestParameterException exception. One way to address
this is to set the required attribute to false, as shown in Listing 2-8. The other option is
to use the defaultValue attribute to specify a default value.

Listing 2-8. Making a Request Parameter Not Required

@GetMapping("/search.html")
public String search(@RequestParam String query,
@RequestParam(value="page", required=false) int pageNumber,
@RequestParam(value="size", defaultValue="10") int pageSize) {
        model.put("currentDate", new Date());
        return "home";
}

@
 RequestMapping
As we learned in the “Controller” section, the @RequestMapping annotation is used to
map a web request to a handler class or handler method. @RequestMapping provides
several attributes that can be used to narrow down these mappings. Table 2-2 shows the
different elements along with their descriptions.

32
Exploring the Variety of Random
Documents with Different Content
– Ne te né! Bizony elmenne előttem passusmutogatás nélkül! Hol
az igazság?
Manassé boszusan fordult az alkalmatlankodó felé. Kicsi, széles
vállú, tömzsi emberke volt az; székelyes zekében, hosszúszárú
csizmában, fején nagy kalappal. Aránytalan hosszú karjai voltak.
Bajusza, szakálla kurtára nyírva, vagy talán inkább régóta nem
borotválva, ott állt nagy hegykén szétterpesztett lábakkal Manassé
előtt, mintha birkózni híná.
Blanka csak elbámult, midőn azt látta, hogy Manassé csakugyan
ölre kap ezzel az emberrel, átnyalábolja mind a két karjával; – de
azért nem mentek egymással birokra, hanem inkább összevissza
csókolták egymást.
– Áron! kedves bátyám!
– Én vagyok biz az, Manassé öcsém, szólt a tömzsi emberke
nevetve, s félvállra vetette a zekéjét, hogy a jobb kezével
megszoríthassa az öcscse kezét.
Aztán Blankához fordult.
– Hát ez a drágalátos szent kép meg tán az ángyikánk lesz?
Ugyan, az Isten áldja meg, hajoljon le hozzám kisség; hadd adjak az
arczára vaj egy fél csókot.
Blanka megtette a kivánságát s adott aztán az arczára Áron nem
felet, de másfelet s elégülten mondá rá:
– Ugyan szeretem, hogy nem fakadt sírva, hogy megszurkálta a
borostás szakállom. Négy nap óta nem borotválkoztam ám. Mind itt
lestem a nagyságos uramöcséméket három nap, három éjjel a
vámdutyiban.
– De hát, hogy tudtad bátyám, hogy ezen jövünk?
– Hát a lófőnek is van annyi esze, hogy ki tudja kálkulálni, hogy a
ki Szathmárból jön Erdélybe, annak a nagy hidon kell bebandukolni.
Itt vagyok biz én parancsolatodra, három nap, három éjjel, minden
utasnak én eresztém fel éjszaka e sorompót, s nem evém az alatt
egyebet szalonnánál, kenyérnél; s csak az az egy bajom volt, hogy
hagymát nem ehettem hozzá, nehogy megharagudjatok érte, ha
majd megcsókollak.
Szegény jó bányász. Három napig lemondott az éltető
hagymájáról, a rokoni csók kedveért.
– Hát a két bátyámról mit tudsz?
Ez volt a legsürgetősebb kérdése Manassénak.
Erre a kérdésre megállt Áron a gyaloghid közepén s kétfelé
vetette a lábait, úgy, hogy nem lehetett tőle tovább menni.
– Mondok egyet, Manassé öcsém, igyunk ahajt előbb egyet.
S egy kulacsot húzott elő a zekéje ujjából.
– Én nem szomjazom.
– De jóféle székely ital ám: fenyővíz.
– Azt meg épen nem szomjazom.
– De én addig egy tappot sem megyek ám odább, a míg velem
nem iszol elébb.
Manassé ismerte a bátyját: tudta, hogy az szavának áll.
– No hát inkább iszom.
– Egészségedre legyen. Már most én is iszom. S mondd vissza.
– Egészségedre legyen.
– Köszönet érte. Hallod, hogy harangoznak a mi feleink
templomában?
– Azt is hallom.
– Rosszul harangoznak. Egészen elkálvinistásodott a
harangozásuk. Nem tudják olyan szépen, mint minálunk odahaza
Toroczkón; hogy egészen megfordul a harang a koronájával lefelé s
csak az egyik oldalát üti meg; «egy! egy! egy!» nem úgy mint ezek
«egy-kettő, egy-kettő, bing-bang!»
– De én nem bánom, akárhogyan húzzák!
– Dehogy nem bánod! Tudod-e, hogy ma Úrnapja vagyon? Aztán
ez a délesti isteni tiszteletre hívó harangszó. Aztán tudod, hogy két
székely testvér, ki egy kulacsból ivott, s ha Úrnapján délesti
harangszó után van az idő, akkor nem szokott egymással
veszekedni. Pedig ha én te neked arra a kérdésedre felelek, hogy hol
van a te két bátyád? hát abból veszekedés lesz. Aztán azt nem
szabad ennek a gyönge ifjasszonykának meghallani. Majd ha ez
egyszer el fog aludni, akkor beszéljünk róla: tudod?
Manassé meg volt hatva a kérges tenyerű bányásztestvér
gyöngéd jószívűségétől. Ő nem akarta Blankát megszomorítani.
– Csak annyit mondj meg, hogy élnek-e? súgá Áronnak.
– Hát bizonyára élnek. Elfeledted a hiszekegyet? Örök életünk
van. – Élnek bizony. Ők jönnek lóháton elejbénk a Leánykakőig, csak
tartsa készen a számukra ángyika a vőfélybokrétát! mert ingyen nem
tanulták be a szép menyasszony-fogadó verset.
Blanka mosolygott a jó Áron tréfáján s azt mondta, hogy majd
maga fog szedni az erdőn őszi virágokat a számukra.
– No abban ugyan lesz ám módja a szép ángyikának, olyan
helyen megyünk végig, a mi most is tele van virággal. Ha nem hiszi,
nézze ezt a piros bokrétát a kalapom mellett, még el sem hervadt;
ezt is ott téptem a tordai hasadékban. Ugyan hallotta-e már hirét a
tordai hasadéknak? Nincs olyan természeti csoda több a kerek
világon. Az egész életében meg fogja emlegetni. Ott van ám
gyönyörűséges szép virágos kert! Meg a híres Balyika vára: a ki a
Rákóczy Ferencz vezére volt. Azt is megnézzük, ugy-e drága
bálványom? Onnan aztán csak egy ugrás a Székelykő s otthon
vagyunk. Szeret-e erdőn keresztül gyalogolni?
– Az a legnagyobb örömem.
– No hát ebből lesz sok.
Manassé súgva kérdé Árontól:
– Te igazán a tordai hasadékon át akarsz bennünket vezetni? –
Hát akkor nem is jutunk mi el a Leánykakőhöz!
– Ejnye, de szigorú vagy! Hiszen tudod, hogy mikor a szegény
góbé urakkal beszél, csak megmondja az igazat; – csakhogy nem
egyszerre.
Most trombitarecsegés vonta félre a figyelmüket. Egy szakasz
Mátyás-huszár vonult át a hidon: fiatal ujonczlovasok mind.
– Ne te né! Milyen büszkén ül azon a lovon! Bizony meg se látná
a szegény embert? Hé Dávid öcs! Hé! Micsoda huszár vagy te, ha
még a szép asszonyon se akad meg a szemed? Te varasgyék!
Ezzel a kiabálással csakugyan odacsalta a hadcsapat élén lovagló
fiatal hadnagyot a gyaloghid korlátjához Áron.
Szakasztott hasonmása volt Manassénak. Ugyanazon arcz,
termet, szemek. Akárhányszor összetévesztették őket egymással.
Csak egy év különbségük volt az időkorban.
A korláton keresztül nyújtotta kezét Manassénak s míg a kezeik
egymást szorították, sokáig néztek egymás szemébe.
– Hová? bátya! szólt Manassé.
– Megyek a két bátyámért boszút állni.
– Én pedig megyek őket megmenteni.
– Megyek a hazámat védni.
É
– Én is oda.
S aztán megcsókolták egymást.
– Hát az ángyikádtól nem kérsz egy csókot? te rusnya béka!
dorgálá őt Áron bátya.
A fiatal hadfi elpirult erre, mint egy szűzleány.
– Majd ha visszatérek; ha megérdemlettem: megkérem azt. Ugy-
e megadod azt, ha halva hoznak is eléd, édes ángyom?
Blanka sejtelemteljesen nyujtá neki kezét.
– Ne félj, nem halok meg! kiálta szikrázó szemekkel, mikor azt
látta, hogy Blanka szemébe köny gyűl. Egy az Isten!
– Egy az Isten! dörmögé utána a vénebb testvér. Az ifju
sarkantyuba kapta paripáját s csapatja élére vágtatott.
– Siessünk, mormogá a hosszú karú s átvéve Blanka utitáskáját,
nagy gyorsasággal vezette őket tekervényes utczákon keresztül
egész a házsongárd utczáig; ott volt egy nyári mulatólaka a
családnak, egyuttal megszálló, ha Toroczkóról bejöttek. Odáig még
pipagyujtásra sem állott meg.
A ház mellett kert is volt, az most zöldséges kertül volt kiadva
egy kufárnénak; az hevenyészett estebédet az utasoknak. Blanka
kiment hozzá a tűzhely mellé s segített neki. A kufárné is részese
volt már az összeesküvésnek, a mibe mindenki be volt avatva, a kivel
csak Blankának érintkeznie kellett. Terv szerint titkolták előtte a
veszélyt, mely őt minden oldalról körülfogja, s melynek szédítő
örvénye fölött csak egy keskeny fenyűszál vezet keresztül. Neki nem
szabad az örvénybe lenézni.
– Tud-e a szekéren alunni, lelkem nagyságos asszony? Kérdé,
dolgát folytatva a sütő-főző asszony. Én néha két hétig is úgy alszom
utazva, mikor almát hordok eladni a Mezőségre. Megszokja azt az
ember. Mert az urak még az éjjel akarnak ám tovamenni Torda felé.
Mivelhogy holnap országos vásár lesz Kolozsvárott s arra annyi tordai
cserzővarga, mézeskalácsos, kofapecsenyesütő, s más efféle fog
tódulni erre felé, hogy velük szembe szinte lehetetlen lesz haladni.
Hát még a rengeteg sok szarvasmarha, birka, sertés, a mit
felhajtanak! Azért még az éjjel akarnak utrakelni.
Blanka igen helyesnek találta azt.
Áron bátya pedig azalatt a lovakat befogatva odakinn, elmondá
rövid szóval Manassénak, hogy «elől tűz, hátul víz».
A rengeteg oláh tábor, mely Toroczkót fenyegeti, a tordai
hegyeket tartja megszállva. A tordaiak eddig erősen tartják
magukat; de most jött a hír a főparancsnoksághoz, hogy Kalliany
császári tábornok egy dandárral közelít Szeben felől. Akkor Tordáról
minden ember menekülni fog Kolozsvár felé. Pedig már a
nagyszebeni és felvinczi menekültek is ott vannak. Ha ez megindul,
azzal szemközt hatolni tiszta lehetetlenség lesz. Azért egy órai
elvesztegetni való idő sincsen, hogy mielőtt a népvándorlás
megindul, ők elérhessék a Hesdád pataki malmot, a mi a tordai
hasadék szállója. Onnan aztán gyalog tovább – madárlátta
ösvényeken.
Blanka megszokta már az éjjeli utazást: azt hitte, mulatságból
történik ez így. Ösztön, sejtelem, vagy talán az «otthon» utáni vágy,
súgta neki is, hogy sietni kell. S nagy veszély érzetében az
asszonyok kitartása óriási.

XXXIX.
Áron maga hajtotta a lovakat (egyet ott hagyott a háznál);
hármasba fogta őket. Manassé mellette ült, s a hátsó ülés Blankának
volt egészen átengedve, a kit a kertésznő kendőkkel úgy bekötözött,
bundába úgy betakart, hogy alig látszott ki belőle.
Hanem azért a mindent meglátó asszonyi szem majd hogy fel
nem fedezte a kegyes csalást, a mivel a szemközt jövő veszélyt
előtte takargatni igyekeztek.
– Nini! ezek a lovak fel is vannak nyergelve, szólt Áronhoz.
– Az ám, felelt a bányász, megzavarhatlan kedélylyel, Erdélyben
ilyen bahó szokás van. Csak olyan formán, mint a hogy a stajerek
meg a ló nyakára tesznek egy nagy kalodát.
Blanka megnyugodott benne, hogy ez csak erdélyi szokás. Azzal
Áron neki ereszté a gyeplőt a három jó székely paripának, a mik a
havason nevekedtek s úgy voltak szokva, hogy ha kell, egy
huszonnégy óráig étlen szomjan elkoczogjanak, s ha egy kicsit
kieresztették őket a fűre, megint be hagyják magukat fogni, hogy
újra kezdjék, a mit elhagytak.
A kocsisnak nem is igen nagy szüksége volt rá, hogy a lovakat
igazgassa. Tudták azok mind a kötelességüket, hegynek fel húzni,
völgynek le tartani, síkon koczogni, maguk előtt haladó szekeret
megelőzni, ha a hátul jövő zörgését hallják, akkor vágtatásnak
eredni, becsületsértést elejbekapással meg nem türni, csárdakapunál
szépen megállani.
Áronnak elég alkalma volt, hogy a kocsisülésből visszafordulva,
ángyikáját vidám adomákkal mulattassa, a mikből kifogyhatalan volt
s jóizű természetes humorral tudta azokat előadni.
Egyszer aztán: mikor vette észre, hogy a felekhegyi unalmas
fölhágónál, mikor lassan halad a szekér, az ifjasszonyka elbólintott, s
a tordai «okos malacz» adomáján sem akar nevetni: akkor a
ködmene zsebébe nyult s onnan kivonva zománczos arany óráját,
annak a gombját megnyomta, s az ismétlő órát ütteté, a füléhez
tartva.
«Tizenkettő és két negyed.»
Az egész ember ilyen volt: aranyóra báránybőr-bekecs zsebben.
Parasztos külső alatt nemes emberi szív: munkában tört tenyér, s
tanult, eszes fő; népies szólásmódokba burkolt értelmesség; gúnyoló
pór-cynismus az uraskodók, a hetvenkedők előtt; hidegvér, jó kedély
a veszélyben: igazi székely lófőpéldány. (A «lófő» nem gúny, hanem
rangczím a székelynél.)
Tehát a mint az ismétlő óra tizenkettőt és felet ütött, azt mondá
az öcscsének:
– No most már elmúlt az Úrnapja, öcsém, az ifjasszonyka is
elaludt, beszélgethetünk egyről-másról. Hát a két bátyád után
tudakozódtál, hogyan jutottak azok fogságra? Hát hogy az elején
kezdjem. Tudod, mikor megszületett a szabadság, hát ez még akkor
gyönge gyerecske volt, a ki azt akarja, hogy szoptassák. Hát én
tehetek róla, hogy ez olyan csecsemő, a kinek nem tej kell, hanem
vér? Biz a toroczkói fiatalság is beállt mind egy szálig honvédnek. Ott
szolgálnak a jámborok a 11-ik, 32-ik és 73-ik zászlóaljakban. Hallom,
mit mondasz te erre? «hogy hát mi szükség volt a bányászoknak
katonákká lenni? Semmi okos nemzet nem viszi el a bányászait a
csatatérre. Eleget harczolnak már azok hazájukért a föld alatt egész
életükön keresztül. Elég, ha ők készítik a vasat, még forgassák is?
Miért kapták II. Endrétől, IV. Bélától szabadalmaikat, hadi szolgálat
alól felmentésüket? Miért irták alá 1702-ben a város vénei a
reversalist, hogy soha közülök és maradékaik közül senki fegyvert
nem fog, és a maradékaiknak is meghagyják, hogy fegyverhez ne
nyuljanak, a mit meg is tartottak híven mind ez esztendeig?» – Ezt
mondod te Manassé öcsém, ugy-e? Könnyű neked onnan a
külföldről! De lettél volna csak idehaza! Láttad volna csak Dávid
bátyádat, mikor a piacz közepén azt a beszédet tartotta a
fiatalsághoz s maga is lóra ült és kardot kötött: magad is velük
mentél volna! Aztán ki olthatja el azt a tüzet, a hol minden ház ég?
Az egész fiatalság égett, lángolt. Nem lehetett azt eloltani. Aztán
nem is olyan háború ez, mint más. Ha György fejedelem hadat
indított Lengyelország ellen, azt mondhatta rá Toroczkó: mi közöm
hozzá, ám lássa György, hogy húzza ki a saruját a sárból, ha
belelépett! De most a szabadságról van szó s ez Toroczkónak is
dolga. – Hallom, mit felelsz te erre? – Hogy «jól van hát no: ha a
ménkü-fiatalság nem maradhatott a sarkán; de hát nekünk véneknek
lehetett volna már annyi eszünk, hogy tudtuk volna, hogy nem kell a
puliszka-evéshez kés; hát mi minek fogtunk fegyvert? Minek
állítottunk ki egy nemzetőr-zászlóaljat?» Hát erre csak azt mondom
neked, a mit az egyszeri góbé mondott a földes úrnak, a kinek a
szelindekét agyonszúrá vas villával, s az szidá érte: hogy mért nem
üté inkább a villa nyelével? Azt tevém vala, mondá a góbé, ha a
szelindek is a farkával akart volna engem megharapni. Köröskörül az
egész oláhság fegyvert fogott; nekünk is hozzá kellett nyulnunk a
magunk védelmére s bizony úgy megőrizzük a hozzánk vezető
utakat, hogy ingyen azokon semmi nép be nem jön. Mivel pedig a
két bátyádat legjobban szerette a népség, mit tehetett mást,
minthogy őket választotta meg hadnagyainak. Hisz ez máskor is csak
úgy volt. A ki legokosabb ember volt a városban, az vezette a
dandárt: váczi püspök, kalocsai érsek az egész sereget. Hallom ám a
nagy pirongatásodat, hogy no ugyan derék sereg, a ki elhagyta fogni
a két vezérét! De csak ne lármázz olyan nagyon! (Manassé még egy
szót se szólt.) Meglátod, hogy a két bátyád nem esik egy sorba a
tordai malaczczal, a kinek esztendős létére lehetett volna már annyi
esze, hogy ne futott légyen a szekér alá. Tudod, hogy a balázsfalvi
román népgyülésre következett az agyagfalvi székely népgyülés.
Sándor bátyád is jelen volt azon az aranyosszékiekkel. Akkor aztán a
mi kis szigetünk itt maradt a tenger közepett. Egy tízezer főből álló
oláh tábor, Móga vezetése alatt (talán ismered ő kelmét?) megjelene
nálunk a «Kő» előtt. Mi pedig volnánk háromszáz puskások. Épen
annyi, a mennyit Thermopylænél vezényelt Leonidás. S a «Kő» is
olyan jó erősség, mint a Thermopylæ. Legöregebb bátyánk a Bertók
azonban, a ki azóta, hogy vegetariánussá lett, minden vérontásnak
ellensége, s még egy csirkét sem enged megölni, azt tanácsolta,
hogy kisértenők meg a békés kiegyezést. Sorsot húztunk: ki menjen
el közülünk? Simon bátyád neve jött ki. Az átmene az ellentáborhoz,
fehér zászló alatt. De azonban ott fogták s nem eresztették vissza.
Ekkor fogta magát a Jonathán, utána ment, hogy majd ő váltságot
ajánl érte. Akkor azt is ott fogták. Már most ott vannak mind a
ketten. Már most aztán az oláh atyafiak azzal fenyegetnek
bennünket, hogy ha meg nem adjuk magunkat, ha le nem rakjuk a
fegyvert, ha be nem bocsátjuk őket Toroczkóba, akkor mind a két
testvérünket felakasztják. Mi pedig nem rakjuk le a fegyvert és nem
bocsátjuk be őket, inkább mind egy lábig elveszünk. És te én nekem
hiába lármázol; mert engem meg nem térítesz. Én beszélek a
hozzám beszélőkkel; de ha harapnak, én is harapok. Csunya dolog
ugyan, hogy a két bátyádat felakaszszák; nemes embert soh se
akasztottak, hanem megtisztelték, fejét vették; de hát mit
kényeskedel most? Mit válogatsz a parasztnak való, meg a nemesnek
való halálban? Egyenlőség van most. Hiába kiabálsz, szidsz,
rugódozol; én most viszlek Toroczkóra, s minthogy a két bátyádnak
már «servus világ!» neked kell a csapat élére állnod: te már tudod a
kommandót s láttál Bécsben és Rómában is torlaszharczot. – De
ugyan ne veszekedjél hát velem olyan nagyon.
Manassé pedig még egy szót sem szólt, csak hagyta Áront maga
magával (az ő nevében is) vitatkozni.
– Nem veszekedem én veled, bátya. S bár vinnél hát haza
Toroczkóra. Nem is rugódozom egy cseppet sem. Hanem úgy látom,
hogy nem jutunk mi oda. Gazda nélkül csináltuk a számadást. Nézd
azt a roppant porfelleget, a mi ránk szemközt jő.
– Ejnye bizony, ugyan jó szemed van, hogy holdvilágnál is
meglátod. Én nem vettem eddig észre. Egész Torda meg Nagy-Enyed
jön szemközt. Azok is megkezdték az elmult estén a menekülést,
hogy felhasználják az éjszakát. Ezen az uton ma keresztül nem
törünk. – Hanem hát azért ne busulj. Rossz róka az, a melyiknek
csak egy lyuka van.
A Felek-hegy magaslatáról messze el lehetett látni a holdsütötte
tájon: a Torda felé vezető út fehéren kanyarodott alá, a távolban
magasra emelkedő fellegtől jelölve.
– Látod ezt a völgyet itten jobbra? Itt az erdős hegyhát alatt. Erre
is út van. Ez vezet Oláh-Fenesre. Ezek jó oláhok: velünk tartanak.
Annak a jeléül a hosszú hajukat is levágták. Azontul jön Szent-
László. Ott magyarok laknak. Odáig elmehetünk szekéren. Gyilkos út
biz az; egyikünknek gyalog kell menni a szekér mellett, hogy tartsuk,
mikor dűlni akar s az asszonykát fel kell ébresztenünk, hogy
megfogózzék a lőcsben. De te azért semmit se félj! A ló kitartja s a
szekér toroczkói munka, elmegy az «ördög szántásán» keresztül is,
tengelytörés nélkül.
A mint a kocsi megállt, magától felébredt Blanka. Manassé
odament hozzá; beszélt neki a szép csillagos égről, megcsókolta a
kezét, s kérte, hogy dugja el a bunda alá, mert megfázik; azzal Áron
bátya neki fordította a völgyi útnak a lovakat, s elkezdődött a
veszedelmes haladás azon az úton, melyen csak fát szoktak
különben felhordani.
A völgyben sötét éjszaka volt: a hold nem sütött ide le; Blanka
nem tudta többé a szemeit nyitva tartani, a mire különben a szekér
döczögése sem invitálta nagyon; olyanokat zökkent az, hogy csoda
volt épségben maradása, s néha úgy féloldalra vágott, hogy még
nagyobb csoda volt fel nem borulása.
Egy izben a keserves út felkanyargott a hegyhátra. A mint ott
pihenőt tartottak, a tordai úton vágtató szekerek dübörgése úgy
hangzott át hozzájuk a csendes éjszakában, mint a távoli égzengés
moraja. Délfelé, keletfelé a hegyek csúcsain vereslő fények kezdtek
kigyulni. «Milyen szép!» mondá Blanka hátra tekintve. Ő nem tudta
azt, hogy azok jeltüzek, mikkel táborozó csapatok izengetnek
egymásnak emberirtó munkára való jelszavakat.
Most egy falu következett: a katonai térképen Peánának van
följegyezve. Különben mindegy, akár hová rajzolta azt a jelt a
mérnök; mert az a falu hosszabb egy mérföldnél: a házak oly
messze egymástól, hogy egyik szomszéd a másik kiáltását meg nem
hallja. Három temploma van; egyszerű faépületek. Egyik ház fel van
rakva a hegyoldalba, másik le a patakpartra. Alusznak már
valamennyiben, csak a patakmalom ablakában ég a mécses; a
kocsizörejre kitekint valaki a sötét éjszakába és egyet kurjant.
Egy kanyarodónál megnyilik a hegyvágányt elzáró erdős
hegyoldal s oda engedi sütni a holdvilágot a csendes tájképre. Zugó
patak, tele nőve égerfákkal; azon keresztül dobogó hid; a hidon túl
palánkkal körülvett emeletes ház; a földszintje fehér kőből rakva, az
emelete karzatos lépcsővel és tornáczczal, fából alkotva, s rajta
piramidélességü magas tető, hangyász-pikkely módra
bezsindelyezve. Körülötte öt más hasonló, de kisebb mérvű házikó.
Túl rajta rengeteg nagy gyümölcsös, melynek garádja mellett omlik
alá a sziklákról a hegyi patak.
A kutyaugatás messziről jelzi a közeledő szekeret. – Az udvarban
éjfélre kukoritanak a kakasok.
– Hallod, hogy kukorítanak a Ciprianu kakasai? mondá öcscsének
Áron.
– Hát te még Ciprianut is ismered, meg a kakasait is?
– Az egyiket jobban, mint a másikat. Ciprianu oláhnak született
magyar nemes ember. Regalista is volt. A kakasai pedig unicumok az
egész világon. Tiszta fehérek és a nyakuk, fejük egészen olyan, mint
a pulykáé. A kiáltásuk is olyan öblögető hang. Különös jó faj. De
Ciprianu nem ád belőle senkinek, se pénzért, se barátságért; kivéve
kappant. Még a tolvajoktól is meg tudja őrizni: azért tart annyi
kutyát. S ha meghallja a szekerünket zörögni, bizonyos, hogy kijön a
tornáczra s kilövi a puskáját; nem ugyan ránk, hanem a levegőbe,
azért, hogy tudassa, hogy ébren van s felfegyverkezve.
– Nem tartozik a fölkelőkhöz?
– Azt nem lehet tudni. Talán igen, talán nem. A nemes urak az
oláhok között eddig még tartották magukat. Dacoromaniát
szeretnék, de a democratiát nem. Eszük is van, vagyonuk is van s az
nem kivánkozik a forradalomba.
E közben mind közelebb értek a házhoz, melyet a patak
választott el az úttól. Itt a völgy lápján jó út is volt, kissé nyirkos, de
síma; sebesebben lehetett haladni.
A házcsoportot körülvevő palánkra fölkapaszkodtak a
komondorok s fejeiket kidugva a faragott deszkák között, onnan
ugattak alá.
Most egy lövés hangzott az éjszakában a ház tornáczáról.
– Mondtam ugy-e? szólt Áron.
– Úr Isten! Mi reánk lőttek? kiáltá föl Blanka.
– Ne féljen, ángyikám: nem nekünk szólt az s aztán elkiáltá
magát kürtnél magasabb hangon: Ne lövöldözz Ciprián! Asszony van
a szekéren; megijed tőle.
Erre a palánkon belül nagy kutyaexecutió támadt, valaki
husánggal tanította jobb véleményre a békétlenkedőket, s aztán a
tanórkapun keresztül kijött egy öles termetű óriás, kifordított
bundában, nagy furkósbottal a kezében s odaügetett a szekérhez,
azokkal az oláhnál szokásos hibbanó lépésekkel.
– Sze treaszka Adorján!
– Sze treaszka Ciprian!
Az első üdvözletre támadt párbeszéd oláhul folyt s abból Blanka
nem értett semmit. Ciprian a hegyeken látszó jelekre mutogatott, a
szemei ijedten forogtak aközben. Végre megfogta az egyik ló
zabláját s erővel félretéríté az útból a szekeret, a saját kapujához
vivő hidra terelve azt.
– Mi történik velünk? kérdé Blanka.
– Semmi baj; felelt neki Áron. A domnule azt mondja, hogy nem
jó lesz ez úton tovább mennünk; mert a víz úgy elrontotta az
átjárókat, hogy éjszaka még szerencsétlenül járhatunk. El kell
fogadnunk a meghivását, hogy töltsük nála a hátralévő éjszakát.
Igazat is mondott Áron, de nem «egyszerre». Mert Ciprian
csakugyan nem tanácsolta a tovább haladást ezen az úton: csakhogy
nem a vizek miatt, hanem a tüzek miatt ott a hegyeken.
A nemes úr maga sietett kinyitni a kaput s aztán szétverni az
ebeket az udvaron, mely zajra többen is jöttek elő a házból. A falusi
embernek soha sincs egész éjszaka, félig felöltözötten alszik az, s
éjjel is fölkel, körülnézni a házat, az aklokat.
A házi gazdának volt egy szép leánya. Épen olyan magas, öletérő
személy, mint az apja, szabályos római metszésű vonásokkal. Az
lejött az udvarra, apja hivására, s Blankát úgy emelte le a szekérről,
mint egy gyermeket. Úgyis vitte fel az ölében a ház emeletébe.
Kellemes kis kastély volt az. Tölgyfából faragva az egész, a mi
simára volt gyalulva és kifényesítve. A konyha, mely egyúttal
előtornácz, tiszta, mint egy sekrestye, fényesre csiszolt czin-
edényekkel a tálason. A tűzhelyen még nem aludt ki a tűz, a friss
gyaluforgácstól felélesztve, egyszerre lángra kapott az s a kürtő úgy
volt csinálva, hogy annak a hátlapja, mázos kemencze-oldal
alakjában, a konyha melletti szobát fütötte.
A házi gazda és leánya csupa szivesség voltak vendégeik iránt.
Egyik asztalt terített számukra; másik hozzálátott a kedvencz étel: a
bálmos készítéséhez. Felhordták eléjük, a mi csak jó és ízletes volt a
házuknál s kinálták erősen Blankát valami idegen nyelven, a mi
hasonlított az olaszhoz, de a miből azért egy szót sem értett.
– Tudnak pedig magyarul is mind a ketten; sugá egyszer Áron
Blankának, mikor magukra maradtak, de most olyan idő van, a mikor
elfelejtették.
Blanka aztán törte rajta a fejét, hogy micsoda idő lehet az, a
mikor az ember valamit elfelejt, a mit máskor tudni szokott? – Blanka
annyit tudott meg, hogy a ház leányát Zenobiának híják.
Mikor asztalhoz ültek, Zenobia kezet akart csókolni Blankának.
Blanka nem engedte azt, hanem magához ölelte a leányt, s
megcsókolta annak a szép arczát.
A házi gazda nagy dolgot csinált ebből!
Blanka nem érté, mit beszélt, de az oláh oly elevenen tud
kezével, arczvonásaival magyarázni, hogy Blankának abból, a mint
Ciprianu a fejéhez kapkodott, Áronnak a vállát megtaszigálta, a saját
összefogott ujjai hegyét megcsókolgatá, égnek emelt fejét himbálta,
a szemöldökeit felrángatta; lehajolt, meg felegyenesedett, a mellére
ütött, aztán megint nagy izmos tenyereit Blanka felé czirógatásra
forgatta, – ki lehetett venni olyasmit, hogy az oláh-magyar nemes
büszke erre a leányának adott csókra.
Míg Áron ezalatt még kurtábban húzta össze a nyakát a válla
közé s csak a kurta bajuszát rángatta s aztán úgy szétvetette a
lábait, mint mikor valaki háborgó tenger közepett áll meg a hajó
födélzetén.
Utoljára kirohant Ciprianu az ajtón, le a lépcsőn s néhány percz
mulva megint be a szobába, kisérve nagy siralmas kárálástól és
kotkodácsolástól. Egy kakast meg egy jérczét hozott lábaiknál fogva
egymáshoz kötve, abból a dicsőséges fajból, a melyiknek olyan a
feje és nyaka, mint a legszebb kalekuti pulykának. Azt a párt, keleti
nagylelkűséggel, odanyujtá Blankának.
Blanka mosolygott és szivesen fogadta az adományt. Gondolta,
most már neki is gazdaságot kell majd alapítani; kezdetnek ez is jó.
Ciprianu nem várta be a hálakitörést; goromba szerénységgel
eltünt a szobából.
– No ángyikám, dörmögé Áron; maga sem sejti, micsoda nagy
dolgot nyert most el? Soha ebből a fajból Ciprianu még a
püspökének sem adott kakast jérczével együtt ajándékba. Most már
nyugodtan alhatunk a házában; úgy megvette a szívét. Ciprianu
kakasával keresztül mehetünk az egész oláh táboron. Ez olyan,
mintha pazsuránk volna.
Blanka nevetett. Tudta is ő, hogy mi az a pazsura? Olyan volt
valóban, mint egy szent: égő parázs fölött járt, kelt s még csak a
ruhája szegélyét sem égette meg.
Annak az egy «szónak» pedig hej de sok özvegy, árva volt a
kisérete!
Blanka ki volt fáradva; alig várta, hogy lefekhessék.
Ciprianu háza jó el volt rendezve vendéglátáshoz, a hogy
nemeseké szokott lenni az oláhoknál. A népies, nemzeties meg van
tartva náluk; de finomság és bőség mutatja az előkelőt.
Mennyezetes nyoszolyák voltak mindenki számára, csak a háziúr
maga aludt, ős szokás szerint, künn a konyhaajtó előtt
keresztülfekve, bundájába takarózva, mellette a duplapuskája.
A benyilóban volt két ágy; azokba Blanka és Zenóbia feküdtek s a
konyha melletti szobában Áron és Manassé.
Mindenki lepihent az Úrban.
Azonban rendesen olyankor tud az ember legkevésbbé aludni,
mikor legjobban el van fáradva. Szokatlan volt Blankának az ilyen
mezei lakban az éj, a mi nem oly csöndes, mint a városi éjszaka. A
sok kutya egyre ugat, az egyik elhagyja, a másik rákezdi. Majd meg
a kakasok jelentik, hogy «holnap» van már. Aztán rákezd egy egész
tyúkól kodácsolni. Valamelyik háremhölgy bizonyosan menyétről
álmodott. Benn a házban is élethangokat ad az álom világa, s az
ilyen fából épült házban minden keresztül hangzik. A házi gazda
álmában horkol és fujtat, álmodott ellenfelekkel veszekszik, tolvajt
akar fogni. Majd meg a szobatársné kezd el álmában nyöszörögni,
zokogni, s egyszer csak megszólal álmában magyarul, ki ébren egy
szót sem akart tudni e nyelven s suttogja szerelmesen: «Oh kedves
Dávid! Ne hagyj itt. Ölelj meg!» Aztán reszketve nyög, mint egy
haldokló.
Blanka szeméből mind kiment az álom.
Csak egy deszkafal választá el Manassétól, ki egy ágyon feküdt
Áronnal. Ha Blanka a deszkafalhoz érteté ajkait, és túlfelől Manassé,
csókot válthattak egymással. Blanka egyre nyugtalankodni hallá
Manassét, mintha nehéz küzdelemben volna valakivel. Beszélt,
vitázott, bizonyosan álmában.
«Nem. – Nem bocsátalak el – Egész hazámat megfürösztöd a
vérben… egész nemzetemet keresztül viszed a tűzön:… de az én kis
szigethazámat nem hagyom tőlem elvenned!… Azt Te magad
körülvetted szikláiddal… benépesítetted szelid békés néppel… Nekem
ez utolsó menedékem az özönvízben… Odaviszem nőmet… Add
vissza azt nékem a Te erős kezedből… Küzdök Veled! harczolok
Veled… Nem rázhatsz le Magadról… Nem bocsátalak el Tégedet, míg
meg nem áldasz engemet!…»
S az álomküzdelemnek ököl- és könyökdöféseit mind a szegény
Áron oldal bordáinak kellett elviselni, ki, midőn megsokallta végre,
felrázta öcscsét álmából s fülébe dörmögé:
– Kivel küzdesz így öcsém?
– Az Istennel! sóhajta fel Manassé.
– Miként Jákób El-Bethelben?
– S nem eresztem el «Őt», míg meg nem áld: miként Jákóbot El-
Bethelben.
– Vigyázz! Mert kificzamítja csipőcsontodat!
– Teheti.
Azzal Manassé is a deszkafal felé fordult. Blanka is. Csak két
ujjnyi tölgyfalap volt közöttük. Akkor aztán elaludtak.
Az «Úr» pedig mondá fölöttük: «Én vagyok a mindenható erős
Isten! Növekedjél és sokasodjál. Nép és népeknek gyülekezete
származzék tetőled! Mert ha Isten ellen diadalmas voltál, az emberek
ellen is diadalmas leszesz…»
XL.
Novemberi reggel későn hajnallik: a háznál mindenki talpon volt
már, mikor Blanka fölébredt.
Manassé azzal örvendezteté meg, hogy innentul az útat nem
szekéren fogják folytatni, hanem lóháton, a minek Blanka úgy őrült,
mint a gyermek.
(Ezért volt a három ló egyuttal fel is nyergelve.)
A külső szobában gazdag reggeli várta. Forró tejszín, bálmos,
paprikás szalonna, hófehér havasi méz, csupa virágillatú, s
szűknyakú «egyesekben» felrakott gyümölcsszeszfélék, fenyőhéjba
takart kászuturó, gesztenyeizű baraboly; olyan étkek, a miket Blanka
először izlelt életében s azonnal meg is szeretett. A házi gazda örült
ennek nagyon. S a mit vendégei meghagytak az asztalon, azt még
összecsomagolta számukra az utitáskájukba, megmagyarázva
Blankának, hogy erre nagy szükség lesz.
Blanka úgy vette észre, hogy az oláh nyelv olyan, hogy ha az
ember nagyon hallgatja, hát megérti. Annyit megértett ő is, hogy a
legközelebbi állomásuk lesz Szent-László; ott a domnu rektor lesz a
gazdájuk, a ki pedig «vegetarianu».
Majd megtudja Blanka azt is, hogy mit tesz ez?
Mikor a lovaikat nyergelték, azt mondá Áron Manassénak:
– No, öcsém, most már csak megmondom neked, hogy ez az én
kurta nyakam ugyan nem érdemli, hogy nyaknak neveztessék; de
már a milyen, olyan, ezuttal azt a te szentecskédnek köszönhetem,
hogy megmaradt épségben; mert tudd meg, hogy ez a Ciprianu, a
kinek a házában most megháltunk, mind egész háza népével együtt
a legelkeseredettebb agitátor, s azonkívül én rám különös oka van
haragudni. De a te bálványod az első pillanatra kicsavarta kezéből a
fegyvert.
– De nem történhetik-e meg rajtunk, hogy majd a kit mellénk fog
rendelni a hegyeken át vezetőül, az visz bele valami kelepczébe?
– Nem. A tulajdon leánya fog bennünket vezetni. Az ugyan
elvesztene engem egy kanál vízben; de a te Blankádért keresztül fog
bennünket vinni a tűzön is. Öcsém, már benne vagyunk. El ne
áruljuk az asszony előtt.
Blanka nevetett az örömtől, mikor fennült a nyeregben. Eleinte
különösnek találta, hogy férfimódra kell megülni a mokány paripát;
hanem aztán, mikor a délczeg Zenóbiát meglátta így lovagolni,
kedvet kapott hozzá.
A jámbor havasi ló úgy ment alatta, mintha dajka ringatná
bölcsőben.
A két hölgy előre lovagolt, a két férfi még hátramaradt az utánuk
szaladó házigazdával még egy rájuk tuszkolt búcsukortyot inni.
Mikor az erdő szélébe értek, Blanka megszólítá társnéját.
– Zenóbia, kérlek, tegezz engem s beszélj velem magyarul. Az
éjjel álmodban hallottalak így beszélni.
A leány visszarántotta paripáját s keresztet vetett magára. Aztán
súgva mondá:
– A szent szűzre kérlek, szent asszony, ne áruld el, a mit hallottál
tőlem; s ne kérdezz erről többet.
Azzal tovább léptettek egymás mellett. Az út hegynek vitt fel.
– Szólj! Messzire fogsz te bennünket elvezetni?
– A hogy illik. Az apám birtokának a határaig.
– S meddig terjed a te apádnak a birtoka?
Zenóbia egy távol meredő hegycsúcsra mutatott, a mit a reggeli
ködfátyol takart még.
– Annak a hegynek a szélső oldaláig.
– Az odáig mind az övé? kérdé elbámulva Blanka.
– Nagy darab szegénység! Van rajta tüzelő fa, kecskenyáj,
sertéskonda, rongyos kalyibák és szurtos emberek. Sok a semmiből.
Egy úr, a ki mérföldekig folyvást a saját birtokán jár; hanem azért
azt a kis darab földet, a mi abban kenyeret terem, maga szántja!
Blanka gyönyörét találta ebben az utazásban. A szép zöld mező
lepve volt már az őszi dértől, de a mint feljött a nap odáig, a hogy a
hegy árnyékot vetett, egyszerre zöld lett a gyep, az árnyék
megmaradt fehérnek. S a zöld gyepen virítottak a rózsaszinű
kökörcsinek.
Az út felvitt a hegyoldalnak, ünnepélyes templomi csendességű
szálerdő fogadta az utazókat, melyben, mint a misemondó
antiphonája, hangzott fel a vadmadarak egymásnak felelgető
kiáltása. Egy pár gyönyörű vad páva szerelmi ömledezései közepett
hagyta meglepni magát a lovaglóktól, s aztán felrebbenve, meg
leszállva előttük, sokáig folyton az útjokban maradt, mintha
előhirnöke volna jövetelüknek.
Mentül feljebb haladtak, annál elevenebb lett az erdő. Vegyülni
kezdett a levélvesztett lombfa, az örökzöld fenyővel. A borókabozót
sűrűn fedte már az aljat, s azon tarkatollú madárcsoport kergetőzött.
Egy ilyen bozótból egész konda disznót vert föl az utazó csoport.
Azok nagy röfögve vágtattak odább. Zenóbia nem mondta meg
Blankának, hogy azok vaddisznók voltak; engedte őt csodálkozni
rajta, hogy ime egy egész konda – pásztor nélkül!
A hegyoldal még meredekebb lejtőre vált; a paripák ugyancsak
feszítettek a hegynek felmászásában. Holmi síkon termett ló rég
kidőlt volna ebből, ezek még csak meg sem izzadtak bele.
Végre fölértek a hegytetőre s ott egyszerre az erdő is megnyilt.
Sajátszerű tájkép tárult eléjük.
Északnak a fensíkot egy kokojszás foglalta el. Az egy ingovány a
hegymagason, még magasabban fekvő hegyek tengerszemétől
táplálva; fölül rőt magas fűvel benőtt láp, mely közt gyér vörös
fenyőfák láthatók; a bürű alatt feneketlen dágvány, mely elnyeli a
rátévedett embert és állatot. Szomorú, ijesztő kép; a sás érett
bugáitól rókafakó az egész mező. Délnek pedig egy fiatal fenyves,
mely valami őserdő helyén támadt, a mit tán húsz év előtt a vihar,
mint egy kaszavágással aratott le. A vén fa rohává lett rég s a húsz
éves sarj üde hajtással magasodik fel sűrűn, buján, áttörhetlenül.
Csak egy csapás visz rajta keresztül.
A fenyők aljában virítanak a havasi nefelejtsek, az erdők örök
virága.
Itt csak egyesével lehet előre haladni. Zenóbia elől lovagolt,
nyomában Blanka. A két férfi messze hátul maradt. Ők nehezebb
terhe voltak a lónak.
Egyszerre Blankának valami furcsa alak vonta magára a
figyelmét.
Olyanforma, mint egy ember: két lába, két keze. Egészen
bundába van öltözve. Emlékezett rá, hogy valamikor,
állatseregletben, látott ilyenforma alakot, csakhogy az ott mogorva,
kedvetlen pajtás volt. Itt pedig jókedvű ficzkó. Tánczol, mórikál,
bukfenczet hány; hintálja magát a fa ágán két hosszú karjánál fogva.
Furcsa gömbölyű fülei, felnyitott szája nevető kifejezést adnak tréfás
ábrázatjának.
Eszében sem volt, hogy megijedjen tőle.
Zenóbia a nyergében maga előtt keresztül fektetett dupla
puskának a sárkányait csendesen felvonta. Blanka pedig gyermeteg
örömmel kiáltá a hátul lovagló Manassénak:
– Nézd csak, Manassé! siess! Milyen furcsa bohó állat van itt!
Manassé sietett is aztán.
A tréfás fenevad erre a kiáltásra, mint a mókus, oly ügyesen
futott fel arra a fiatal fenyősudarra, a minek az alsó ágán himbálta
magát addig, s mikor legtetejében volt, hogy a hajló sudar elkezdte
nehéz terhét himbálni: tökéletes naiv humorú pofával tekinte alá,
mintha egészen Blankának produkálná magát. Egy szörnyeteg, mely
pajkos gyerkőczöt mimel.
S az utazóknak épen azon fa alatt kellett elmenniök; mert kétfelől
áttörhetlen bozót terült.
Blanka kiváncsi mosolygással nézett fel a feje fölött hintázó erdei
bohóczra.
Az pedig megvárta, míg mind a négy lovas elhaladt alatta, akkor,
hogy megmutassa a nézőknek, hogy mit tud még, hirtelen belevágta
rettentő körmeit a fa háncsába, s egyszerre aláeresztve több mázsás
termetét, egy pillanat alatt egész a tövéig meztelenre hántotta a
fiatal fenyőfát. Blanka csak akkor sápadt el az ijedtségtől, mikor ez
iszonyú erőmutatványt látta.
– Ne félj semmit, mondá neki Zenóbia, a medve csak játszik.
S azzal a szörnyeteg befutott a bozót közé: a sürű fenyőgeszt,
mint a vetés kalásza, nyitott utat iszonyú termetének.
Zenóbia mondott Blankának valamit.
– A ki boldog, az nem tud félni! Lám, én a madár felrebbenésétől
is megijedek.
Az út most egyszerre megkönnyült. A hegyháton visz az végig:
folyvást sima gyepen, mohos mezőkön, miket egész mesgyékben
fedett az áfonya most érő piros és kék édes bogyóival. A
hegygerinczről messze be lehetett látni a vidéket. Hasonló volt a
látvány a tengeréhez. Itt a föld vet hullámokat, ott a víz. Itt a zöld
fenyőlomb takar egy alatta élő világot, ott a zöld hullám; – itt távol
házikók jelzik csak, hogy e magányban ember is él, mint amott a
fehérlő vitorlák. Olyan vidék, a melyben hegytetőről sem látni falut.
Már délponton állt a nap, a mint a hosszú hegygerincz végét
elérték. Ott egy meredek bérczfal állta el az útat, s annak a lábában
kellett a völgybe alászállni.
E pontról már megtudta mutatni Zenóbia az utasoknak a
«Monasteria» hegyormát, mely a «Tordai hasadék» fölött uralg. Ezen
a bérczfalon keresztül kell lenni egy átjárásnak, mely a Hesdád-völgy
katlanába átvezet.
Messziről hozzájárulhatlannak látszik az; de itt a «Mikus bán»
várromjai alatt lakik egy ember, a ki jól ismeri ezt a merész utat; a
nép a «Vén Matuzsálem»-nek hívja. Egy «magyar zsidó».
Blanka kétkedve tekinte Manasséra.
A helyett Áron felelt meg.
– Igen. Egy elzüllött maradéka az erdélyi «Szombatosok»-nak.
Blanka rejthetlen kiváncsisággal nézett Manasséra. Ez pedig
megszokta már hölgye tekintetéből kiolvasni a gondolatban ejtett
kérdést.
– Te azt hitted ugy-e, hogy a «magyar zsidó» csak gúnynév,
melylyel minket illetnek: egy Istent vallókat. Magyar zsidók valóban
léteznek itt Erdélyben, egész községszámra; de elszórva is laknak
köztünk s azok tartják magukat az igazi zsidóknak; minket csak
Sadduceusoknak fogadnak el.
– Majd látni fog egy eredeti példányt belőlük ángyikám; biztatá őt
Áron. Én rég ismerem az öreg Mathusalemet; úgy tudom, hogy egy
unokája is van; ha még meg nem házasodott.
E közben az utazó társaság egész a sziklafalig ért, mely útjokat
elzárni látszott. Hatalmas, égnek meredő, juraképződési mészfal volt
az, mely a többi hegycsoportot kettévágni látszott. A fensík véget ért
előtte, s meredeken hanyatlott alá; beborítva egész a völgy mélyéig
sűrű borókával. A fensík magasán állt még egyetlen vén bükkfa: az
utolsó abból a lomberdőből, mely valaha a hegyormot koronázta; sok
százéves lehetett már s még mindig tartotta magát. Vastag gyökerei
messze elnyúltak s belekapaszkodtak a sziklába. – E tölgyfa mögött
látszott a sziklafalban egy barlang szája: góthidomú csúcsívvel s
előtte egy öblös medencze volt, melynek csak a fenekén látszott
valami maradvány nyirok.
Ide érve, Zenóbia leszökött a lováról, s kirántva annak a fejéből a
zablaszerszámot, s megeresztve a terhelőjét, azt mondá Blankának:
– Most itt a «csodakútnál» pihenőt tartunk, falatozunk egyet, a
lovainkat legelni hagyjuk s aztán megitatjuk.
– Miből? Itt nincs viz.
– Nincs. De nem sokára lesz. Azért csodakút ez. Minden két
órában felbuzog a forrás s megint visszahúzódik.
Blanka hitetlenül rázta a fejét, s mert nem volt képes elhinni,
hogy abban a medenczében mai nap több viz legyen, mint a mennyi
már van: a markába merített belőle s megitatta vele – az ajándékba
kapott jérczéjét, kakasát.
Ez alatt Áron bátya kiteríté az Isten adta szép zöld abroszra az
utitáska élelmi készletét s ezüstveretes kését elővéve, elkezdett
mindenki számára felszelni a komoly csemegéből.
Blanka azt mondá, hogy ő inkább szomjas, mint éhes.
Zenóbia mosolyogva mondá:
– A szent asszonyoknak minden kivánsága beteljesül, még a
szikla is megindul szavukra. Halld csak: a forrás már közelít.
A barlang szája bugyborékoló korgást kezde hallatni, zuhogó
hullám böffenései hangzottak az üreg mélyéből elő s percz mulva
rögtöni lökéssel bugygyant ki a barlang torkából az üde
kristályzuhatag, ellepve a medenczét, s aztán túlömölve rajta. A
bőséges forrás szakadatlan rohamban tódult elő a sziklanyilásból s
aztán alább omolva, szikláról-sziklára zúdult szökellve a völgybe alá.
Blanka örömében tapsolt a szép tüneménynek. Azt mondta, hogy
ha ő nagy úr volna, ide építtetne magának egy házat s aztán elnézné
azt a csodaforrást reggeltől estig s nem kivánna más mulatságot.
Nevetett a gyönyörtől.
És meglehet, hogy ez volt az egyetlen nevető hang, a mit azon a
napon egész Erdélyből hírül vihettek az égnek az Úr angyalai.
Áron bátya tüzet is rakott targalyból s megtanította ángyikáját,
hogyan kell szalonnát pirítani kenyérrel? a mi nem csekély tudomány.
Félóra mulva a forrás megszünt a sziklából kiömleni. Odabenn
nyeldeklő, fuldokló hangok hallatszottak: a zuhatag nem tánczolt
tovább a sziklákon, s egy percz mulva a medenczében maradt vizet
is visszanyelte a sziklatorok: a forrás újra eltünt.
Valami azonban megzavarta Blankának az örömét; nehány
darázs. Abból az aristokratikus fajtából, a mi az erdőket lakja, s
négy-öt képes egy lovat megölni. A csemege szagára jöttek elő
valahonnan s mind Blanka fejét dongták körül, ő pedig sikoltozott
tőlük.
Áron segíteni akart az ángyikáján. Ezek a vakmerő állatok
bizonyosan ebben az odvas bükkfában laknak. Azokat ő kipusztítja
valahogy.
Meg is találta az odujukat, s azzal csóvát készített, hogy kifüstölje
őket belőle.
A mint azonban a lángoló gazcsutakot bedugta a fölfedezett
darázsoduba, abban a pillanatban, mint a gőzkatlan kürtőjének
bömbölése, oly robaj hangzott a bükkfa belsejében s egyszerre csak
kicsapott a láng az élőfa legeslegtetején.
Az tele volt már százados pudvával, a mi a lángtól egyszerre
végtől-végig föllobbant s akkor elkezdett az óriási szálfa, mint egy
rengeteg fáklya égni felülről.
– Mit tettél? kiálta Zenóbia felugorva fektéből. Tudod-e, hogy
most megölted az apámat, s fölgyujtottad azt a házat, a miben az
éjjel aludtál?
Blanka azt hitte, hogy ez csak tréfabeszéd; de a mint Áron
boszús arczára s Manassé összevont szemöldeire tekintett,
észrevevé, hogy a leány szavainak értelme van, a mit a férfiak föl
tudtak fogni.
– Most már gyorsan a lovaitokhoz! Kiálta Zenóbia. Egy percznyi
idő sincs. Én futok az apámhoz! Ti igyekezzetek a patak medrén a
völgybe leszállni. A zsidó átvezet a Hesdád völgyén benneteket. Itt
ne találjon benneteket az éjszaka! – Oh, Áron! Az Isten bocsássa
meg neked, a mit én velem cselekedtél!
A lánggal égő fa oduiból bagolysereg, mókus-család, kigyóivadék
menekült repülve, mászva, kunkorogva szanaszéjjel, de gyorsabban
azok sem menekültek, mint utasaink. Zenóbia vágtatott vissza azon
az úton, a melyen idejöttek: a magára hagyott két férfi pedig
középre vette a hölgyet s úgy indult neki az elátkozott útnak, melyet
a csodaforrás száraz medre képezett előttük.
És Blanka mindebből nem értett semmit.
Mi nagy baj származhatik abból, hogy egy vén, odvas bükkfa
kigyulladt?

XLI.
Az a völgybe levivő út kegyetlenül megviseli a lovast. A ló
szikláról-sziklára lép, a zsurmalék megindul a lába alatt; néhol egyik
partról a másikra kell átugornia; a lovas nem vezeti a mént, maga
esze és szeme után jár az, valódi hű társa a bajban.
Különben is sietni kellett, a nap már öt óra után lemegy, s nekik
addig a Hesdád-völgyben kell lenniök.
Zenóbia oly óvatosan vezette őket a hegyhátakon keresztül, hogy
minden közbeeső falvat elkerültek: Szelistye, Indal – csak a távol
harangszó volt sejthető.
Egy órai folytonos völgynek alászállás után jutottak el az első
pihenőig.
Egy völgykatlanba épült ház volt az, mely mögött sövénynyel
bekerített szántóföldek látszottak, körülpalánkolt ólak a
hegyoldalban, s tövissel elsánczolt szénaboglyák.
– Itt vagyunk már! Mondá Áron. Ez a mi zsidónk háza.
Valamivel különb épület volt az a többi oláh kunyhóknál, de
Ciprian lakával nem vetekedett. A ház eresze tele volt galambokkal;
azok a magyar zsidó kedvencz majorsága. A ház udvarán látszott a
lombsátor, borókából építve; a ház keleti oldalán egy kis szoba,
mintegy kinövése az egész épületnek, mely fehérre volt meszelve, s
aztán vörös festékkel irombára petyegetve. – Kutya nem volt a
háznál; azt a zsidó nem tart, mert megharapott egyénnek fizetéssel
tartozik. Hanem egy oláh suhancz őgyelgett ott az udvaron; arra
rábízták, hogy jártassa meg a lovakat.
Blankát azonban ölben kellett a ház küszöbéig vinni, mert a körül
oly nagy volt a sár, hogy abban a női lábbelivel czélhoz jutni nem
lehetett.
Áron tudta már itt a járást. Az ajtó, mely a szobába vezetett, be
volt zárva, s kilincse nem volt kívülről. Bezörgetett rajta ököllel.
– Mi kell? hangzott belülről.
– Ereszsz be az ajtón.
– Nyisd ki, ha tudod.
Áron pedig tudott ahhoz. Ha kilincs nem volt az ajtón kivülről, de
volt rajta egy lyuk, azon bogra kötött zsineg volt kidugva, azt ha
meghúzta az ember, a závár ütközője felbillent s be lehetett lépni a
szobába.
Ott pedig egészen sötét volt. Az ablaktáblák betéve; hanem egy
vékony faggyúgyertya égett az asztalon s az olyan sötétséget
terjesztett maga körül, hogy a bennlevők ki nem vehették tőle
egymást, kivált a kik a verőfényről léptek be egyszerre.
– Jézus! Kiáltá föl Blanka. Ide kell bemennünk S azzal félénken
huzódott vissza a tornáczra, Manassét is visszatartóztatva. Csak Áron
lépett be. Benn a sötét szobában czihelődött valami.
– Hát fiam, Naftali, miért nem akartad kinyitni az ajtót? szólítá
meg Áron azt a valamit.
– Azért, mert ma huszonnegyedik Tizri van; felelt ridegen a
valami.
– S mi van azon a huszonnegyedik Tizrin?
– A Garizim hegyén való ünnep.
– S azon a napon igazhitü zsidó még az ajtó kilincséhez sem
nyul, ugy-e bár?
– Te tudod.
– Hát nem jösz elő a sutból, Naftali.
– Mindjárt, csak bekötöm az arczomat.
– S miért kötöd be az arczodat, Naftali?
– Azért, mert idegen asszonyi állat hangját hallom.
– S neked még most sem szabad idegen asszonyi állat arczát
látnod?

You might also like