SlideShare a Scribd company logo
Programming Wcf Services 4th Edition Juval Lwy
Michael Montgomery download
https://ebookbell.com/product/programming-wcf-services-4th-
edition-juval-lwy-michael-montgomery-5238676
Explore and download more ebooks at ebookbell.com
Here are some recommended products that we believe you will be
interested in. You can click the link to download.
Programming Wcf Services 2nd Edition Second Edition Juval Lowy
https://ebookbell.com/product/programming-wcf-services-2nd-edition-
second-edition-juval-lowy-2399036
Programming Wcf Services Juval Lowy
https://ebookbell.com/product/programming-wcf-services-juval-
lowy-37208962
Professional Wcf Programming Net Development With The Windows
Communication Foundation Scott Klein
https://ebookbell.com/product/professional-wcf-programming-net-
development-with-the-windows-communication-foundation-scott-
klein-4106444
Programming Net 35 Build Ntier Applications With Wpf Ajax Silverlight
Linq Wcf And More 1st Edition Jesse Liberty
https://ebookbell.com/product/programming-net-35-build-ntier-
applications-with-wpf-ajax-silverlight-linq-wcf-and-more-1st-edition-
jesse-liberty-1021740
Programming Languages And Systems 31st European Symposium On
Programming Esop 2022 Held As Part Of The European Joint Conferences
On Theory And Practice Of Software Etaps 2022 Munich Germany April 27
2022 Proceedings Ilya Sergey
https://ebookbell.com/product/programming-languages-and-systems-31st-
european-symposium-on-programming-esop-2022-held-as-part-of-the-
european-joint-conferences-on-theory-and-practice-of-software-
etaps-2022-munich-germany-april-27-2022-proceedings-ilya-
sergey-44887738
Programming 101 Learn To Code Using The Processing Programming
Language 2nd Edition 2nd Jeanine Meyer
https://ebookbell.com/product/programming-101-learn-to-code-using-the-
processing-programming-language-2nd-edition-2nd-jeanine-meyer-46238180
Programming 101 The How And Why Of Programming Revealed Using The
Processing Programming Language Jeanine Meyer
https://ebookbell.com/product/programming-101-the-how-and-why-of-
programming-revealed-using-the-processing-programming-language-
jeanine-meyer-46318424
Programming And Gui Fundamentals Tcltk For Electronic Design
Automation Suman Lata Tripathi
https://ebookbell.com/product/programming-and-gui-fundamentals-tcltk-
for-electronic-design-automation-suman-lata-tripathi-46318712
Programming With Openscad A Beginners Guide To Coding 3dprintable
Objects 1st Edition Justin Gohde
https://ebookbell.com/product/programming-with-openscad-a-beginners-
guide-to-coding-3dprintable-objects-1st-edition-justin-gohde-46410140
Programming Wcf Services 4th Edition Juval Lwy Michael Montgomery
Programming Wcf Services 4th Edition Juval Lwy Michael Montgomery
Programming Wcf Services 4th Edition Juval Lwy Michael Montgomery
4TH EDITION
Programming WCF Services
Juval Lowy & Michael Montgomery
Boston
Programming WCF Services
by Juval Lowy and Michael Montgomery
Copyright © 2016 Juval Lowy and Michael Montgomery. All rights reserved.
Printed in the United States of America.
Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472.
O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are
also available for most titles (http://safaribooksonline.com). For more information, contact our corporate/
institutional sales department: 800-998-9938 or corporate@oreilly.com.
Editors: Brian MacDonald and Rachel Roumeliotis Interior Designer: David Futato
Production Editor: Melanie Yarbrough Cover Designer: Randy Comer
Proofreader: Jasmine Kwityn Illustrator: Rebecca Demarest
Indexer: WordCo Indexing Services
December 2015: Fourth Edition
Revision History for the Fourth Edition
2015-11-04: First Release
See http://oreilly.com/catalog/errata.csp?isbn=9781491944837 for release details.
The O’Reilly logo is a registered trademark of O’Reilly Media, Inc. Programming WCF Services, the cover
image, and related trade dress are trademarks of O’Reilly Media, Inc.
While the publisher and the author have used good faith efforts to ensure that the information and
instructions contained in this work are accurate, the publisher and the author disclaim all responsibility
for errors or omissions, including without limitation responsibility for damages resulting from the use of
or reliance on this work. Use of the information and instructions contained in this work is at your own
risk. If any code samples or other technology this work contains or describes is subject to open source
licenses or the intellectual property rights of others, it is your responsibility to ensure that your use
thereof complies with such licenses and/or rights.
978-1-491-94483-7
[LSI]
Table of Contents
Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii
1. WCF Essentials. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
What Is WCF? 1
Services 3
Service Execution Boundaries 4
WCF and Location Transparency 5
Addresses 5
TCP Addresses 6
HTTP Addresses 7
IPC Addresses 7
MSMQ Addresses 8
WebSocket Addresses 8
UDP Addresses 8
Contracts 8
The Service Contract 9
Hosting 13
IIS Hosting 14
Self-Hosting 15
WAS Hosting 21
Custom Hosting in IIS/WAS 21
Choosing a Host 22
Bindings 23
The Common Bindings 24
Choosing a Binding 26
Additional Bindings 27
Using a Binding 30
Endpoints 30
iii
Administrative Endpoint Configuration 31
Programmatic Endpoint Configuration 35
Default Endpoints 37
The Configure() Method 40
Metadata Exchange 43
Metadata over HTTP-GET 44
The Metadata Exchange Endpoint 47
The Metadata Explorer 54
More on Behavior Configuration 56
Client-Side Programming 58
Generating the Proxy 59
Administrative Client Configuration 64
Programmatic Client Configuration 71
The WCF-Provided Test Client 72
Programmatic Versus Administrative Configuration 75
Configuration Policy 75
WCF Architecture 76
Host Architecture 77
Working with Channels 78
The InProcFactory Class 80
Transport-Level Sessions 84
Transport Session and Binding 84
Transport Session Termination 85
Reliability 86
Bindings, Reliability, and Ordered Messages 87
Configuring Reliability 88
Requiring Ordered Delivery 89
2. Service Contracts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Operation Overloading 93
Contract Inheritance 96
Client-Side Contract Hierarchy 97
Service Contract Factoring and Design 101
Contract Factoring 101
Factoring Metrics 103
Contract Queries 105
Programmatic Metadata Processing 106
The MetadataHelper Class 109
3. Data Contracts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Serialization 115
.NET Serialization 117
iv | Table of Contents
The WCF Formatters 119
Data Contract via Serialization 122
Data Contract Attributes 123
Importing a Data Contract 125
Data Contracts and the Serializable Attribute 129
Inferred Data Contracts 130
Composite Data Contracts 131
Data Contract Events 133
Shared Data Contracts 136
Data Contract Hierarchy 137
Known Types 138
Service Known Types 140
Multiple Known Types 141
Configuring Known Types 142
Data Contract Resolvers 143
Objects and Interfaces 155
Data Contract Equivalence 157
Serialization Order 158
Versioning 160
New Members 161
Missing Members 162
Versioning Round-Trip 166
Data Contract Factoring and Design 169
Data Contract Design 169
Data Contract Factoring 169
Operation Factoring 181
The Data Transfer Object Pattern 183
Enumerations 184
Delegates and Data Contracts 186
Generics 187
Collections 191
Concrete Collections 192
Custom Collections 194
The CollectionDataContract Attribute 194
Referencing a Collection 196
Dictionaries 196
4. Instance Management. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Behaviors 201
Per-Call Services 203
Benefits of Per-Call Services 204
Configuring Per-Call Services 204
Table of Contents | v
Per-Call Services and Transport Sessions 206
Designing Per-Call Services 206
Choosing Per-Call Services 209
Per-Session Services 209
Configuring Private Sessions 210
Sessions and Reliability 215
The Session ID 216
Session Termination 218
Singleton Service 218
Initializing a Singleton 220
Choosing a Singleton 223
Demarcating Operations 223
Instance Deactivation 226
Configuring with ReleaseInstanceMode.None 227
Configuring with ReleaseInstanceMode.BeforeCall 228
Configuring with ReleaseInstanceMode.AfterCall 229
Configuring with ReleaseInstanceMode.BeforeAndAfterCall 229
Explicit Deactivation 230
Using Instance Deactivation 231
Durable Services 231
Durable Services and Instance Management Modes 232
Instance IDs and Durable Storage 233
Explicit Instance IDs 234
Instance IDs in Headers 236
Context Bindings for Instance IDs 239
Automatic Durable Behavior 245
Throttling 252
Configuring Throttling 255
5. Operations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
Request-Reply Operations 261
One-Way Operations 262
Configuring One-Way Operations 262
One-Way Operations and Reliability 263
One-Way Operations and Sessionful Services 263
One-Way Operations and Exceptions 264
Callback Operations 266
The Callback Contract 267
Client Callback Setup 268
Service-Side Callback Invocation 272
Callback Connection Management 275
The Duplex Proxy and Type Safety 278
vi | Table of Contents
The Duplex Factory 281
Callback Contract Hierarchy 283
Events 285
Streaming 289
I/O Streams 289
Streaming and Binding 290
Streaming and Transport 291
6. Faults. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
Error Isolation and Decoupling 293
Error Masking 294
Channel Faulting 295
Fault Propagation 299
Fault Contracts 301
Fault Debugging 305
Faults and Callbacks 312
Error-Handling Extensions 315
Providing a Fault 316
Handling a Fault 319
Installing Error-Handling Extensions 322
The Host and Error Extensions 325
Callbacks and Error Extensions 329
7. Transactions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333
The Recovery Challenge 333
Transactions 334
Transactional Resources 335
Transaction Properties 335
Transaction Management 337
Resource Managers 341
Transaction Propagation 341
Transaction Flow and Bindings 341
Transaction Flow and the Operation Contract 343
One-Way Calls 345
Transaction Protocols and Managers 345
Protocols and Bindings 346
Transaction Managers 348
Transaction Manager Promotion 350
The Transaction Class 352
The Ambient Transaction 352
Local Versus Distributed Transactions 353
Transactional Service Programming 354
Table of Contents | vii
Setting the Ambient Transaction 354
Transaction Propagation Modes 357
Voting and Completion 365
Transaction Isolation 369
Transaction Timeout 371
Explicit Transaction Programming 373
The TransactionScope Class 373
Transaction Flow Management 375
Non-Service Clients 383
Service State Management 384
The Transaction Boundary 385
Instance Management and Transactions 386
Per-Call Transactional Services 387
Per-Session Transactional Services 391
Transactional Durable Services 406
Transactional Behavior 408
Transactional Singleton Service 415
Instancing Modes and Transactions 418
Callbacks 419
Callback Transaction Modes 420
Callback Voting 422
Using Transactional Callbacks 422
8. Concurrency Management. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427
Instance Management and Concurrency 428
Service Concurrency Modes 428
429
ConcurrencyMode.Single
429
ConcurrencyMode.Multiple
433
ConcurrencyMode.Reentrant
Instances and Concurrent Access 436
Per-Call Services 436
Sessionful and Singleton Services 437
Resources and Services 438
Deadlocked Access 438
Deadlock Avoidance 439
Resource Synchronization Context 441
.NET Synchronization Contexts 441
The UI Synchronization Context 445
Service Synchronization Context 451
Hosting on the UI Thread 452
A Form as a Service 458
The UI Thread and Concurrency Management 461
viii | Table of Contents
Custom Service Synchronization Contexts 464
The Thread Pool Synchronizer 464
Replacing the I/O Completion Thread Pool 469
Thread Affinity 471
Priority Processing 473
Callbacks and Client Safety 477
Callbacks with ConcurrencyMode.Single 478
Callbacks with ConcurrencyMode.Multiple 479
Callbacks with ConcurrencyMode.Reentrant 479
Callbacks and Synchronization Contexts 480
Callbacks and the UI Synchronization Context 480
Callback Custom Synchronization Contexts 484
Asynchronous Calls 488
Requirements for an Asynchronous Mechanism 488
Proxy-Based Asynchronous Calls 489
Asynchronous Invocation 492
Polling or Waiting for Completion 494
Continuations 497
One-Way Asynchronous Operations 508
Asynchronous Error Handling 512
Asynchronous Calls and Transactions 515
Synchronous Versus Asynchronous Calls 516
Asynchronous Service Operations 517
9. Queued Services. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543
Disconnected Services and Clients 543
Queued Calls 544
Queued Calls Architecture 545
Queued Contracts 545
Configuration and Setup 546
Transactions 554
Delivery and Playback 554
Service Transaction Configuration 556
Nontransactional Queues 559
Instance Management 560
Per-Call Queued Services 561
Sessionful Queued Services 563
Singleton Service 566
Concurrency Management 567
Throttling 568
Delivery Failures 569
The Dead-Letter Queue 570
Table of Contents | ix
Time to Live 571
Configuring the Dead-Letter Queue 571
Processing the Dead-Letter Queue 573
Playback Failures 578
Poison Messages 579
Poison Message Handling 579
Queued Versus Connected Calls 584
Requiring Queuing 586
The Response Service 587
Designing a Response Service Contract 588
Client-Side Programming 592
Queued Service-Side Programming 595
Response Service-Side Programming 597
Transactions 598
The HTTP Bridge 602
Designing the Bridge 602
Transaction Configuration 603
Service-Side Configuration 604
Client-Side Configuration 606
10. Security. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 609
Authentication 609
Authorization 610
Transfer Security 611
Transfer Security Modes 612
Transfer Security Mode Configuration 614
Transport Security and Credentials 617
Message Security and Credentials 617
Identity Management 618
Overall Policy 618
Scenario-Driven Approach 619
Intranet Application Scenario 620
Securing the Intranet Bindings 620
Constraining Message Protection 628
Authentication 629
Identities 632
The Security Call Context 633
Impersonation 635
Authorization 643
Identity Management 650
Callbacks 651
Internet Application Scenario 652
x | Table of Contents
Securing the Internet Bindings 652
Message Protection 655
Authentication 660
Using Windows Credentials 662
Using the ASP.NET Providers 663
Identity Management 673
Business-to-Business Application Scenario 673
Securing the Business-to-Business Bindings 674
Authentication 674
Authorization 677
Identity Management 679
Host Security Configuration 679
Anonymous Application Scenario 680
Securing the Anonymous Bindings 680
Authentication 681
Authorization 681
Identity Management 681
Callbacks 682
No Security Scenario 682
Unsecuring the Bindings 682
Authentication 683
Authorization 683
Identity Management 683
Callbacks 683
Scenarios Summary 684
Declarative Security Framework 684
The SecurityBehaviorAttribute 685
Host-Side Declarative Security 693
Client-Side Declarative Security 695
Security Auditing 702
Configuring Security Audits 703
Declarative Security Auditing 706
11. The Azure Service Fabric. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 709
Why Azure Service Fabric 709
An Integrated Platform 710
Design Consistency 710
Programming Model Consistency 711
Future Compatible 711
Preparing for the Service Fabric 713
ServiceModelEx.ServiceFabric 713
Configuring the Service Fabric 714
Table of Contents | xi
IT Operations 714
Development 716
Both 718
Programming the Service Fabric 723
The Service Programming Model 724
Reliable Services 724
Reliable Actors 734
State Management 737
Hosting 745
The Client Programming Model 746
Modeling the Service Fabric 756
Modeling Approach 757
Modeling Reliable Services 758
Modeling Reliable Actors 761
Modeling Hosting 770
Testing 771
A. Introduction to Service Orientation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 779
B. Headers and Contexts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 795
C. Discovery. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 819
D. Publish-Subscribe Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 883
E. Generic Interceptor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 911
F. WCF Coding Standard. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 929
G. ServiceModelEx Catalog. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 943
Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 969
xii | Table of Contents
Preface
On the software time scale, WCF is ancient. In August 2001, I first learned the details
of a Microsoft effort to rewrite COM+ using managed code. Nothing much happened
after that. Then, during a C# 2.0 Strategic Design Review in July 2002, the remoting
program manager outlined in broad strokes plans to rework remoting into something
that developers should actually use. At the same time, Microsoft was also working on
incorporating the new security specs for web services into the ASMX stack and
actively working with others on drafting a score of additional web services specs.
In July 2003, I was given access to a new transactional infrastructure that improved
on the deficiencies in transactional .NET programming. At the time, there was no
cohesive programming model that unified these distinct technologies. Toward the
end of 2003, I was privileged to be invited to join a small team of outside industry
experts and to participate in the strategic design review of a new development plat­
form codenamed Indigo. Some of the smartest and nicest people I ever worked with
were part of that team. Over the next two to three years, Indigo went through some
three generations of programming models. The final declarative, endpoint-driven
object model debuted in early 2005, was stabilized by August of that year, and was
named the Windows Communication Foundation (WCF). WCF was released in
November 2006 as part of .NET 3.0
On the software relevancy scale, WCF is a titan. It has all the correct elements
required to build a modern software system including the foundational pattern of all
modern software; an extensible, interception-based pipeline. It is the basis for the
upcoming Azure Service Fabric and it integrates with the Service Fabric as-is. In fact,
the previous three editions of this book showed how to implement all the elements of
the Service Fabric already. As such, WCF is as paramount as ever.
WCF has several facets, and is the only technology today that offers interoperability,
productivity and extensibility. It is the ultimate interoperability solution, an imple­
mentation of a long list of industry standards. To the distributed application devel­
oper, it is the easiest way of making remote calls and even queued calls. To the system
xiii
developer, it is the next generation of productivity-oriented features, such as transac­
tions and hosting, that provide off-the-shelf plumbing for applications. To the appli­
cation developer, it is a declarative programming model for structuring applications.
And to the architect, it is a tool for building service-oriented applications. WCF is, in
actuality, all of those, simply because it was designed that way—to be the unified
offering of Microsoft’s disparate technologies.
To me, WCF is a superior development platform, which to a large extent subsumed
raw .NET programming. All .NET developers should use WCF, regardless of their
application types, sizes, or industry domains. WCF is a fundamental technology that
provides an easy and clean way to generate services and applications in compliance
with what I regard as sound design principles. WCF was engineered from the ground
up to simplify application development and deployment and to lower the overall cost
of ownership. WCF services allow you to build service-oriented applications, from
standalone desktop applications to web-based applications and services to high-end
Enterprise applications.
How This Book Is Organized
This book covers the topics and skills you need to design and develop service­
oriented WCF-based applications, illustrating how to take advantage of built-in fea­
tures such as service hosting, instance management, concurrency management,
transactions, disconnected queued calls, security, and the new Windows Azure Ser­
vice Fabric. But in fact, this book is not about WCF. It is about modern software engi­
neering, using WCF as a medium to express these design ideas. The various concepts
disused in this book transcend technologies. So while the book shows you how to use
these features in WCF, it focuses on the “why” and on the rationale behind particular
design decisions. You’ll learn about not only WCF programming and the related sys­
tem issues, but also relevant design options, tips, best practices, and pitfalls. I
approach almost every topic and aspect from a software engineering standpoint,
because my objective is to make you not just a WCF expert, but also a better software
engineer. Armed with the insights this text provides, you can engineer your applica­
tions for maintainability, extensibility, reusability, and productivity.
This fourth edition has provided me with several opportunities: first, to catch up with
WCF in .NET 4.6 with its new features of parallel processing and configuration. Sec­
ond, I wanted to present the upcoming Azure Service Fabric, which is a fundamen­
tally disruptive technology because of the sort of applications it allows developers to
build and how it unifies development and operations. Third, I have had a few more
years’ worth of WCF techniques, ideas, and helper classes, as well as improvement of
the ideas I had in the previous editions. I believe this new material will make this edi­
tion valuable even to readers of the third edition.
xiv | Preface
This book avoids many implementation details of WCF and largely confines its cov­
erage to the possibilities and practical aspects of using WCF: how to apply the tech­
nology and how to choose among the available design and programming models. It
makes the most of what .NET 4.6 and the Service Fabric has to offer, and in some
respects is an advanced C# book as well.
In addition, the book contains many useful utilities, tools, and helper classes I have
written, collectively known as ServiceModelEx. My tools, helper classes, and attributes
aim at increasing your productivity and the quality of your WCF services. ServiceMo­
delEx is literally a small framework that sits on top of WCF and compensates for
some oversights in its design. ServiceModelEx also simplifies and automates certain
tasks. This book is as much about my tools, ideas, and techniques as it is about native
WCF, and my framework also demonstrates how you can extend WCF. Many readers
have told me that aside from the explanations in this book, ServiceModelEx is the
most valuable asset the book offers. I have also kept to my guideline that, in principle,
readers should not have to use all (or any part) of ServiceModelEx. In practice, Serv­
iceModelEx is your WCF power tools collection. You can also use each helper class,
utility, or framework individually, as there are few, if any, interdependencies.
Each chapter addresses a single topic and discusses it in depth. However, the chapters
often rely on those that precede them, so you should read the book in order.
Here is a brief summary of the chapters and appendixes in this book:
Chapter 1, WCF Essentials
This first chapter starts by explaining what WCF is, then describes essential WCF
concepts and building blocks (such as addresses, contracts, bindings, endpoints,
hosting, and clients) and key concepts such as reliability and transport sessions.
The chapter includes a discussion of the WCF architecture, which is really the
linchpin of all that follows in the subsequent chapters. This chapter assumes that
you understand the basic motivation and benefit of service orientation. If that is
not the case, you should first read Appendix A. Even if you are already familiar
with the basic concepts of WCF, I recommend that you give this chapter at least a
cursory reading, not only to ensure that you have a solid foundation, but also
because some of the helper classes and terms introduced here will be used and
extended throughout the book.
Chapter 2, Service Contracts
Chapter 2 is dedicated to the topic of designing and working with service con­
tracts. First, it covers some useful techniques for service contract overloading and
inheritance, as well as some advanced techniques. The chapter also discusses how
to design and factor contracts that cater to reuse, maintainability, and extensibil­
ity. It ends by showing you how to interact programmatically with the metadata
of the exposed contracts at runtime.
Preface | xv
Chapter 3, Data Contracts
Chapter 3 deals with how the client and the service can exchange data without
ever actually sharing the data type itself or using the same development technol­
ogy. In this chapter, you will see how to deal with some interesting real-life issues,
such as data versioning, and how to pass collections of items. This chapter also
extends the contract design and factoring discussion of Chapter 2 to data con­
tracts.
Chapter 4, Instance Management
This chapter answers the question of which service instance handles which cli­
ent’s request. WCF supports several service instance management, activation, and
lifetime management techniques, and your choices will have drastic implications
for scalability, performance, the programming model, and the business workflow.
This chapter presents the rationale behind each of the instance management
modes, offers guidelines on when and how to best use them, and also addresses
some related topics, such as durability and throttling.
Chapter 5, Operations
Chapter 5 deals with the types of operations clients can invoke on a service and
related design guidelines, such as how to improve on and extend the basic WCF
offering to support callback setup and teardown, manage callback ports and
channels, and provide for type-safe duplex proxies.
Chapter 6, Faults
This chapter discusses the best practices of error handling, enabling you to
decouple the client’s error handling from the service’s. When required, the chap­
ter shows how services can report errors and exceptions back to their clients,
since constructs such as exceptions and exception handling are technology­
specific and should not transcend the service boundary. This chapter also dem­
onstrates how you can extend and improve on WCF’s basic error-handling
mechanism.
Chapter 7, Transactions
This chapter begins by explaining the motivation for transactions in general,
then discusses the many aspects of transactional services: the transaction man­
agement architecture, transaction propagation configuration, the declarative
transaction support offered by WCF, and how clients can create transactions. The
chapter ends by discussing relevant design guidelines such as transactional ser­
vice state management and instancing modes.
Chapter 8, Concurrency Management
Chapter 8 first describes the powerful yet simple declarative way WCF offers for
managing concurrency and synchronization, both for the client and the service.
The chapter then presents more advanced aspects of concurrency management,
xvi | Preface
such as callbacks, reentrancy, thread affinity, and synchronization context, best
practices and guidelines for avoiding deadlocks, and asynchronous call manage­
ment. The chapter also explores the Task-based Asynchronous Pattern (TAP) and
how this style of asynchrony relates to WCF, highlighting best practice techni­
ques, as well as, discussing potential pitfalls.
Chapter 9, Queued Services
Chapter 9 shows how clients can queue up calls to services, thus enabling asyn­
chronous, disconnected work. The chapter starts by showing how to set up and
configure queued services, then focuses on aspects such as transactions, instance
management, and failures and their impact on both the business model of the
service and its implementation. It also presents techniques for streamlining
queues, call management, and several original design ideas (such as a queued
response service).
Chapter 10, Security
This chapter demystifies service-oriented security by breaking down this multi­
faceted task into its basic elements, such as message transfer, authentication, and
authorization. It also demonstrates how to provide security for key scenarios
such as intranet and Internet applications. Finally, it presents my framework for
declarative WCF security, designed to automate security setup and to considera­
bly simplify managing security.
Chapter 11, The Azure Service Fabric
Chapter 11 introduces you to the Azure Service Fabric. This chapter starts by
briefly explaining the value and rationale behind the new platform and continues
by presenting the Service Fabric’s many capabilities. The chapter ends by present­
ing ServiceModelEx.ServiceFabric, our operational Service Fabric that simpli­
fies how you prepare for the Service Fabric and allows you to deploy Service
Fabric code to any Windows environment that can host WCF services.
Appendix A, Introduction to Service Orientation
This appendix is designed for readers who want to understand what service ori­
entation is all about: it presents my take on service orientation and puts it in a
concrete context. The appendix defines service-oriented applications (as opposed
to mere architecture) and the services themselves and examines the benefits of
the methodology. It then presents the principles of service orientation and aug­
ments the abstract tenets with a few more practical points required by most
applications. In this appendix, I also share my perspective on where SOA and
WCF are heading.
Appendix B, Headers and Contexts
This appendix introduces two distinct techniques for enabling the client to pass
out-of-band parameters to the service, resulting in a custom logical context: you
Preface | xvii
will see how to use either the message headers or the context binding to achieve
this goal. This appendix also presents my helper classes, which greatly simplify
and encapsulate the required programming. These helper classes and custom
contexts are used in several places in the book.
Appendix C, Discovery
This appendix starts by describing the basic offering of service discovery and
availability announcements introduced in .NET 4.0. Discovery simplifies service
and client deployment and management, and allows for great volatility across
time and deployment sites. The appendix then shows some simple techniques
and helper classes you can use to streamline the programming model. The
appendix ends with our technique for TCP-based discovery that mimics regular
WCF discovery, benefiting from discovery even where UDP is disallowed.
Appendix D, Publish-Subscribe Service
Appendix D presents several techniques for implementing a publish-subscribe
event management solution. It starts with my framework, which lets you develop
a publishing and a subscription service in, at most, one line of code. The appen­
dix ends with a discovery-enabled publish-subscribe solution that requires no
explicit subscriptions steps.
Appendix E, Generic Interceptor
This appendix presents a general-purpose extensible framework for intercepting
calls to your WCF services. It walks through the technique and thought process
behind such an extension and shows two examples of how to utilize this simple
yet powerful and useful technique.
Appendix F, WCF Coding Standard
Appendix F is basically a consolidated list of all the best practices and dos and
don’ts mentioned throughout this book. The standard is all about the “how” and
the “what,” not the “why.” The rationale behind it is found in the rest of the book.
The standard also uses the terms and helper classes discussed in this book.
Appendix G, ServiceModelEx Catalog
The final appendix presents a catalog of the 100 or so public helper types (exclud­
ing internal helper types) of ServiceModelEx mentioned in the book, arranged by
categories and techniques, with a short description of each.
Introducing Michael “Monty” Montgomery
In 2009 at my annual Architect’s Master Class I met Monty, who at the time was the
chief architect of a large enterprise. Over the next few years we kept in touch since
Monty was one of the best architects I have ever met. Monty has a natural knack for
service-oriented design and the related system issues. He also proved to be a WCF
expert. In 2012 he finally made the jump and joined IDesign. The reason I wanted
xviii | Preface
him had almost nothing to do with his technical expertise. Monty has a fundamental
appreciation for what it takes to make a developer team of a broad spectrum of acu­
men productive. Over the years Monty has mentored many architects on how to ach­
ieve just that objective, so he was a natural fit to help with this fourth edition of the
WCF ‘Bible’. Together we bounced new and old ideas off each other, culminating in
the new techniques you read in this book.
With the addition of a second author, I wanted to keep the original author’s voice
from the previous three editions when referring to personal opinions or contribu­
tions. As with the previous editions, when the text mentions “I” or “my,” it refers to
Juval. When it says “we” or “our,” it refers to both Juval and Monty.
Some Assumptions About the Reader
I assume that you, the reader, are an experienced developer and that you are comfort­
able with object-oriented concepts such as encapsulation and inheritance. I will take
advantage of your existing understanding of object and component technology and
terminology, and port that knowledge to WCF. You should ideally have a fair under­
standing of .NET and know C# 4.5. Although the book uses C# for the most part, it is
just as pertinent to Visual Basic developers.
What You Need to Use This Book
To use this book, you will need .NET 4.5 or .NET 4.6 and Visual Studio 2015 or 2016.
For the Service Fabric appendix, you will need the Windows Azure Service Fabric
SDK. Unless I explicitly mention otherwise, the contents apply to any platform that
can run WCF. You may also install additional Windows components, such as MSMQ
and IIS.
Conventions Used in This Book
The following typographical conventions are used in this book:
Italic
Used for technical terms, URLs, email addresses, filenames, and file extensions.
Constant width
Used for code samples, statements, namespaces, classes, assemblies, interface
directives, operators, attributes, and reserved words.
Constant width bold
Used for emphasis in code samples.
Preface | xix
Constant width italic
Shows text that should be replaced with user-supplied values or by values deter­
mined by context.
This element signifies a tip or suggestion.
This element signifies a general note.
This element indicates a warning or caution.
Whenever I wish to make a point in a code sample, I do so with the static Assert
method of the Debug class:
int number = 1+2;
Debug.Assert(number = 3);
The Assert method accepts a Boolean value and throws an exception when it is false.
The book follows the recommended naming guidelines and coding style available at
iDesign. Whenever it deviates from that standard, it is likely the result of space or
line-length constraints. As for naming conventions, I use “Pascal casing” for public
member methods and properties; this means the first letter of each word in the name
is capitalized. For local variables and method parameters I use “camel casing,” in
which the first letter of each word in the name is capitalized, with the exception of the
first word. The names of private member variables are prefixed with m_:
class SomeClass
{
int m_Number;
public int Number
{get;set};
}
I use ellipses between curly braces to indicate the presence of code that is necessary
but unspecified:
xx | Preface
class SomeClass
{...}
In the interest of clarity and space, code examples often do not contain all the using
statements needed to specify all the namespaces the examples require; instead, such
examples include only the new namespaces introduced in the preceding text.
Safari® Books Online
Safari Books Online is an on-demand digital library that deliv­
ers expert content in both book and video form from the
world’s leading authors in technology and business.
Technology professionals, software developers, web designers, and business and crea­
tive professionals use Safari Books Online as their primary resource for research,
problem solving, learning, and certification training.
Safari Books Online offers a range of plans and pricing for enterprise, government,
education, and individuals.
Members have access to thousands of books, training videos, and prepublication
manuscripts in one fully searchable database from publishers like O’Reilly Media,
Prentice Hall Professional, Addison-Wesley Professional, Microsoft Press, Sams, Que,
Peachpit Press, Focal Press, Cisco Press, John Wiley & Sons, Syngress, Morgan Kauf­
mann, IBM Redbooks, Packt, Adobe Press, FT Press, Apress, Manning, New Riders,
McGraw-Hill, Jones & Bartlett, Course Technology, and hundreds more. For more
information about Safari Books Online, please visit us online.
How to Contact Us
Please address comments and questions concerning this book to the publisher:
O’Reilly Media, Inc.
1005 Gravenstein Highway North
Sebastopol, CA 95472
800-998-9938 (in the United States or Canada)
707-829-0515 (international or local)
707-829-0104 (fax)
We have a web page for this book, where we list errata, examples, and any additional
information. You can access this page at http://bit.ly/prog-wcf-services.
You can also contact the author at: http://www.idesign.net.
The author has posted a comprehensive code library on the IDesign website with
more than 150 downloads related to WCF essentials, contract design, instance man‐
Preface | xxi
agement, operations and calls, faults, transactions, concurrency, queuing, security,
and the service bus. The downloads articulate many of the code snippets in this book
in a working fashion. However, because of the large number of the downloads, the
maintenance involved, and the fact that these secondary, accompanying examples do
not themselves appear in the book, they are provided separately from the official
sources.
To comment or ask technical questions about this book, send email to bookques­
tions@oreilly.com.
For more information about our books, courses, conferences, and news, see our web­
site at http://www.oreilly.com.
Find us on Facebook: http://facebook.com/oreilly
Follow us on Twitter: http://twitter.com/oreillymedia
Watch us on YouTube: http://www.youtube.com/oreillymedia
Acknowledgments
I would not have been able to come to terms with WCF in its early days without the
constant support of and interaction with the WCF (then Indigo) program managers. I
am especially grateful to Steve Swartz, one of the WCF architects, not just for his
knowledge and insight, but also for his patience with me and those long IM sessions.
Thanks go to Yasser Shohoud, Doug Purdy, and Shy Cohen for the fascinating strate­
gic design reviews and to Krish Srinivasan for his almost philosophical approach to
engineering. Working with you guys has been the best part of learning WCF and a
privilege in its own right. The following WCF program managers also shared their
time and helped clarify WCF: Andy Milligan, Brian McNamara, Eugene Osovetsky,
Kenny Wolf, Kirill Gavrylyuk, Max Feingold, Michael Marucheck, Mike Vernal, and
Steve Millet. Thanks also to the group manager, Angela Mills.
Outside Microsoft, I am grateful to Nicholas Paldino for his help. This is the sixth
book that Nick has reviewed for me, and by now I am hooked. I simply cannot imag­
ine going to print without Nick’s insight, meticulous scrutiny, and diligent help, to say
nothing about Nick’s technical competence, which is nothing short of awe-striking
and humbling. The books are always a superior product as a result of his editing and
feedback.
I dedicate the book to the IDesign Alumni. A unique post-class benefit of attending
one of the IDesign Master Classes is joining this private forum where you can discuss
practicing our techniques, share observation and insights, and ask pertinent ques­
tions. The members of the forum are all world-class developers, architects, and
project leads, and the discussion amongst this group is profound, insightful, and of
the highest quality. Many of the ideas and techniques in this book were first tried on
xxii | Preface
and trialed by the fire of the Alumni. The best emails I get each day are the discussion
of the Alumni forum, and the level of mutual involvement, empathy, excellence, pro­
fessional integrity and responsiveness is second to none. It is truly inspiring that a
community of mostly virtual peers can care about their trade and each other that
much. I thank you for every time you made us stop and think about the best way of
answering a question, a smarter way of solving an Alumni’s design problem, or the
need for an improved technique. It is people like you that we write books for.
Preface | xxiii
Programming Wcf Services 4th Edition Juval Lwy Michael Montgomery
CHAPTER 1
WCF Essentials
This chapter describes the essential concepts and building blocks of Windows Com­
munication Foundation (WCF) and its architecture enabling you to build simple
services. You will learn the basic terms regarding addresses, bindings, contracts, and
endpoints; see how to host a service; learn how to write a client; understand related
topics, such as in-process (in-proc) hosting reliability, and transport sessions; and see
how to utilize WCF in Visual Studio. Even if you are already familiar with the basic
concepts of WCF, I recommend that you give this chapter at least a cursory reading,
not only to ensure that you have a solid foundation, but also because some of the
helper classes and terms introduced here will be used and extended throughout the
book.
What Is WCF?
WCF is a software development kit for developing and deploying services on Win­
dows (I will describe what a service is in the next section). But WCF is much more—
it is literally a better .NET. WCF provides a runtime environment for your services,
enabling you to expose Common Language Runtime (CLR) types as services and to
consume other services as CLR types. Although in theory you could build services
without WCF, in practice, building services is significantly easier with WCF. WCF is
Microsoft’s implementation of a set of industry standards defining service interac­
tions, type conversions, marshaling, and the management of various protocols. Con­
sequently, WCF provides interoperability between services.
WCF provides developers with the essential off-the-shelf plumbing required by
almost all applications, and as such, it greatly increases productivity. The first release
of WCF (as part of .NET 3.0) provided many useful facilities for developing services,
such as hosting, service instance management, asynchronous calls, reliability, transac­
tion management, disconnected queued calls, and security. The second release of
1
WCF (as part of .NET 3.5) provided additional tools and extended the original offer­
ing with additional communication options. The third release (as part of .NET 4.0)
included configuration changes, a few extensions, and the new features of discovery
(discussed in Appendix C) and routers (not discussed in this book). With WCF’s
fourth release (as part of .NET 4.5), WCF has several new simplification features and
additional bindings, including UDP and WebSocket bindings. WCF has an elegant
extensibility model you can use to enrich the basic offering. In fact, WCF itself is
written using this extensibility model. This book is dedicated to exploring these
aspects and features.
WCF is part of .NET 4.5, so it can run only on operating systems that support it.
Presently, this list consists of Windows XP and later and Windows Server 2003 and
later.
Most of the WCF functionality is included in a single assembly called System.Service­
Model.dll, located in the System.ServiceModel namespace.
Azure Service Bus
Microsoft originally designed the Azure Service Bus to solve the broad and challeng­
ing connectivity issues of consuming web services over the Internet.
The Azure Service Bus has since established itself as an indispensable tool for the
modern developer who is creating connected systems on any platform. The Azure
Service Bus has grown into a fully fledged connectivity platform with a diverse set of
features.
Recognizing that the challenges of providing service connectivity are not limited to
the Internet, Microsoft has released an Intranet version of the Azure Service Bus
named Service Bus for Windows Server. This version of the Service Bus targets the on­
premises versions of Windows Server and SQL Server.
As a connectivity platform, the Service Bus offers a wide array of options for dis­
tributed computing solutions. These include service relay features, event publishing
and subscription, persistent queues, and topics (queued events). The Service Bus also
supports a modern, federated security model through claim-based access control. The
Service Bus now supports a variety of programming models including classic WCF,
REST-based and even Advanced Message Queuing Protocol (AMQP). From this set
of building blocks, developers can create even more sophisticated patterns that
enhance the scalability, throughput, discoverability, availability, and security of their
solutions. The previous edition of this book devoted an in-depth chapter and a num­
ber of appendix sections to the Service Bus, along with several extensions and original
enhancements.
We consider the Service Bus nothing short of a fundamentally disruptive, essential
platform for modern distributed computing. There is no question the Service Bus
2 | Chapter 1: WCF Essentials
now merits a book in its own right to fully explore its many features and patterns in
depth. We have therefore removed the chapters on the Service Bus from this edition.
The material from those chapters will appear in greater and up-to-date detail in our
forthcoming book dedicated to the Service Bus platform.
Services
A service is a unit of functionality exposed to the world. In that respect, it is the next
evolutionary step in the long journey from functions to objects to components to
services. Service orientation (SO) is an abstract set of principles and best practices for
building service-oriented applications. Appendix A provides a concise overview and
outlines the motivation for using this methodology. The rest of this book assumes
you are familiar with these principles. A service-oriented application aggregates serv­
ices into a single logical application, similar to the way a component-oriented applica­
tion aggregates components and an object-oriented application aggregates objects, as
shown in Figure 1-1.
Figure 1-1. A service-oriented application
The services can be local or remote, can be developed by multiple parties using any
technology, can be versioned independently, and can even execute on different time­
lines. Inside a service, you will find concepts such as languages, technologies, plat­
forms, versions, and frameworks, yet between services, only prescribed
communication patterns are allowed.
The client of a service is merely the party consuming its functionality. The client can
be literally anything—for instance, a Windows Forms, WPF, Silverlight, or Windows
Store App class, an ASP.NET page, or another service.
Clients and services interact by sending and receiving messages. Messages may be
transferred directly from the client to the service or be sent via an intermediary such
Services | 3
as the Azure Service Bus. With WCF, messages are SOAP messages. These messages
are independent of transport protocols—unlike web services, WCF services may
communicate over a variety of transports (not just HTTP). WCF clients may intero­
perate with non-WCF services, and WCF services can interact with non-WCF clients.
That said, if you develop both the client and the service, you can typically construct
the application so that both ends require WCF in order to utilize WCF-specific
advantages.
Because the making of the service is opaque from the outside, a WCF service typically
exposes metadata describing the available functionality and possible ways of commu­
nicating with the service. The metadata is published in a predefined, technology­
neutral way, such as using Web Services Description Language (WSDL) over HTTP­
GET or an industry standard for metadata exchange over any protocol. A non-WCF
client can import the metadata to its native environment as native types. Similarly, a
WCF client can import the metadata of a non-WCF service and consume it as native
CLR classes and interfaces.
Service Execution Boundaries
With WCF, the client never interacts with a service directly, even when dealing with a
local, in-memory service. Instead, the client always uses a proxy to forward calls to
the service. The proxy exposes the same operations as the service, plus some proxy­
management methods.
WCF allows the client to communicate with a service across all execution boundaries.
On the same machine, the client can consume services in the same app domain,
across app domains in the same process, or across processes (see Figure 1-2).
Figure 1-2. Same-machine communication using WCF
Across machine boundaries (Figure 1-3), the client can interact with services in its
intranet or across the Internet.
4 | Chapter 1: WCF Essentials
Figure 1-3. Cross-machine communication using WCF
WCF and Location Transparency
In the past, distributed computing technologies such as DCOM and .NET remoting
aspired to provide the same programming model to the client regardless of whether
the object was local or remote. In the case of a local call, the client used a direct refer­
ence, and when dealing with a remote object, the client used a proxy. The problem
with trying to use the local programming model as the remote programming model
was that there is much more to a remote call than an object with a wire. Complex
issues such as lifecycle management, reliability, state management, and security
reared their heads, making the remote programming model significantly more com­
plex. Numerous problems arose, all because the remote object was trying to be what it
is not—a local object.
WCF also strives to provide the client with the same programming model regardless
of the location of the service. However, the WCF approach is the exact opposite: it
takes the remote programming model of instantiating and using a proxy and uses it
even in the most local case. Because all interactions are done via a proxy, requiring
the same configuration and hosting, WCF maintains the same programming model
for the local and remote cases; thus, it not only enables you to switch locations
without affecting the client, but also significantly simplifies the application program­
ming model. Another important benefit of always using a proxy is that it enables
WCF to intercept the calls and add its value, as you will see later on.
Addresses
In WCF, every service is associated with a unique address. The address provides two
important elements: the location of the service and the transport protocol, or trans­
port scheme, used to communicate with the service. The location portion of the
address indicates the name of the target machine, site, or network; a communication
port, pipe, or queue; and an optional specific path, or Uniform Resource Ifepvkfier
Addresses | 5
(URI). A URI can be any unique string, such as the service name or a globally unique
identifier (GUID).
Out of the box, WCF supports the following transport schemes:
• HTTP/HTTPS
• TCP
• IPC
• MSMQ
• Service Bus
• WebSocket
• UDP
Addresses always have the following format:
[base address]/[optional URI]
The base address is always in this format:
[transport]://[machine or domain][:optional port]
Here are a few sample addresses:
http://localhost:8001
http://localhost:8001/MyService
net.tcp://localhost:8002/MyService
net.pipe://localhost/MyPipe
net.msmq://localhost/private/MyQueue
net.msmq://localhost/MyQueue
ws://localhost/MyService
soap.udp://localhost:8081/MyService
The way to read an address such as:
http://localhost:8001
is like this: “Using HTTP, go to the machine called localhost, where on port 8001
someone is waiting for my calls.”
If there is also a URI, as in:
http://localhost:8001/MyService
the address will read as follows: “Using HTTP, go to the machine called localhost,
where on port 8001 someone called MyService is waiting for my calls.”
TCP Addresses
TCP addresses use net.tcp for transport and typically include a port number, as in:
6 | Chapter 1: WCF Essentials
net.tcp://localhost:8002/MyService
When a port number is not specified, the TCP address defaults to port 808:
net.tcp://localhost/MyService
It is possible for two TCP addresses (from the same host, as discussed later in this
chapter) to share a port:
net.tcp://localhost:8002/MyService
net.tcp://localhost:8002/MyOtherService
TCP-based addresses are used throughout this book.
You can configure TCP-based addresses from different service
hosts to share a port.
HTTP Addresses
HTTP addresses use http for transport and can also use https for secure transport.
You typically use HTTP addresses with outward-facing Internet-based services, and
you can specify a port as shown here:
http://localhost:8001
If you do not specify the port number, it defaults to 80 (and port 443 for HTTPS). As
with TCP addresses, two HTTP addresses from the same host can share a port, even
on the same machine.
HTTP-based addresses are also used throughout this book.
IPC Addresses
Inter-process communication (IPC) addresses use net.pipe for transport, to indicate
the use of the Windows named pipe mechanism. In WCF, services that use IPC can
only accept calls from the same machine. Consequently, you must specify either the
explicit local machine name or localhost for the machine name, followed by a
unique string for the pipe name:
net.pipe://localhost/MyPipe
You can open a named pipe only once per machine, so it is not possible for two
named pipe addresses to share a pipe name on the same machine.
IPC-based addresses are used throughout this book.
Addresses | 7
The IPC address format as provided by Microsoft is incorrect, indi­
cating the mechanism instead of the protocol. The correct scheme
format should have been net.ipc instead of net.pipe, much like
the TCP address uses net.tcp rather than net.socket.
MSMQ Addresses
MSMQ addresses use net.msmq for transport, to indicate the use of the Microsoft
Message Queue (MSMQ). You must specify the queue name. When you’re dealing
with private queues, you must also specify the queue type, but you can omit that for
public queues:
net.msmq://localhost/private/MyService
net.msmq://localhost/MyService
Chapter 9 is dedicated to making queued calls.
WebSocket Addresses
WebSocket addresses are unique in that they are asymmetrical between client and
service. The client uses ws for transport and wss for secure transport, while the ser­
vice always uses http or https respectively. WebSocket addresses are required when
you need callbacks over the Internet, and you can specify a port as shown here:
ws://localhost:8080
If you do not specify the port number, a WebSocket defaults to the standard HTTP
port 80 (and port 443 for wss or HTTPS). As with TCP addresses, two WebSocket
addresses on the same machine from the same host can share a port.
UDP Addresses
UDP addresses use soap.udp for transport, to indicate SOAP over UDP is being used.
You can also specify a port as shown here:
soap.udp://localhost:8081
Contracts
In WCF, all services expose contracts. The contract is a platform-neutral and standard
way of describing what the service does. WCF defines four types of contracts:
Service contracts
Describe which operations the client can perform on the service. Service con­
tracts are the subject of Chapter 2, but they are used extensively in every chapter
in this book.
8 | Chapter 1: WCF Essentials
Data contracts
Define which data types are passed to and from the service. WCF defines implicit
contracts for built-in types such as int and string, but you can easily define
explicit opt-in data contracts for custom types. Chapter 3 is dedicated to defining
and using data contracts, and subsequent chapters make use of data contracts as
required.
Fault contracts
Define which errors are raised by the service and how the service handles and
propagates errors to its clients. Chapter 6 is dedicated to defining and using fault
contracts.
Message contracts
Allow the service to interact directly with messages. Message contracts can be
typed or untyped and are useful in interoperability cases when another party has
already dictated some explicit (typically proprietary) message format. This, how­
ever, is by no means the usual case for common WCF applications, so this book
makes no use of message contracts. Unless you are required to leverage the flexi­
bility, power, and extensibility of message contracts, you should avoid them, as
they add no value, but do add complexity. In many cases, the desire to use mes­
sage contracts indicates a need for a custom application context, which you can
address using custom headers (a useful alternative technique used throughout
this book). For more on message headers, see Appendix B.
The Service Contract
The ServiceContractAttribute is defined as:
[AttributeUsage(AttributeTargets.Interface|AttributeTargets.Class,
Inherited = false)]
public sealed class ServiceContractAttribute : Attribute
{
public string Name
{get;set;}
public string Namespace
{get;set;}
//More members
}
This attribute allows you to define a service contract. You can apply the attribute on
an interface or a class, as shown in Example 1-1.
Example 1-1. Defipkpg and implementing a service contract
[ServiceContract]
interface IMyContract
{
Contracts | 9
[OperationContract]
string MyMethod(string text);
//Will not be part of the contract
string MyOtherMethod(string text);
}
class MyService : IMyContract
{
public string MyMethod(string text)
{
return "Hello " + text;
}
public string MyOtherMethod(string text)
{
return "Cannot call this method over WCF";
}
}
The ServiceContract attribute maps a CLR interface (or inferred interface, as you
will see later) to a technology-neutral service contract. The ServiceContract
attribute exposes a CLR interface (or a class) as a WCF contract independently of that
type’s visibility. The type visibility has no bearing on WCF, because visibility is a CLR
concept. Applying the ServiceContract attribute on an internal interface exposes
that interface as a public service contract, ready to be consumed across the assembly
boundary. Without the ServiceContract attribute, the interface is not visible to WCF
clients, in line with the service-oriented tenet that service boundaries should be
explicit. To enforce that tenet, all contracts must explicitly opt in: only interfaces (or
classes) decorated with the ServiceContract attribute will be considered WCF con­
tracts; other types will not.
In addition, none of the members of the type will ever be part of the contract when
using the ServiceContract attribute. You must explicitly indicate to WCF which
methods to expose as part of the WCF contract using the OperationContractAttri
bute, defined as:
[AttributeUsage(AttributeTargets.Method)]
public sealed class OperationContractAttribute : Attribute
{
public string Name
{get;set;}
//More members
}
You can apply the OperationContract attribute only on methods, not on properties,
indexers, or events, which are CLR concepts. WCF only understands operations—log­
ical functions—and the OperationContract attribute exposes a contract method as a
logical operation to perform as part of the service contract. Other methods on the
interface (or class) that do not have the OperationContract attribute will not be part
10 | Chapter 1: WCF Essentials
of the contract. This enforces explicit service boundaries and maintains an explicit
opt-in model for the operations themselves. In addition, a contract operation cannot
use object references as parameters: only primitive types or data contracts are
allowed.
Applying the ServiceContract attribute
WCF lets you apply the ServiceContract attribute on an interface or on a class.
When you apply it on an interface, some class needs to implement that interface. In
general, you use plain C# or VB to implement the interface, and nothing in the ser­
vice class code pertains to it being a WCF service:
[ServiceContract]
interface IMyContract
{
[OperationContract]
string MyMethod();
}
class MyService : IMyContract
{
public string MyMethod()
{
return "Hello WCF";
}
}
You can use implicit or explicit interface implementation:
class MyService : IMyContract
{
string IMyContract.MyMethod()
{
return "Hello WCF";
}
}
Because the client can never use the service class directly and must
always go through a proxy, using explicit interface implementation
is less important in WCF than it is in regular .NET programming.
A single class can support multiple contracts by deriving and implementing multiple
interfaces decorated with the ServiceContract attribute:
[ServiceContract]
interface IMyContract
{
[OperationContract]
string MyMethod();
Contracts | 11
}
[ServiceContract]
interface IMyOtherContract
{
[OperationContract]
void MyOtherMethod();
}
class MyService : IMyContract,IMyOtherContract
{
public string MyMethod()
{...}
public void MyOtherMethod()
{...}
}
There are, however, a few implementation constraints on the service implementation
class. You should avoid parameterized constructors, because WCF will only use the
default constructor. Also, although the class can use internal properties, indexers, and
static members, no WCF client will ever be able to access them.
WCF also lets you apply the ServiceContract attribute directly on the service class,
without defining a separate contract first:
//Avoid
[ServiceContract]
class MyService
{
[OperationContract]
string MyMethod()
{
return "Hello WCF";
}
}
Under the covers, WCF will infer the contract definition. You can apply the Opera
tionContract attribute on any method of the class, be it private or public.
Avoid using the ServiceContract attribute directly on the service
class. Always define a separate contract so that you can both con­
sume it independently of the class and have other classes imple­
ment it.
Names and namespaces
You can and should define a namespace for your contract. The contract namespace
serves the same purpose in WCF as it does in .NET programming: to scope a type of
contract and reduce the overall chance of a collision. You can use the Namespace
property of the ServiceContract attribute to provide a namespace:
12 | Chapter 1: WCF Essentials
[ServiceContract(Namespace = "MyNamespace")]
interface IMyContract
{...}
Unspecified, the contract namespace defaults to http://tempuri.org. For outward­
facing services, you typically use your company’s URL, and for intranet services, you
can use any meaningful unique name, such as MyApplication.
By default, the exposed name of the contract will be the name of the interface. How­
ever, you can use an alias for a contract to expose a different name to the clients in the
metadata, by using the Name property of the ServiceContract attribute:
[ServiceContract(Name = "IMyContract")]
interface IMyOtherContract
{...}
Similarly, the name of the publicly exposed operation defaults to the method name,
but you can use the Name property of the OperationContract attribute to alias it to a
different publicly exposed name:
[ServiceContract]
interface IMyContract
{
[OperationContract(Name = "SomeOperation")]
void MyMethod(string text);
}
You will see a use for these properties in Chapter 2.
Hosting
The WCF service class cannot exist in a void. Every WCF service must be hosted in a
Windows process called the host process. A single host process can host multiple serv­
ices, and the same service type can be hosted in multiple host processes. WCF has no
restrictions regarding whether or not the host process is also the client process,
although having a separate process promotes fault and security isolation. It is also
immaterial who provides the process and what kind of process is involved. The host
can be provided by Internet Information Services (IIS), by the Windows Activation
Service (WAS) on versions of Windows before Windows Server 2008 R2 and Win­
dows 7, or by the developer as part of the application.
In-process (or in-proc) hosting, where the service resides in the
same process as the client, is a special case. By definition, the devel­
oper provides the host for the in-proc case.
Hosting | 13
IIS Hosting
The main advantage of hosting a service on the Microsoft IIS web server is that the
host process is launched automatically upon the first client request, and IIS manages
the lifecycle of the host process. The main disadvantage of IIS hosting is that you can
only use HTTP.
Hosting in IIS is very similar to hosting a web service or ASP.NET Web API service.
You need to provide a virtual directory under IIS and supply an .svc file. IIS uses
the .svc file to identify the service code behind the file and class. Example 1-2 shows
the syntax for the .svc file.
Example 1-2. A .svc fine
<%@ ServiceHost
Language = "C#"
Debug = "true"
CodeBehind = "~/App_Code/MyService.cs"
Service = "MyService"
%>
You can even inject the service code inline in the .svc file, but that is
not advisable.
When you use IIS hosting, the base address used for the service always has to be the
same as the address of the .svc file.
Using Visual Studio
You can use Visual Studio to generate a boilerplate IIS-hosted service. From the File
menu, select New Web Site, then select WCF Service from the New Web Site dialog
box. Visual Studio creates a new website, service code, and a matching .svc file. You
can also use the Add New Item dialog box to add another service later.
The Web.Eonfii fiffle
The website config file (yeb.eqpfig) typically lists the types you want to expose as
services. You need to use fully qualified type names, including the assembly name if
the service type comes from an unreferenced assembly:
<system.serviceModel>
<services>
<service name = "MyNamespace.MyService">
...
</service>
14 | Chapter 1: WCF Essentials
</services>
</system.serviceModel>
Instead of defining an .svc file, you can provide the service type and its address infor­
mation directly in the application yeb.eqpfig file in the serviceHostingEnvironment
section. In fact, you can list as many services as you like there:
<system.serviceModel>
<serviceHostingEnvironment>
<serviceActivations>
<add relativeAddress = "MyService.svc" service =
"MyNamespace.MyService"/>
<add relativeAddress = "MyOtherService.svc" service =
"MyOtherService"/>
</serviceActivations>
</serviceHostingEnvironment>
<services>
<service name = "MyNamespace.MyService">
...
</service>
<service name = "MyOtherService">
...
</service>
</services>
</system.serviceModel>
Self-Hosting
Self-hosting is the technique in which the developer is responsible for providing and
managing the lifecycle of the host process. Use self-hosting when you want a process
(or machine) boundary between the client and the service and when you are using
the service in-proc—that is, in the same process as the client. You can provide any
Windows process, such as a Windows Forms application, a WPF application, a Con­
sole application, or a Windows Service. Note that the process must be running before
the client calls the service, which typically means you have to prelaunch it. This is not
an issue for Windows Services or in-proc hosting. You can provide a host with only a
few lines of code. Unlike IIS, a self-hosted service can use any WCF transport proto­
col, and you can take advantage of all the WCF features, including the Service Bus,
discovery, and utilizing a singleton service.
As with IIS hosting, the hosting application config file (app.eqpfig) typically lists the
types of the services you wish to host and expose to the world:
<system.serviceModel>
<services>
<service name = "MyNamespace.MyService">
...
</service>
</services>
</system.serviceModel>
Hosting | 15
In addition, the host process must explicitly register the service types at runtime and
open the host for client calls, which is why the host process must be running before
the client calls arrive. Creating the host is typically done in the Main() method using
the class ServiceHost, defined in Example 1-3.
Example 1-3. The ServiceHost class
public interface ICommunicationObject
{
void Open();
void Close();
//More members
}
public abstract class CommunicationObject : ICommunicationObject
{...}
public abstract class ServiceHostBase : CommunicationObject,IDisposable,...
{...}
public class ServiceHost : ServiceHostBase
{
public ServiceHost(Type serviceType,params Uri[] baseAddresses);
//More members
}
You need to provide the constructor of ServiceHost with the service type and
optionally with default base addresses. The set of base addresses can be an empty set,
and even if you provide base addresses, you can configure the service to use different
base addresses. Having a set of base addresses enables the service to accept calls on
multiple addresses and protocols and to use only a relative URI.
Note that each ServiceHost instance is associated with a particular service type, and
if the host process needs to host multiple types of services, you will need a matching
number of ServiceHost instances. By calling the Open() method on the host, you
allow calls in, and by calling the Close() method, you gracefully exit the host
instance, allowing calls in progress to complete while refusing future client calls even
if the host process is still running. Closing the service host is typically done when the
host process shuts down. For example, to host this service in a Windows Forms appli­
cation:
[ServiceContract]
interface IMyContract
{...}
class MyService : IMyContract
{...}
you would write the following hosting code:
static void Main()
{
ServiceHost host = new ServiceHost(typeof(MyService));
16 | Chapter 1: WCF Essentials
host.Open();
//Can do blocking calls:
Application.Run(new MyForm());
host.Close();
}
Opening a host loads the WCF runtime and launches worker threads to monitor
incoming requests. The monitoring threads dispatch incoming calls to worker
threads from the I/O completion thread pool (where there are up to 1,000 threads by
default). Because worker threads are involved, you can perform blocking operations
after opening the host.
Because the host is closed gracefully, the amount of time it will take is undetermined.
By default, the host will block for 10 seconds waiting for Close() to return and will
proceed with the shutdown after that timeout has expired. Before opening the host,
you can configure a different close timeout with the CloseTimeout property of
ServiceHostBase:
public abstract class ServiceHostBase : ...
{
public TimeSpan CloseTimeout
{get;set;}
//More members
}
For example, you can use programmatic calls to set the close timeout to 20 seconds:
ServiceHost host = new ServiceHost(...);
host.CloseTimeout = TimeSpan.FromSeconds(20);
host.Open();
You can do the same in a config file by placing the close timeout in the host section
of the service:
<system.serviceModel>
<services>
<service name = "MyNamespace.MyService">
<host>
<timeouts
closeTimeout = "00:00:20"
/>
</host>
...
</service>
</services>
</system.serviceModel>
Hosting | 17
Using Visual Studio
Visual Studio allows you to add a WCF service to any application project by selecting
WCF Service from the Add New Item dialog box. A service added this way is, of
course, in-proc toward the host process, but out-of-proc clients can also access it.
Self-hosting and base addresses
You can launch a service host without providing any base address by omitting the
base addresses altogether:
ServiceHost host = new ServiceHost(typeof(MyService));
Do not provide a null instead of an empty list, because that will
throw an exception:
ServiceHost host;
host = new ServiceHost(typeof(MyService),null);
You can also register multiple base addresses separated by commas, as in the follow­
ing snippet, as long as the addresses do not use the same transport scheme (note the
use of the params qualifier in Example 1-3):
Uri tcpBaseAddress = new Uri("net.tcp://localhost:8001/");
Uri httpBaseAddress = new Uri("http://localhost:8002/");
ServiceHost host = new ServiceHost(typeof(MyService),
tcpBaseAddress,httpBaseAddress);
WCF also lets you list the base addresses in the host config file:
<system.serviceModel>
<services>
<service name = "MyNamespace.MyService">
<host>
<baseAddresses>
<add baseAddress = "net.tcp://localhost:8001/"/>
<add baseAddress = "http://localhost:8002/"/>
</baseAddresses>
</host>
...
</service>
</services>
</system.serviceModel>
When you create the host, it will use whichever base addresses it finds in the config
file, plus any base addresses you provide programmatically. Take extra care to ensure
the configured base addresses and the programmatic ones do not overlap in the
scheme.
18 | Chapter 1: WCF Essentials
On any machine running Windows XP or later, for HTTP
addresses other than port 80, you will need to launch the host pro­
cess (or Visual Studio while testing or debugging) as an adminis­
trator. Instead of doing that every time, you can instruct Windows
to reserve the port namespace for the user running the host. Do
this using the netsh.exe command-line utility. For example, to
reserve the HTTP port 8002 on the local machine, you will need to
run this command at a command prompt launched as an adminis­
trator:
netsh http add urlacl url=http://+:8002/user=
"MachineOrDomainUserName"
You can even register multiple hosts for the same type, as long as the hosts use differ­
ent base addresses:
Uri baseAddress1 = new Uri("net.tcp://localhost:8001/");
ServiceHost host1 = new ServiceHost(typeof(MyService),baseAddress1);
host1.Open();
Uri baseAddress2 = new Uri("net.tcp://localhost:8002/");
ServiceHost host2 = new ServiceHost(typeof(MyService),baseAddress2);
host2.Open();
However, with the exception of some threading issues discussed in Chapter 8, open­
ing multiple hosts this way offers no real advantage. In addition, opening multiple
hosts for the same type does not work with base addresses supplied in the config file
and requires use of the ServiceHost constructor.
Advanced hosting features
The ICommunicationObject interface that ServiceHost supports offers some
advanced features, listed in Example 1-4.
Example 1-4. The ICommunicationObject interface
public interface ICommunicationObject
{
void Open();
void Close();
void Abort();
event EventHandler Closed;
event EventHandler Closing;
event EventHandler Faulted;
event EventHandler Opened;
event EventHandler Opening;
IAsyncResult BeginClose(AsyncCallback callback,object state);
IAsyncResult BeginOpen(AsyncCallback callback,object state);
void EndClose(IAsyncResult result);
Hosting | 19
void EndOpen(IAsyncResult result);
CommunicationState State
{get;}
//More members
}
public enum CommunicationState
{
Created,
Opening,
Opened,
Closing,
Closed,
Faulted
}
If opening or closing the host is a lengthy operation, you can do so asynchronously
with the BeginOpen() and BeginClose() methods.
You can subscribe to hosting events such as state changes or faults, and you can use
the State property to query for the host status. Finally, the ServiceHost class also
offers the Abort() method. Abort() is an ungraceful exit—when called, it immedi­
ately aborts all service calls in progress and shuts down the host. Active clients will
each get an exception.
The ServiceHost<T> class
You can improve on the WCF-provided ServiceHost class by defining the Service
Host<T> class, as shown in Example 1-5.
Example 1-5. The ServiceHost<T> class
public class ServiceHost<T> : ServiceHost
{
public ServiceHost() : base(typeof(T))
{}
public ServiceHost(params string[] baseAddresses) : base(typeof(T),
baseAddresses.Select(address=>new Uri(address)).ToArray())
{}
public ServiceHost(params Uri[] baseAddresses) : base(typeof(T),baseAddresses)
{}
}
ServiceHost<T> provides simple constructors that do not require the service type as
a construction parameter and that can operate on raw strings instead of the cumber­
some Uri. I’ll add quite a few extensions, features, and capabilities to ServiceHost<T>
throughout this book.
20 | Chapter 1: WCF Essentials
WAS Hosting
The problem with hosting in IIS is that it is a web server, not a hosting engine. It
therefore requires you to masquerade your service as a website. While ASP.NET
encapsulates this step for you, it causes a significant increase in internal complexity,
involving the HTTP modules and the ASP.NET pipeline. The problem is that the
more moving parts involved, the higher the likelihood of something going wrong.
Moreover, limiting the service to using only HTTP makes IIS ill-suited for intranet
applications.
With the next wave of Windows, Microsoft rectified this issue by providing a general­
purpose hosting engine called the Windows Activation Service (WAS). WAS is a sys­
tem service available with Windows versions Windows Server 2008 or later. The WAS
is a true general-purpose hosting engine. It can host websites (in fact, IIS 7 or later
will host its websites in the WAS by default), but it can just as easily host your serv­
ices, allowing you to use any transport, such as TCP, IPC, or MSMQ. You can install
and configure the WAS separately from IIS. Hosting a WCF service in the WAS is
designed to look just like hosting in IIS. You need to either supply an .svc file, just as
with IIS, or provide the equivalent information in the config file. All the other devel­
opment aspects, such as support in Visual Studio, remain exactly the same. Because
the WAS is a system service, you do not need to pre-launch your service host process.
When the first client call arrives, the WAS will intercept it, launch a worker process to
host your service, and forward it the call.
WAS offers many features beyond self-hosting, including application pooling, recy­
cling, idle time management, identity management, and isolation. To use the WAS,
you must target a platform that supports it, such as a Windows Server 2008 (or later)
machine for scalability, or a Windows 7 (or later) client machine for a handful of cli­
ents.
That said, self-hosted processes do offer singular advantages, such as in-proc hosting,
dealing well with unknown customer environments, and easy programmatic access to
the advanced hosting features described previously.
Custom Hosting in IIS/WAS
It is often the case that you need to interact with the host instance. While this is inte­
gral to the use of a self-hosting solution, when using IIS or WAS, you have no direct
access to the host. To overcome this hurdle, WCF provides a hook called a host fac­
tory. Using the Factory tag in the .svc file, you can specify a class you provide that
creates the host instance:
<%@ ServiceHost
Language = "C#"
Debug = "true"
CodeBehind = "~/App_Code/MyService.cs"
Hosting | 21
Service = "MyService"
Factory = "MyServiceFactory"
%>
You can also specify the host factory in the config file when not using an .svc file
explicitly:
<serviceActivations>
<add relativeAddress = "MyService.svc"
service = "MyService"
factory = "MyServiceFactory"
/>
</serviceActivations>
The host factory class must derive from the ServiceHostFactory class and override
the CreateServiceHost() virtual method:
public class ServiceHostFactory : ...
{
protected virtual ServiceHost CreateServiceHost(Type serviceType,
Uri[] baseAddresses);
//More members
}
For example:
class MyServiceFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType,
Uri[] baseAddresses)
{
ServiceHost host = new ServiceHost(serviceType,baseAddresses);
//Custom steps here
return host;
}
}
The CreateServiceHost() method is logically the Main() method
of an IIS or WAS hosted service, and you can use it just for that
purpose.
Choosing a Host
Although WCF offers such a variety of options, from IIS, to the WAS, to self-hosting,
it is easy to choose the correct host, as shown in Figure 1-4. For an Internet applica­
tion (i.e., an application that receives calls from clients across the Internet), IIS or the
WAS provide the best capabilities to harden your services against the security con­
22 | Chapter 1: WCF Essentials
cerns of access over the Internet. Otherwise prefer self-hosting your services. Self­
hosting provides your organization with a hosting model that significantly simplifies
the administration and provisioning of intranet services. WCF services do not require
the many additional lifecycle management facilities that the WAS provides.
Figure 1-4. Choosing a host for any service
Microsoft will retire Windows Server AppFabric in April 2016. You
should not target any of its features, particularly the service autos­
tart feature, for any of your systems.
Bindings
There are multiple aspects of communication with any given service, and there are
many possible communication patterns. Messages can follow a synchronous request­
reply or asynchronous fire-and-forget pattern, messages can be bidirectional, mes­
sages can be delivered immediately or queued, and the queues can be durable or
volatile. As discussed previously, there are many possible transport protocols for the
messages, such as HTTP (or HTTPS), TCP, IPC, MSMQ. There are also a few possi­
ble message encoding options. You can choose plain text to enable interoperability,
binary encoding to optimize performance, or the Message Transport Optimization
Bindings | 23
Mechanism (MTOM) for large payloads. Finally, there are multiple options for secur­
ing messages. You can choose not to secure them at all, to provide transport-level
security only, or to provide message-level privacy and security, and of course, there
are numerous ways to authenticate and authorize the clients. Message delivery might
be unreliable or reliable end-to-end across intermediaries and dropped connections,
and the messages might be processed in the order they were sent or in the order they
were received. Your service might need to interoperate with other services or clients
that are aware of only the basic web service protocol, or with clients and services
capable of using the score of WS-* protocols, such as WS-Security and WS-Atomic
Transactions. Your service may need to have the capability to interoperate with any
client or you may want to restrict your service to interoperate only with another WCF
service or client.
If you were to count all the possible communication and interaction options, you’d
probably find that the number of permutations is in the tens of thousands. Some of
those choices may be mutually exclusive and some may mandate other choices.
Clearly, both the client and the service must be aligned on all these options in order
to communicate properly. Managing this level of complexity adds no business value
to most applications, and yet the productivity and quality implications of making the
wrong decisions are severe.
To simplify these choices and make them manageable, WCF groups together sets of
communication aspects in bindings. A binding is merely a consistent, canned set of
choices regarding the transport protocol, message encoding, communication pattern,
reliability, security, transaction propagation, and interoperability. All you need to do
is determine the target scenario for your service, and WCF makes a correct multidi­
mensional decision for you regarding all the aspects of the communication. Ideally,
you can extract all these “plumbing” aspects from your service code and allow the
service to focus solely on the implementation of the business logic. Bindings allow
you to use the same service logic over drastically different plumbing.
You can use the WCF-provided bindings out of the box, you can tweak their proper­
ties, or you can write your own custom bindings from scratch. The service publishes
its choice of binding in its metadata, enabling clients to query for the type and spe­
cific properties of the binding. This is important because the client must use the exact
same binding values as the service. A single service can support multiple bindings on
separate addresses.
The Common Bindings
WCF defines five frequently used bindings:
Basic binding
Offered by the BasicHttpBinding class, basic binding is designed to expose a
WCF service as a legacy ASMX web service so that old clients can work with new
24 | Chapter 1: WCF Essentials
Random documents with unrelated
content Scribd suggests to you:
"Tarkoitatko, että olet valehdellut?"
"Tyhjää valhetta kaikki!"
"Sinä olet ilkeä, Anna."
"Kai lienen. En ole muuten kovin onnellinenkaan, se minun on
sanottava. — Mutta rouvat ovat jo heränneet ja herrat tulevat saliin.
Mennään sinne!"
Kynnyksellä hänet pysäyttää Gösta Berling, joka tulee nuorten
naisten seuraan.
"Teidän pitää nyt olla minulle kärsivällisiä", hän sanoo nauraen.
"Kiusaan teitä vain kymmenen minuuttia, mutta nyt teidän täytyy
kuunnella runoa."
Hän kertoo heille, että oli viime yönä nähnyt unta elävämmin kuin
juuri koskaan, hän oli nähnyt sellaista unta, että oli muka kirjoittanut
runon. Hän, jota ihmiset sanoivat "runoilijaksi", vaikka hän oli tähän
asti saanut aivan aiheetta omistaa tuon lisänimen, hän oli silloin,
keskellä yötä, noussut ja puolittain unessa, puolittain valveilla
alkanut kirjoittaa. Ja runoelman hän oli sitten aamulla löytänyt
kirjoituspöydältään. Hän ei ollut ikinä uskonut mokomaa itsestään. Ja
nyt piti naisten se kuulla.
Ja hän lukee:
Nousi nyt kuu, ihanimman vuorokauden hetkistä toi.
Sinikirkkaalta, kalvaalta holviltaan läpi köynnösten hohtoa
parvekkeelle se seuloi, jonk' alla värisi uurnassaan punalilja,
min terään päivätär kultapäärmehet neuloi. Kiviportaill' istuen
unelmoi siin' ääneti nuoret ja vanhat, kuunnellen noita
sydämen vanhoja lauluja, muistoon joita ihanimpana
vuorokauden hetkistä tunne toi.
Reseedaryhmästä nous' sulotuoksu, meit' ympäröi, ja
viidoista tummien pensastoin varjoja hiipii kasteisen,
välkkyvän nurmikon laitaa. Sielukin ruumiin varjosta noin
valon ilmoihin, seutuihin, joita se tuskin tajuta taitaa,
sinihohto-holveihin ikävöi, kirkkauteen, johon verraten tähdet
on kelmeet. Oi, kuka torjuu tunteiden leikit ja telmeet, yön
varjot, reseedain suruisa tuoksu kun ympäröi.
Terät köynnösruusun tippui viimeiset, vaalenneet, vaikkei
niit' uhriksi vaatinut tuulonen vallaton. Noin — mietittiin —
elon jättää soisimme, haipuin ilmaan kuin sävel kantelon, kuin
lehti syyskelmeä tyhjiin vaikertamatta vaipuin. Pitkät miks' iän
taipaleet? Luontoa häiriten nauttimaan elon harhasta
jäämme. Kuolema on elon palkka; siis hiljaa se jättäkäämme,
kuin terät köynnösruusun viimeiset, vaalenneet.
Yösiippa häilähtäin ohi liipotti, minne lie,
häipyi pois, kuun kohdalla häämötti taas.
Vaan silloin nous poven ankeen alta
tuo kysymys raskas kuin haudan paas,
tuo yhä vastaamaton, tuo vanha kuin tuskan valta:
"Oi, mihin kuljemme, oi, mik' on eessämme tie,
konsa maan vihreät niityt ei enää allamme loista?"
Hengen tielle voipiko toinen neuvoa toista, —
yösiippaa helpommin neuvot, mi liipotti, minne lie.
Ja olkaani päänsä hän, pehmeät kutrinsa, kallistaa,
hän, joka minua lempi, ja kuiskivi hiljaa näin:
Elä usko, ei kaukaisiin avaruuksihin sielut lennä;
kun kuolen, el' usko, ett' etäällä oon.
Mihin koditon sieluni vois, jos ei lemmityn sieluun mennä?
Sun luonas se ainian asukoon!
Oi ahdistus! Suru sydämen murtaa tahtoi.
Hänet kuoloko veis, pian veis? Yö viimeinen olla jo mahtoi?
Viimeisen kerranko suutelin kutria aaltoavaa?
On vuosia vierinyt. Viel' yhä varjohon siell' usein istun, kun
yö tutun paikan on tummentanut. Mut parvekkeell' läpi
köynnösten kuultavan kuun näen kammoin. Se yksin tietää,
kuink' usein armasta suudellut siell' oon, se värjyen kirkkaasti
kyyneleet ammoin, joit' armaani kutreille vierinyt on. Voi,
muistojen tuskaa! Se syntisen sieluni vaiva on tietää: hän
asuvi siinä! Minkä rangaistuksen se sietää, ken sitoi itseensä
sielun, mi niin oli puhdas ja tahraton.
"Gösta", sanoo Anna leikillisesti, vaikka tuska kuristaa hänen
kurkkuaan, "sinusta sanotaan, että olet elänyt useampia runoja kuin
toiset ovat kirjoittaneet, vaikk'eivät olisi elämässään muuta
tehneetkään, mutta tiedätkös: sinun on parasta runoilla omalla
tavallasi. Tuo oli yötyötä, tiedätkös."
"Et ole lempeä, Anna."
"Tulla lukemaan tuollaista, kuolemasta ja surkeudesta, — ettet
häpeä!"
Gösta ei kuule enää häntä. Hänen silmänsä ovat suunnatut
nuoreen kreivittäreen. Kreivitär istuu aivan jäykkänä,
liikkumattomana kuin kuvapatsas. Göstasta hän näyttää kuin
pyörtyvän.
Mutta sanomattoman työläästi saa kreivitär sanan huuliltaan.
"Menkää!" hän sanoo.
"Kuka, menkää? Pitääkö minun mennä?"
"Papin pitää mennä", änkyttää kreivitär.
"Elisabet, ole toki vaiti!"
"Juoppo pappi saa mennä ulos huoneestani!"
"Anna, Anna", kysyy Gösta, "mitä hän tarkoittaa?"
"Parasta on sinun mennä, Gösta."
"Miksi minun pitää mennä? Mitä tämä merkitsee?"
"Anna", sanoo kreivitär Elisabet, "sano hänelle, sano hänelle…!"
"En, sano itse, kreivitär!"
Kreivitär puree hampaansa yhteen ja masentaa liikutuksensa.
"Herra Berling", hän sanoo ja astuu hänen eteensä, "teillä on
merkillinen kyky saada ihmiset unohtamaan, kuka olette. Minä en ole
tiennyt sitä ennen kuin tänään. Olen juuri kuullut kertomuksen Ebba
Dohnan kuolemasta ja saanut samalla tietää, että tieto, että hän
rakasti arvotonta, tappoi hänet. Teidän runonne on selittänyt
minulle, että se mies olette te. En voi ymmärtää, miten kukaan
sellaisen jälkeen, kuin te olette elänyt, voi olla kunniallisen naisen
seurassa. Minä en voi sitä ymmärtää, herra Berling. Puhuinko nyt
kyllin selvästi?"
"Kyllä, kreivitär. Tahdon vain sanoa yhden ainoan sanan
puolustuksekseni. Olin vakuuttunut siitä, koko ajan olen ollut varma
siitä, että te tiesitte kaiken minusta. En ole koskaan yrittänyt salata
mitään, mutta eipä liene hauska huudella elämänsä katkerimpia
onnettomuuksia turuilla ja teillä, kaikkein vähimmin itse huudella."
Hän menee.
Ja samassa painaa kreivitär Dohna kapean jalkansa pienen,
sinitähtisen vuokkokimpun päälle.
"Sinä olet nyt tehnyt niinkuin minä toivoin", sanoo Anna Stjärnhök
kreivittärelle kylmästi, "mutta nyt tuli myös loppu ystävyydestämme.
Älä luulekaan, että minä voin antaa anteeksi sitä, että olet ollut
hänelle julma. Olet ajanut hänet pois, ivannut ja haavoittanut häntä,
ja minä, minä tahtoisin seurata häntä vankeuteen, häpeäpenkille, jos
niin vaadittaisiin. Minä tahdon vartioida häntä, säilyttää hänet. Sinä
olet tehnyt niinkuin minä tahdoin, mutta en anna sinulle koskaan
anteeksi!"
"Mutta Anna, Anna!"
"Kun äsken kerroin sinulle, niin uskotko, että tein sen iloisin mielin!
Enkö ole tässä kappale kappaleelta raastanut omaa sydäntäni
rinnasta?"
"Miksi sitten teit sen?"
"Miksi? Siksi, etten halunnut — etten halunnut, että hänestä tulee
vihityn vaimon rakastaja…"
Kolmastoista luku
MAMSELLI MARIE
Hiljaa, ihan hiljaa!
Pääni ympärillä surisee. Kai se on kimalainen, joka tulla pörisee.
Ei, hiljaa nyt! Ah, millaista tuoksua! Niin totta kuin olen tässä, eikö
se ole koimarunan ja lavendelin ja tuomen ja sireenin ja
valkonarsissien tuoksua. Ihanaa on tuntea sellaista harmaana
syysiltana, keskellä kaupunkia. Kun vain etsinkin ajatuksiini tuon
pienen, siunatun maakaistaleen, heti alkaa ympärilläni surista ja
lennellä, ja siirryn aivan huomaamattani pieneen, nelisnurkkaiseen
ruususarkaan, joka on täynnä kukkia, ligusterpensaisen aidan
takana. Nurkissa on sireenimajat ja niissä kaidat lautapenkit, ja
kukkalavain ympärillä, jotka on järjestetty sydämien ja tähtien
muotoon, kiertelevät kapeat polut, valkealla merihiekalla ripotetut.
Kolmelta puolen ympäröi ruususarkaa metsä. Pihlaja ja tuomi, nuo
puolisivistyneet ja kauniskukkaiset, seisovat likinnä ja yhdistävät
tuoksunsa sireenien lemuun. Niiden takana kohoaa muutamia
koivusikermiä, ja sitten alkaa kuusimetsä, oikea metsä, hiljainen ja
tumma ja partainen ja pistävä.
Ja neljännellä puolella on pieni, harmaa tupa.
Se ruususarka, jota minä nyt ajattelen, oli kuusikymmentä vuotta
sitten Svartsjössä Moreuksen vanhalla rouvalla, hänellä, joka elätti
itseään tikkaamalla peitteitä talonpojille ja valmistamalla ruokaa
heidän pitoihinsa.
Rakkaat ystävät! Kaikesta hyvästä, jota teille toivon, mainitsen
ensiksi tikkauspuut ja ruususaran. Suuret, huojuvat, vanhanaikaiset
tikkauspuut, joissa on somat linkut ja kuluneet rissat, minä toivon
teille, sellaiset, joiden ympärillä viisi, kuusi henkeä voi yhtaikaa
työskennellä, joiden ääressä ommellaan kilpaa ja koetellaan, kuka
saa kauniimmat pisteet nurealle puolelle; joiden ääressä syödään
omenapaistikkaita ja rupatellaan ja "matkustetaan Grönlantiin" ja
"kätketään sormusta", ja nauretaan niin, että oravat metsässä
nakkelevat kuperkeikkaa pelästyksestä. Tikkauspuut talveksi, rakkaat
ystävät, ja ruususarka kesäksi! Ei puutarhaa, johon uppoaa rahaa
enemmän kuin huvi kannattaa, ei, vaan ruususarka, kuten ennen
maailmassa sanottiin. Sellainen pitää teillä olla, sellainen jota voitte
hoidella omin käsin. Pienoisten orjanruusupensaiden tulee siellä
rehottaa pienten maakumpareiden huipulla, ja lemmikkirivin kierrellä
niiden juurella; suuri, lehahtava unikko, joka kylvää itse itsensä,
leviää siellä kaikkialle, sekä ruohoreunustalle että hiekkakäytävälle,
ja siellä pitää olla ruskeaksi kulottunut turvesohva, jossa kasvaa
akilleioja ja keisarinkruunuja, sekä istuimella että selkänojalla.
Vanhalla Moreuksen rouvalla oli ennen aikaan paljon hyvää.
Hänellä oli kolme iloista ja ahkeraa tytärtä sekä pieni tupa
tienposkessa. Hänellä oli kirstunpohjalla säästöjä, hänellä oli jäykkiä
silkkisaaleja, suoraselkäisiä nojatuoleja ja tietoja monenlaisista
asioista, mitkä ovat tarpeellisia tietää sellaisen, jonka itse täytyy
hankkia leipänsä.
Mutta parhainta olivat hänen tikkauspuunsa, jotka tuottivat hänelle
työtä läpi vuoden, ja ruususarka, joka antoi hänelle iloa koko kesän
ajan.
Ja nyt on kerrottava, että Moreuksen rouvan pienessä tuvassa eleli
vuokralainen, pieni kuiva mamselli, nelikymmenvuotias, joka asui
ullakkokamarissa. Mamselli Mariella, joksi häntä aina sanottiin, oli
omat käsityksensä monista asioista, kuten usein on sellaisella
ihmisellä, joka oleksii paljon yksinään ja antaa ajatuksensa
pyöriskellä havaitsemissaan asioissa.
Mamselli Marie uskoi, että rakkaus on kaiken pahan alku tässä
matoisessa maailmassa.
Joka ilta hän ennen nukkumistaan pani kätensä ristiin ja luki
iltarukouksensa. Luettuaan "Isä meidän" ja "Herra siunatkoon
meitä", hän päätti aina rukouksensa pyytämällä Jumalaa
varjelemaan häntä rakkaudesta.
"Siitä vasta viheliäisyyttä koituisi", hän sanoi. "Minä olen vanha ja
ruma ja köyhä. Ei, kunpa vain säästyisin rakastumasta!"
Hän istui päivät päästään Moreuksen rouvan pienessä
yliskamarissa ja koukkusi ikkunaverhoja ja suomusvirkkauksia. Ne
hän sitten myi emännille ja herrasväelle. Hän koukkusi sillä tavoin
itselleen tupaa.
Sillä pieni tupa, töyrylle vastapäätä Svartsjön kirkkoa, hänen piti
saada, tupa, joka olisi niin korkealla paikalla, että sieltä voi nähdä
mukavasti kauas; se oli hänen unelmansa. Mutta rakkaudesta hän ei
tahtonut kuulla puhuttavan.
Kun hän kesäiltoina kuuli viulun soivan tienhaarassa, missä peluri
istui veräjälaudalla ja nuori väki hölkkäsi polkkaa niin että tanner
pölisi, silloin hän kaarsi pitkät matkat metsän kautta päästäkseen
kuulemasta ja näkemästä moista.
Toisena joulupäivänä, kun maalaismorsiamia tuli viisin ja kuusin
Moreuksen rouvan ja hänen tyttäriensä luo puetuttamaan itseään;
jolloin heidät koristettiin myrttiseppeleillä ja korkeilla silkkisillä ja
lasihelmisillä kruunuilla ja koreilla silkkivöillä, pantiin rintaan
kotitekoiset ruusunkimput ja hame reunustettiin taftikankaisilla
kiehkuroilla, silloin hän pysyi itsepintaisesti huoneessaan
päästäkseen näkemästä, miten toisia hepenöitiin rakkauden
kunniaksi.
Kun Moreuksen tytöt istuivat talvi-iltoina tikkauspuiden ääressä ja
suuri, porstuan vasemmalla puolella oleva huone säteili kodikkuutta,
kun lasiomenat heiluivat ja hikoilivat uunin luona tulen loimuun
ripustettuina, kun kaunis Gösta Berling tai kiltti Ferdinand, jotka
olivat tulleet vieraisille, aina kepposiin valmiina nykäsivät tytöiltä
rihman neulansilmästä tahi narrasivat heidät ompelemaan vääriä
pistoksia; ja kun huone raikui iloa ja remua ja kuhertelua ja kädet
puristelivat toisiaan tikkauspuiden alla, silloin kääri mamselli Marie
ärtyneenä neuleensa kokoon ja meni tiehensä, sillä hän vihasi
rakkautta ja rakkauden teitä.
Mutta rakkauden ilkiteot hän tunsi, ja niistä hän tiesi kertoella.
Hän ihmetteli, että rakkaus vielä tohti näyttäytyä maan päällä, ettei
sitä karkottanut täältä hyljättyjen valitus ja niiden kiroukset, jotka se
oli tehnyt rikollisiksi, eikä niiden vaikerrukset, jotka se oli kytkenyt
vihattaviin kahleihin. Hän ihmetteli, miten sen siivet saattoivat
kantaa niin vapaasti ja keveästi, miten se ei tuskan ja häpeän
painamana jo uponnut nimettömiin syvyyksiin.
Ei, nuori hän oli ollut kuten kaikki muutkin, mutta rakkautta hän ei
ollut koskaan maistanut. Koskaan hän ei ollut antanut houkutella
itseään tanssiin ja hyväilyihin. Hänen äitinsä kitara riippui pölyisenä
ja kielettömänä ullakolla. Koskaan hän ei ollut näpännyt sitä vienoon
lemmenvirteen.
Hänen äitinsä ruusupuut kasvoivat hänen ikkunallaan. Hän antoi
niille nipin napin vettä. Hän ei rakastanut kukkia, noita lemmen
lapsia. Niiden lehdet riippuivat tomuisina. Hämähäkit keikkuivat
oksien välissä, ja nuput eivät koskaan puhjenneet.
Ja Moreuksen rouvan ruususaralle, jossa perhot liehuivat ja linnut
lauloivat, jossa tuoksuvat kukkaset lähettivät lemmenviestejä
lentäville mehiläisille, jossa kaikki puhui tuosta vihattavasta, sinne
hän harvoin pisti jalkansa.
Tulipa sitten aika, jolloin Svartsjön kunta panetti urut kirkkoonsa.
Se oli sen vuoden edellisenä kesänä, jolloin valta oli kavaljeerien
käsissä. Paikkakunnalle tuli nuori urkujenrakentaja. Ja hänkin tuli
rouva Moreukselle asumaan, ja hänet sijoitettiin toiseen pieneen
ullakkokamariin.
Ja sitten hän asetti paikoilleen nuo urut, joilla on niin ihmeelliset
äänet, joiden hirmuinen pasuuna tuon tuostakin vongahtaa keskellä
rauhallista virttä — kuka ties miksi ja miten — ja pelästyttää lapset
joulukirkossa itkemään.
Oliko nuori urkujenrakentaja alallaan mestari, sitä epäiltäköön
kernaasti. Mutta iloinen velikulta hän oli ainainen päivänpaiste
silmissään. Hän puheli aina ystävällisesti kaikille, rikkaalle ja
köyhälle, vanhalle ja nuorelle. Hänestä tuli pian talonväkensä hyvä
ystävä, ah, enemmän kuin ystävä.
Kun hän iltaisin tuli kotiin työstä, hän piteli Moreuksen rouvan
lankavyyhteä ja aherteli nuorten tyttöjen apuna ruususaralla. Hän
lausuili "Axelia" ja lauloi "Frithiofia". Hän poimi maasta mamselli
Marien lankakerän, pudottipa tämä sen miten usein tahansa, ja
korjasi vielä hänen pöytäkellonsakin käymään.
Hän ei hellittänyt yksissäkään tanssiaisissa ennen kuin oli
tanssittanut kaikki naiset, vanhimmasta rouvasta nuorimpaan
tyttöseen, ja jos vastoinkäyminen häntä kohtasi, hän istahti heti
ensiksi näkemänsä naisen viereen, olipa tämä kuka tahansa, ja teki
hänestä uskottunsa. Niin, hän oli sellainen mies, joita naiset luovat
unelmissaan! Älköön hänestä sanottako, että hän puhui kenenkään
kanssa rakkaudesta. Mutta kun hän oli vain pari viikkoa asunut
Moreuksen rouvan ullakkokamarissa, olivat kaikki tytöt rakastuneet
häneen, ja mamselli Marie parka tiesi, hänkin, rukoilleensa turhaan.
Ne olivat surun päiviä ja riemun päiviä. Kyynelet tippuivat
tikattavalle kankaalle ja huuhtoivat liituviivat pois. Iltaisin istui
tavallisesti joku kalpea uneksijatar sireenimajassa, ja mamselli
Marien pienessä ullakkokamarissa näppäiltiin äskenviritettyä kitaraa
vienoihin lemmen virsiin, joita hän oli oppinut äidiltään.
Nuori urkujenrakentaja heippaili talossa yhtä suruttomana ja
iloisena kuin ennenkin ja siroitteli hymyjä ja palveluksia noille
riutuneille naisille, jotka kiistelivät hänestä kun hän oli poissa kotoa
työssään. Ja viimein tuli päivä, jolloin hänen oli matkustettava pois.
Kyytihevonen seisoi kuistin edessä. Matkalaukku oli köytetty
kärryjen takalautaan, ja nuori mies teki jäähyväiset. Hän suuteli
rouva Moreuksen kättä ja sulki itkevät tytöt syliinsä ja suuteli heitä
poskelle. Hän itsekin itki sitä, että hänen oli pakko lähteä, sillä hänen
kesänsä oli ollut päivänpaistetta siinä pienessä, harmaassa tuvassa.
Viimein hän alkoi katsella, missä mamselli Marie oli.
Silloin mamselli tulikin alas vinnin kapeita portaita, parhaassa
asussaan. Kitara riippui hänen kaulassaan leveässä, viheriässä
silkkinauhassa, ja kädessä hänellä oli ruusunippu, sillä tänä vuonna
olivat hänen äitinsä ruusut kukkineet. Hän pysähtyi nuoren miehen
eteen, näppäsi kitaraansa ja lauloi:
"Sa lähdet pois. Tervetuloa taas!
Ole, rakkahin, murheita vailla!
Äl' unhoita armasta tuttavaas,
joka huokaa Vermlannin mailla!"
Sitten hän pisti kukat hänen napinläpeensä ja suuteli häntä
suoraan suulle. Ja niin: sitten hän katosi taas ullakolle, tuo vanha
ilmestys.
Rakkaus oli kostanut hänelle ja tehnyt hänestä yleisen naurun
kohteen. Mutta hän ei moittinut enää koskaan rakkautta. Hän ei
heittänyt enää koskaan kitaraa joutilaaksi eikä unohtanut koskaan
vaalia äitinsä ruusupuita.
* * * * *
Aika vieri. Ekebyn majurinrouva karkotettiin talostaan, kavaljeerit
pääsivät valtaan, ja tapahtui sitten, niinkuin taannoin on tarinoitu,
että Gösta Berling eräänä sunnuntai-iltana luki nuorelle Borgin
kreivittärelle runon, jonka jälkeen kreivitär kielsi häntä
näyttäytymästä kodissaan.
Kerrotaan, että kun Gösta sinä iltana talosta lähtiessään sulki
eteisen oven, niin hän näki pari kolme rekeä tulevan Borgin pihaan.
Hän katsahti pientä naista, joka istui etumaisessa reessä. Jos hän jo
ennestäänkin oli synkkä, niin vielä synkemmäksi hän tämän
nähdessään tuli. Hän kiiruhti pois, ettei häntä tunnettaisi, mutta
onnettomuuden aavistus täytti hänen mielensä. Olivatko juuri nuo
äskeiset puheet mananneet tänne tämän naisen? Ei onnettomuus
mene ilman toista onnettomuutta.
Mutta palvelijat kiiruhtivat ulos, rekipeitot päästettiin, vällyt
leväytettiin auki. Ken oli tuo tulija? Kuka oli tuo pieni nainen, joka
nyt nousi seisomaan reessä? Ah, se on todellakin itse Märta Dohna,
tuo kuuluisa kreivitär!
Hän oli naisista hupaisin ja huimamielisin. Maailman ilo oli
nostanut hänet valtaistuimelleen ja kruunannut hänet
kuningattarekseen. Leikit ja sulohymyt olivat hänen alamaisiaan.
Soitto ja tanssi ja seikkailu olivat sattuneet hänen osakseen silloin,
kun elämän arpaa heitettiin.
Hän oli nyt jo melkein viisissäkymmenissä, mutta hän oli niitä
viisaita, jotka eivät laske vuosien lukua. "Se, jonka jalka ei nouse
tanssiin tai suu sula hymyyn", hän sanoi, "on vanha. Se tuntee
vuosien kamalan painon, mutta en minä."
Ilolla ei suinkaan ollut vakaata valtaistuinta hänen nuoruutensa
päivinä, mutta vaihtelu ja epävarmuus lisäsivät vain elämän
suloisuutta. Ilon perhossiipinen majesteetti piti yhtenä päivänä
kahvikekkerit hovinaisten saleissa Tukholman linnassa ja tanssi
huomispäivänä hännystakissa ja pahkasauva kourassa Pariisissa. Se
käväisi Napoleonin kenttäleirissä, se matkasi Nelsonin laivastossa
sinisellä Välimerellä, se käväisi Wienin kongressissa, se uskalsi
Brysseliin tanssiaisiin erään kuuluisan taistelun edellisenä yönä.
Ja missä ikinä ilo oleksi, siellä oli Märta Dohna, hänen
valiokuningattarensa. Soitellen, tanssien, ilveillen samosi kreivitär
Märta ympäri maailmaa. Mitä ei hän olisi nähnyt, mitä elänyt? Hän
oli tanssinut kumoon valtaistuimia, pelannut écartéta[10]
ruhtinaskunnista, sytytellyt pilahuulin hävittäviä sotia! Hilpeyttä ja
hullutusta oli hänen elämänsä ollut ja oli edelleen oleva. Ei ollut
hänen ruumiinsa liian vanha tanssimaan, ei hänen sydämensä liian
vanha lempimään. Milloin hän väsyisi naamiaisiin ja huvinäytelmiin,
hupaisiin tarinoihin ja kaihoisiin lauluihin?
Kun ilo joskus jäi kodittomaksi maailmassa, joka oli muuttunut
sotatantereeksi, se vetäytyi pitemmäksi tai lyhemmäksi aikaa
vanhaan kreivinhoviin Lövenin pitkän järven rannalle. Samoin
matkasi kreivitärkin sinne silloin, kun ruhtinaat ja hovit kävivät
hänestä pyhän allianssin aikana liian synkiksi. Tällaisella käynnillä
hän oli nähnyt hyväksi ottaa Gösta Berlingin kotiopettajaksi
pojalleen. Kreivitär viihtyi kyllä täällä pohjoisessa. Missään ei ilolla
ollut ihanampaa valtakuntaa. Siellä oli laulua ja soittoa,
seikkailunhaluisia miehiä ja kauniita, iloisia naisia. Siellä siltä ei
puuttunut pitoja ja tanssiaisia, ei venematkoja kuutamoisilla järvillä,
ei rekiretkiä halki tummain metsäin, ei myöskään sydäntä järisyttäviä
tapahtumia ja rakkauden tuskaa ja vaivaa.
Mutta tyttärensä kuoltua oli kreivitär lakannut käymästä Borgissa.
Hän ei ollut nähnyt sitä viiteen vuoteen. Nyt hän tuli katsomaan,
jaksoiko hänen miniänsä elää kuusikkojen, karhujen ja lumikinosten
keskellä. Hänestä oli hänen velvollisuutensa mennä katsomaan, eikö
tuhma Henrik ollut jo kiduttanut kuivuudellaan nuorta kreivitärtä
kuoliaaksi. Nyt hän tahtoi tulla kotirauhan laupiaaksi enkeliksi.
Päivänpaiste ja onni oli tuotu mukaan ladottuina hänen
neljäänkymmeneen nahkaiseen matkalaukkuunsa, hupi oli hänen
kamarineitsyensä, pila hänen kuskinsa, leikki hänen seuranaisensa.
Ja kun hän juoksi ylös portaita, otettiin hänet avosylin vastaan.
Hänen entinen huoneensa alakerrassa odotti häntä. Hänen
palvelijansa, seuranaisensa ja kamarineitsyensä, hänen
neljäkymmentä nahkaista matkalaukkuaan, hänen kolmekymmentä
hatturasiaansa, hänen toalettivehkeensä, monet saalinsa ja
turkkinsa, kaikki ne saatiin vähitellen huoneeseen. Siitäkös riitti
touhua ja hälinää! Ovet paukkuivat ja portaissa juostiin. Kyllä näki,
että kreivitär Märta oli tullut.
* * * * *
Oli kerran keväinen ilta, oikein kaunis ilta, vaikkei vielä ollut kuin
huhtikuu parhaillaan, eikä jää ollut vielä lähtenyt. Mamselli Marie oli
avannut ikkunansa. Hän istui huoneessaan, näppäili kitaraansa ja
lauloi.
Hän oli niin kiintynyt kitaraansa ja muistoihinsa, ettei huomannut,
että vaunut vierivät tiellä ja pysähtyivät tuvan eteen. Vaunuissa istui
kreivitär Märta, ja hänestä oli aika hauskaa nähdä, kuinka mamselli
Marie istui ikkunassaan, kitaranauha kaulassa ja silmät käännettyinä
taivasta kohti, ja lauloi vanhoja, kuluneita rakkauslauluja.
Viimein laskeusi kreivitär vaunuista ja meni tupaan, jossa nuo kiltit
tytöt istuivat peitettä tikkaamassa. Hän ei ollut koskaan ollut kopea:
vallankumouksen tuuli oli puhaltanut häneen ja täyttänyt hänen
keuhkonsa raikkaalla ilmalla.
Hän ei voinut sille mitään, että oli kreivitär, oli hänen tapanaan
sanoa; mutta joka tapauksessa hän aikoi elää sellaista elämää, joka
häntä miellytti. Hänellä oli yhtä hauska talonpoikaishäissä kuin
hovitanssiaisissa. Hän näytteli hovinäytelmiä piioilleen, kun ei muita
katselijoita ollut saapuvilla, ja toi tullessaan riemua seuraan, mihin
kulloinkin ilmestyi pienine somine kasvoineen ja kuohuvine
elämäntunteineen.
Hän tilasi peitteitä Moreuksen rouvalta ja kehui tyttäriä. Hän
katseli ruususarkaa ja kertoi matkaseikkailujaan. Hänellä oli aina
seikkailuja, tällä kreivittärellä. Ja viimein hän tohti nousta ullakon
portaille, jotka olivat pelottavan jyrkät ja kaidat, ja meni mamselli
Marien luo hänen päätykamariinsa.
Siellä hän väläytteli mustia silmiään tuon yksinäisen pikku olennon
edessä ja antoi sulosointuisen äänensä hyväillä tämän korvia.
Hän osti Marielta uutimia. Hän ei voinut elää Borgissa, jollei hänen
kaikissa ikkunoissaan ollut suomussilmäisiä verhoja ja joka pöydällä
mamselli Marien virkkaamaa liinaa.
Hän lainasi sitten hänen kitaraansa ja lauloi hänelle riemusta ja
rakkaudesta. Ja hän kertoi hänelle juttuja, ja mamselli Marie
huomasi ennen pitkää liitävänsä keskellä hauskaa, humuavaa
maailmaa. Ja kreivittären nauru oli sellaista musiikkia, että
kohmettuneet lintuset ruususaralla alkoivat sen kuullessaan laulaa, ja
hänen kasvonsa, jotka tuskin enää olivat kauniit — sillä ihomaali oli
turmellut hipiän, ja suupielissä oli aistillisuuden piirteitä — näyttivät
mamselli Mariesta niin kauniilta, että hän ihmetteli, kuinka pikku peili
hennoo ne jälleen kadottaa, saatuaan ne kerran kiiltävälle pinnalleen
vangituiksi.
Lähtiessään hän suuteli mamselli Marieta ja pyysi tätä käymään
Borgissa.
Mamselli Marien sydän oli autio kuin pikku pääskysten pesä
joulunaikaan. Hän oli vapaa, mutta hän halusi kahleita kuin
vanhuuden päivillä vapaaksi päästetty orja.
Nyt koittivat taaskin riemun päivät ja surun päivät mamselli
Marielle; mutta ei pitkät, ainoastaan kahdeksan lyhyttä päivää.
Kreivitär nouti hänet vähän väliä Borgiin. Hän näytteli hänelle
huvinäytelmiään ja kertoi kosijoistaan, ja mamselli Marie nauroi niin,
ettei siten ollut ikänään nauranut. Heistä tuli iki-hyvät ystävät.
Kreivitär sai pian tietää kaikki nuoresta urkujenrakentajasta ja
jäähyväisistä. Ja hämärissä hän antoi mamselli Marien istua sinisen
pikku kabinetin ikkunakomerossa. Ja hän pujotti kitarannauhan
hänen kaulaansa ja sai hänet laulamaan lemmenlauluja. Sitten istui
kreivitär katsellen, miten ikäneidon kuiva, laiha vartalo ja pieni, ruma
pää kuvastuivat punaista iltavalaistusta vasten, ja hän sanoi, että
mamselliraukka muistuttaa riutuvaa linnanneitoa. Mutta jokainen
laulu tarinoi hellistä paimenista ja julmista paimentytöistä, ja
mamselli Marien ääni oli kovin ohut ja kovin kimeä, ja voi hyvin
ymmärtää, että kreivitär iloitsi sellaisesta ilveilystä.
Ja sitten hommattiin Borgiin kemut, kuten luonnollista, koska
kerran kreivin äiti oli tullut kotiin. Ja oli hauskaa kuten tavallisesti.
Vierasjoukko ei ollut kuitenkaan suuri. Sinne oli kutsuttu ainoastaan
oman pitäjän väkeä.
Ruokasali oli alakerrassa, ja illallisen jälkeen sattui, etteivät vieraat
nousseet yläkertaan, vaan jäivät alas kreivitär Märtan huoneisiin,
jotka olivat ruokasalin takana. Ja kreivitär sai käsiinsä mamselli
Marien kitaran ja alkoi laulaa vieraille. Hän oli hupainen nainen, tuo
kreivitär, ja osasi matkia ketä tahansa. Nyt hänen päähänsä pälkähti
matkia mamselli Marieta. Hän kohotti silmänsä taivasta kohti ja alkoi
ohuella, kimakalla lapsenäänellä laulaa.
"Älkäähän, kreivitär!" rukoili Marie.
Mutta kreivittärellä oli hauskaa, ja vieraat eivät voineet olla
nauramatta, niin surkeata kuin se olikin mamselli Marien kannalta.
Kreivitär otti käsityölippaasta kourallisen kuihtuneita ruusunlehtiä,
astui traagillisin elein mamselli Marien luo ja lauloi syvästi
liikuttuneella äänellä:
"Sa lähdet pois. Tervetuloa taas!
Ole, rakkahin, murheita vailla!
Äl' unhoita armasta tuttavaas,
joka huokaa Vermlannin mailla!"
Sitten hän ripotteli ruusunlehdet hänen päähänsä. Ihmiset
nauroivat; mutta mamselli Marie raivostui. Näytti kuin hän olisi
tahtonut repiä kreivittäreltä silmät päästä.
"Sinä olet huono nainen, Märta Dohna", hän sanoi. "Kenenkään
kunniallisen naisen ei sopisi seurustella sinun kanssasi."
Kreivitär Märta suuttui nyt hänkin.
"Ulos, mamselli!" hän sanoi. "Olen kyllästynyt hupsutuksiisi."
"Kyllä minä menenkin", sanoi mamselli Marie, "mutta ensin minun
pitää saada maksu liinoista ja uutimista, jotka olet tänne ripustellut."
"Vanhoista rääsyistä!" huusi kreivitär. "Tahtooko hän maksua
sellaisista rääsyistä? Ota ja vie ne! En tahdo nähdä niitä enää
silmissäni! Ota heti ja vie!"
Sitten nakkaa kreivitär hänelle liinat ja repii alas uutimet, sillä nyt
hän on raivon vallassa.
Seuraavana päivänä pyysi nuori kreivitär anoppiaan sopimaan
mamselli Marien kanssa; mutta kreivitär ei tahtonut. Hän oli
kyllästynyt mamselliin.
Elisabet kreivitär lähti silloin itse ja osti mamselli Marielta koko
uudinvaraston ja koristi niillä kaikki yläkerran ikkunat. Niin mamselli
Marie tyytyi ja sai hyvityksen.
Kreivitär Märta laski sitten monta kertaa leikkiä miniänsä
mieltymyksestä suomusneuleihin. Hän osasi myös kätkeä vihansa —
säilyttää sitä tuoreena ja uutena vuosikausia. Hän oli varsin lahjakas
nainen.
JÄLKIMMÄINEN OSA
Ensimmäinen luku
KRISTOFFER-SERKKU
Heillä oli vanha petolintu siellä kavaljeerien rakennuksessa. Hän
istui aina uuninnurkassa ja vaali takkavalkeaa, ettei se päässyt
sammumaan. Pörröinen ja harmaa hän oli. Pieni pää, jossa oli iso
nokka ja sammuvat silmät, nuokkui surullisesti pitkän, laihan kaulan
päässä, joka pisti esiin tuuheasta turkinkauluksesta. Sillä
petolintumme kulki turkki yllään sekä kesällä että talvella.
Muinoin hän oli kuulunut siihen parveen, joka samosi suuren
keisarin seurassa saalista ajaen yli Euroopan; mutta hänen nimeään
ja arvoaan ei kukaan nykyjään uskalla käydä arvailemaan.
Vermlannissa tiedettiin vain, että hän oli ollut noissa suurissa
sodissa, että hän oli mahtavasti riehunut jylisevissä taisteluissa ja
että hänen vuoden 1815 jälkeen täytyi suunnata siipiensä lento pois
kiittämättömästä isänmaastaan. Hän sai suojaa Ruotsin
kruununprinssin hovissa ja tämä neuvoi häntä kaukaiseen
Vermlantiin. Sellainen oli aika, että hän, jonka nimi muinoin oli
pannut maailmat vapisemaan, sai nyt olla iloinen, kun ei kukaan
tuntenut enää hänen nimeään, tuota aikoinaan niin pelättyä.
Hän oli kunniasanalla luvannut kruununprinssille, ettei lähtisi
Vermlannista eikä mainitsisi tarpeettomasti kuka oli. Ja niin hänet
lähetettiin Ekebyhyn, kädessään kruununprinssin omakätinen
kirjelmä majurille, jossa suositeltiin häntä mitä lämpimimmin. Silloin
aukaisi kavaljeerirakennus hänelle ovensa.
Aluksi arvailtiin innokkaasti, kuka oli tuo kuuluisuus, joka kätkeytyi
uuden, tekaistun nimen taakse. Mutta vähitellen hän muuttui
kavaljeeriksi ja vermlantilaiseksi. Kaikki sanoivat häntä Kristoffer-
serkuksi, tietämättä oikein kuinka hän oli saanut juuri tämän nimen.
Mutta ei ole petolinnun hyvä elää häkissä. Ymmärtää, että se on
tottunut muuhun kuin hyppäämään pienalta pienalle ja ottamaan
ruokansa hoitajan kädestä. Alituinen kuolemanvaara on muinoin
sytyttänyt hänen valtimonsa tuleen. Häntä iljettää tämä untelo
rauha.
On kyllä totta, etteivät nuo toisetkaan kavaljeerit olleet juuri
kesyjä lintuja; mutta kenenkään veri ei ollut kiehunut niin kuumana
kuin Kristoffer-serkun. Vain karhunjahti saattoi elähyttää hänen
lamaantunutta elinintoaan, karhunjahti tahi nainen, yksi ainoa
nainen.
Hän oli vironnut henkiin kymmenen vuotta sitten nähtyään ensi
kerran Märta-kreivittären, joka silloin jo oli leski. Nainen,
vaihtelevainen kuin sotaonni, kiihoittava kuin vaara, räiskyvä,
ylimielinen olento — sotaurho rakasti häntä.
Ja nyt hän istui siellä ja vanheni ja harmeni voimatta pyytää häntä
vaimokseen. Hän ei ollut nähnyt häntä viiteen vuoteen. Hän kuihtui
ja riutui vitkalleen, niin kuin vangitut kotkat riutuvat. Vuosi vuodelta
hän kävi yhä kuivemmaksi ja viluisemmaksi. Hänen täytyi piiloutua
paremmin turkkiinsa ja vääntäytyä lähemmäksi takkaa.
* * * * *
Niin hän istuu siellä, viluisena, pörröisenä ja harmaana senkin
päivän aamuna, jonka iltana pääsiäispaukut ammutaan ja poltetaan
pääsiäisakka. Kavaljeerit ovat kaikki kylillä, mutta hän istuu kotona
uuninnurkassa.
Oi, Kristoffer-serkku, Kristoffer-serkku, etkö sinä sitä tiedä?
Hymyillen on tullut viettelevä kevät.
Hereille kapsahtaa luonto untelosta unestaan, ja sini-ilmoissa
hulmuavat perhossiipiset henget huimassa leikissä. Lukemattomina
kuin villipensaan ruusut kimmeltävät heidän muotonsa ylhäältä
hattaroiden lomista.
Maa, suuri emo, alkaa elää. Huimana kuin lapsi hän nousee
kevätvirran kylvystä, kevätsateiden vihman alta. Kivet ja multa
kimaltavat halusta. "Ylös, elon kiertokulkuun!" riemuitsee pieninkin
hiukkanen. "Me matkaamme kuin siivet kirkkaassa ilmassa. Me
helotamme nuorten tyttöjen punehtuvilla poskilla."
Kevään hupaisat henget uivat ilman ja veden mukana ruumiiseen,
hyppivät kuin ankeriaat veressä, panevat sydämen ailahtamaan.
Samaa ääntä on kaikkialla. Sydämiin ja kukkiin, kaikkeen, joka häilyy
ja väräjää, tarttuvat nuo perhossiipiset ja soittavat yhä kuin tuhansin
myrskynkelloin: "Intoa ja iloa, huvia ja iloa! Tullut on hän, hymyilevä
kevät!"
Mutta Kristoffer-serkku istuu sopessaan eikä ymmärrä mitään. Hän
nojaa päänsä jäykistyneihin sormiinsa ja uneksii kuulatuiskuista ja
taistotanterella kasvaneesta kunniasta. Sisäisen silmänsä eteen hän
loihtii laakereita ja ruusuja, jotka eivät kukoistaakseen kaipaa kevään
vienoa ihanuutta.
Sääli on kumminkin häntä, tuota yksinäistä, vanhaa tungeksijaa,
joka istuu ylhäällä kavaljeerien rakennuksessa, ilman kansaa, ilman
maata; sääli häntä, joka ei koskaan kuule kotimaansa kielen sointua,
häntä, joka saa nimettömän haudan Bron kirkkomaalla. Voiko hän
mitään sille, että on kotka ja syntynyt vainoamaan, tappamaan?
Oi, Kristoffer-serkku, olet jo kyllin kauan istunut uneksien
kavaljeerirakennuksessa! Nouse ja juo elämän pulppuavaa viiniä
uljaiden linnojen saleissa. Tiedä, serkku Kristoffer, että tänä päivänä
on majurille tullut kirje, kuninkaallinen kirje, joka on suljettu Svean
kuningaskunnan sinetillä. Se on osoitettu majurille, mutta sisältö
koskee sinua. Merkillistä nähdä kuinka sinä, vanha petolintu, luet
kirjettä. Silmä syttyy loistoon ja pää kohoaa. Näet häkin ovien
avautuvan ja avaruuden leviävän kaipaavien siipiesi nousta.
* * * * *
Kristoffer-serkku kaivaa ja penkoo vaatekirstunsa pohjia. Hän
vetää esiin kultakoristeisen univormunsa, jota on säilyttänyt kuin
silmäteräänsä, ja pukeutuu siihen. Hän painaa töyhtökorskan hatun
päähänsä ja kiitää pian Ekebystä pois, ratsastaen mainiolla valkealla
ratsullaan.
Tämä on toki toista kuin istua viluisena uuninnurkassa. Nyt näkee
hänkin, että kevät on tullut.
Hän kohottautuu satulassa ja laskee laukkaa. Turkitettu dolma,
husaarijakku hulmuaa. Lakin töyhtö häilyy. Nuortunut on mies kuten
maaemo itse. Herännyt on hän pitkästä talvesta. Vanha kulta voi
vielä välähdellä. Nuo rohkeat sotilaskasvot ovat kolmikulmaisen lakin
alla ylväs näky.
Ihmeellistä on hänen ratsastuksensa. Maasta pulppuaa puroja, ja
vuokkoja versoo mistä hän ratsastaa. Muuttolinnut kirkuvat ja
riemuitsevat vapautetun vangin ympärillä. Koko luonto yhtyy hänen
iloonsa.
Komeana kuin triumfaattori hän tulee. Itse kevät ratsastaa edeltä
väikkyvällä pilvellä. Kevyt ja ilmava on hän, tuo valon henki. Hänellä
on käyrätorvi huulillaan, ja hän hypähtelee ilosta, keikkuen ylös alas
satulassaan. Ja Kristoffer-serkun ympärillä tepastelee esikunta
vanhoja asetovereja hevosineen: onni on varpaillaan satulassa, ja
kunnia uljaan juoksijansa selästä, ja rakkaus kiitää tulisella Arabian
orhilla. Ihmeellistä on ratsastus; ihmeellinen ratsastaja. Kielitaitoinen
lahorastas huutaa hänelle:
"Kristoffer-serkku, Kristoffer-serkku. Minne ratsastat? Minne
ratsastat?"
"Borgiin kosimaan, Borgiin kosimaan", vastaa Kristoffer-serkku.
"Älä mene Borgiin, älä mene Borgiin! Poikamiehellä ei surua",
huutaa lahorastas perästä.
Mutta hän ei kuule varoitusta. Hän karauttaa mäet ylös, mäet alas,
kunnes vihdoinkin saapuu perille. Hän hypähtää alas satulasta, ja
hänet viedään saliin kreivitärten luo.
Kaikki käy hyvin. Märta-kreivitär on hänelle armollinen. Kristoffer-
serkku näkee kyllä, ettei kreivitär halua kieltäytyä kantamasta hänen
loistavaa nimeään eikä hallitsemasta hänen linnassaan. Soturi
puhelee ja lykkää tuonnemmaksi sen hurman hetken, jolloin hän on
näyttävä kreivittärelle kuninkaallisen kirjeen. Hän nauttii tästä
odotuksesta.
Kreivitär pakisee ja hauskuuttaa häntä tuhansin jutuin. Kristoffer-
serkku nauraa kaikelle, ihmettelee kaikkea. Mutta koska he istuvat
eräässä niistä huoneista, joihin kreivitär Elisabet on ripustanut
mamselli Marien uutimia, alkaa kreivitär kertoa myöskin niistä. Ja
hän vääntää tapahtuman niin hauskaksi kuin voi.
"Nähkääs", hän sanoo lopulta, "niin ilkeä minä olen. Täällä
riippuvat nyt nämä uutimet, jotta joka päivä ja joka hetki ajattelisin
syntiäni. Se on tavatonta parannuksen tekoa. Hyi näitä kauhistavia
suomusneuleita!"
Suuri Kristoffer-serkku katsoo häneen palavin silmin.
"Minä olen myöskin vanha ja köyhä", hän sanoo, "ja olen
kymmenen vuotta istunut takan ääressä kaivaten rakastettuani.
Nauraako armollinen kreivitär sillekin?"
"Oh, se on toinen asia", huudahtaa kreivitär.
"Jumala on ottanut minulta onnen ja isänmaan ja pakottanut
minut syömään vierasta leipää", sanoo Kristoffer-serkku vakavasti.
"Minä olen saanut oppia kunnioittamaan köyhyyttä, minä."
"Oh, tekin", huudahtaa kreivitär kohottaen käsiään. "Miten ihmiset
ovat hurskaita. Ah, miten ihmiset ovat tulleet hurskaiksi!"
"Niin", sanoo Kristoffer-serkku, "pankaa mieleenne, kreivitär, että
jos Jumala antaa minulle vielä kerran rikkautta ja valtaa, niin
osaanpa käyttää niitä paremmin kuin jakaa ne jonkun
maailmannaisen kanssa, tuollaisen maalatun, sydämettömän
marakatin, joka pilkkaa köyhyyttä."
"Olettepa vallan oikeassa, Kristoffer-serkku."
Ja niin marssii Kristoffer-serkku ulos huoneesta ja ratsastaa
takaisin Ekebyhyn; mutta henget eivät seuraa häntä, lahorastas ei
huuda hänelle, eikä hän enää voi nähdä hymyilevää kevättä.
Ekebyhyn hän tuli juuri kun pääsiäispaukut piti laukaistaman ja
pääsiäisakka poltettaman. Pääsiäisakka on suuri olkinukke, jonka
riepunaamaan on hiilellä piirretty silmät, nenä ja suu. Ja yllään sillä
on ruotuämmän joutovaatteet. Pitkävartinen hiilihanko ja luuta on
asetettu sen viereen, ja rasvasarvi riippuu sen kaulassa. Se on aivan
valmis Kyöpelin matkalle.
Majuri Fuchs lataa pyssynsä ja laukoo sen kerta toisensa jälkeen
suoraan ilmaan. Kuiva risurovio sytytetään, noita-akka heitetään
tuleen ja palaa iloisesti hulmuten. Kavaljeerit kyllä tekevät kaiken
voitavansa hävittääkseen pahuuden voimia vanhalla koetellulla
tavallaan.
Kristoffer-serkku seisoo ja katsoo tuikeasti roviota. Äkkiä hän
tempaa suuren kuninkaallisen kirjeen hihansa käänteestä ja nakkaa
sen tuleen. Jumala yksin tietää, mitä hän ajatteli. Kenties hän
kuvitteli, että Märta kreivitär itse paloi tuossa roviolla. Kenties hän
ajatteli, että koska se nainen sittenkin oli vain rääsyjä ja olkia, niin ei
maailmassa enää ollut mitään muutakaan arvokasta.
Hän menee takaisin kavaljeerirakennukseen, sytyttää takkavalkean
ja kätkee univormunsa. Ja niin hän jälleen asettuu uuninnurkkaan, ja
päivä päivältä hän käy yhä pörröisemmäksi ja harmaammaksi. Hän
riutuu vitkalleen siinä, kuten vanhat kotkat riutuvat vankeudessa.
Hän ei ole enää vanki; mutta hän ei huoli käyttää vapauttaan.
Avaruus on hänelle avoinna. Taistelutanteret, kunnia, elämä
odottavat häntä. Mutta hänellä ei ole enää voimia levittää siipiään
lentoon.
Toinen luku
ELÄMÄN POLUT
Raskaat ovat ne tiet, joita ihmisten on vaellettava maan päällä.
Erämaan teitä, järvien teitä, tunturien teitä.
Miksi saa niin moni suru käydä häiritsemättä, kunnes se eksyy
erämaahan tahi vaipuu järveen tai suistuu tunturilta? Missä ovat
pienet kukkasten poimijattaret, missä ovat pienet satuprinsessat,
joiden askelilla ruusuja kasvaa, missä ovat ne, joiden pitäisi siroitella
kukkasia raskaille teille?
Nyt on Gösta Berling, runoilija, päättänyt mennä naimisiin. Hän
etsii vielä vain morsianta, joka on kyllin köyhä, kyllin halpa, kyllin
hyljeksitty hullun papin vaimoksi.
Kauniit ja jalot naiset ovat rakastaneet häntä, mutta älkööt he
yrittäkö kilpailla hänen suosiostaan. Hyljätty valitsee hyljättyjen
joukosta.
Kenet hän valitsee, ketä hän etsii?
Ekebyssä käy joskus vastoja kaupalla köyhä tyttö yksinäisestä
metsäkylästä, joka on kaukana vuorien keskellä. Tässä kylässä, jossa
vallitsee alinomainen köyhyys ja suuri kurjuus, on monta, joilla ei ole
täyttä ymmärrystä, ja vastatyttö on yksi niitä.
Mutta kaunis hän on. Hänen runsas, musta tukkansa on niin
paksuilla palmikoilla, että ne tuskin mahtuvat hänen päähänsä,
hänen poskensa ovat hienosti pyöristyneet, nenä suora ja parhaan
kokoinen, silmät siniset. Hän on sitä surumielistä, madonnamaista
kaunotartyyppiä, jollaista vielä näkee Lövenin pitkän järven rannoilla.
No, siinähän se nyt on se Göstan morsian — hassahtavasta
vastatytöstä tulee mainio hullun papin vaimo, niin ettei paremmasta
apua.
Göstan ei tarvitse muuta kuin matkata Karlstadiin ostamaan
sormuksia, ja sitten olkoon Lövenin rannalla taas ilon päivä.
Naurakoot ihmiset vielä kerran Gösta Berlingille, kun tämä kihlaa
vastatytön ja viettää häitä hänen kanssaan! Naurakoot vain! Onko
hän ikänään keksinyt hauskempaa kujetta?
Eikö hyljätyn pidä polkeman hyljätyn tietä, vihan tietä, surun tietä,
onnettomuuden tietä! Mitäpä haittaa jos hän suistuu, jos hän
turmeltuu? Onko ketään joka huolii häntä hillitä? Onko ketään joka
ojentaa hänelle ohjaavan kätensä tai virkistävän juoman? Missä ovat
pienet kukkasten poimijattaret, missä ovat pienet satuprinsessat,
missä ovat ne, joiden pitäisi sirotella ruusuja raskaille teille?
Ei, ei, nuori, lempeä Borgin kreivitär ei suinkaan häiritse Gösta
Berlingiä hänen aikeissaan. Hänenhän on ajateltava mainettaan,
ajateltava miehensä vihaa ja anoppinsa vihaa; ei, hän ei yritäkään
pidättää Göstaa.
Pitkän jumalanpalveluksen aikana Svartsjön kirkossa hän painaa
päänsä alas, panee kätensä ristiin ja rukoilee Göstan puolesta.
Unettomina öinä hän usein itkee ja pelkää hänen tähtensä, mutta
hän ei sirottele kukkia hyljätyn tielle eikä anna pisaraa vettä
janoavalle. Hän ei ojenna kättään vetääkseen toista perikadon
partaalta.
Gösta Berling ei huoli verhota valittuaan silkkiin eikä koruihin. Hän
antaa tämän kaupustella vastoja talosta taloon entiseen tapaan,
mutta sitten kun hän on kutsunut kaikki seudun mainittavat miehet
ja naiset suuriin kemuihin Ekebyhyn, sitten hän julkaisee
kihlauksensa. Silloin hän kutsuu hänet keittiöstä saliin sellaisena kuin
hän on taivalluksensa jäljiltä, tien pöly ja lika vaatteissaan, ehkä
rääsyisenä, ehkä hiukset pörröisinä, silmissä sekava ilme ja yhtä
sekava sanatulva huulilla. Ja hän kysyy vierailta, eikö hän nyt ole
valinnut sopivaa morsianta, eikö hullun papin pidä ylpeillä niin
kauniista morsiamesta, tästä lempeästä madonnan muodosta, näistä
sinisistä, haaveellisista silmistä.
Hän oli aikonut olla hiiskumatta tästä kenellekään ennen aikojaan,
mutta hän ei pystynyt varjelemaan salaisuuttaan, ja niin sai myös
nuori kreivitär Dohna sen tietoonsa.
Mutta mitä hän voi tehdä estääkseen Göstaa? Kihlauspäivä on
tullut, sen myöhä hämärän hetki on käsissä. Kreivitär seisoo ikkunan
edessä sinisessä kabinetissa ja katsoo pohjoiseen. Hän on melkein
näkevinään Ekebyn, vaikka kyyneleet ja sumu peittävät hänen
näköalansa. Yhtä kaikki hän näkee selvään, miten iso
kolmikerroksinen rakennus loistaa kolmine valaistuine
ikkunariveineen, hän kuvittelee, miten samppanja kaadetaan
laseihin, miten maljahuuto raikuu ja hän, Gösta Berling, ilmoittaa
kihlauksensa, hänen ja vastatytön liiton.
Jos hän nyt olisi lähellä Göstaa ja panisi aivan hiljaa kätensä
hänen käsivarrelleen tai vain soisi hänelle ystävällisen katseen, niin
eiköpä Gösta kääntyisi huonolta hyljeksittyjen tieltä? Jos kerran
kreivittären lausuma sana oli ajanut hänet niin epätoivoiseen tekoon,
niin eikö myös hänen sanansa voisi häntä hillitä?
Häntä kauhistuttaa rikos, jonka Gösta aikoo tehdä tuota
kovaonnista lapsiparkaa kohtaan. Häntä pöyristyttää synti tuota
poloista raukkaa kohtaan, joka nyt tulee houkutelluksi rakastamaan
Göstaa, ehkäpä vain yhden päivän pilan tähden. Kenties häntä myös
nyt kahta enemmän kauhistuttaa rikos, jonka Gösta tekee itseään
kohtaan — tuo tyttö tulee kytketyksi kuin painava kahle hänen
elämäänsä ja riistää hänen hengeltään korkeuteen pääsyn voimat.
Ja kaikkeen oli kreivitär syynä. Hän oli syössyt tuomitsevalla
sanalla Göstan huonolle tielle. Hän, joka oli tullut siunaamaan,
lientämään, miksi juuri hän oli vääntänyt vielä lisäokaan syntisen
orjantappuraiseen kruunuun?
No niin, nyt hän tietää, mitä hänen on tehtävä. Hänpä menee ja
valjastuttaa mustat hevoset reen eteen ja ajaa hurauttaa Lövenin yli,
ryntää Ekebyn hoviin, asettuu Gösta Berlingin eteen ja sanoo
hänelle, ettei hän halveksi häntä, ettei hän tiennyt mitä puhui
karkottaessaan hänet kotoaan… Ei, hänen on sittenkin mahdoton
tehdä niin, hän häpeäisi eikä uskaltaisi virkkaa sanaakaan. Hänhän
oli naimisissa ja hänen piti varjella itseään panettelulta ja juoruilta.
Mutta kuinka sitten kävisi Gösta Berlingin?
Hänen on lähdettävä.
Sitten hän ajattelee, että sellainen matka on mahdoton. Tänä
vuonna ei enää yksikään hevonen voi päästä Lövenin yli. Jää sulaa,
se on jo irtautunut maasta. Se on vapaana, puhkeillut, kamalan
näköinen. Vesi porisee ylös ja alas railoista, paikoin se on
kokoontunut mustiksi lammikoiksi, toisin paikoin jää on hohtavan
valkeaa. Enimmäkseen se on kumminkin harmaata, likaista sulavasta
lumesta, ja tiet kuultavat pitkinä, mustina juovina sen pinnalla.
Miten hän voi ajatellakaan moista matkaa? Vanha Märta-kreivitär,
hänen anoppinsa, ei millään ehdolla sallisi hänen sitä tehdä. Koko
illan hänen on istuttava kreivittären vieressä salissa ja kuunneltava
vanhoja hovijuttuja, jotka ovat vanhuksen suurin ilo.
Mutta yö tulee, ja hänen miehensä on poissa; nyt hän on vapaa.
Hevosella hän ei voi mennä, palvelijoita hän ei tohdi pyytää
mukaansa, mutta tuska ajaa hänet kotoa ulkosalle. Hän ei muuta
voi.
Raskaita ovat ne tiet, joita ihmiset maan päällä vaeltavat: erämaan
teitä, järvien teitä, tunturien teitä.
Mutta tuota öistä tietä yli sulavan jään, mihin minä sitä vertaisin?
Eikö se ole juuri se tie, jota pienten kukkainpoimijatarten on
käytävä, epävarma, keinuva, liukas tie, niiden polku jotka tahtovat
lääkitä iskettyjä haavoja, niiden polku jotka tahtovat hyvittää
vääryydet; kevyen jalan, nopean silmän ja uljaan, rakastavan
sydämen polku?
Puoliyö oli jo ohi, kun kreivitär viimein pääsi Ekebyn rantaan. Hän
oli lankeillut jäällä, hän oli hyppinyt railojen yli, hän oli juosten
ylittänyt sellaiset paikat, joissa jalanjäljen täytti pulppuava vesi, hän
oli liukastunut, hän oli ryöminyt.
Se oli ollut raskasta vaellusta; hän oli itkenyt kulkiessaan. Hän oli
märkä ja väsynyt, ja pimeys, kolkkous ja autius olivat tuoneet
mieleen kamalia ajatuksia.
Ekebyn rannassa hänen täytyi kahlata jalansyvyisessä vedessä
päästäkseen maalle. Ja tultuaan rannalle hän ei saattanut muuta
kuin istahtaa rannan kivelle ja itkeä väsymystään ja avuttomuuttaan.
Raskaita teitä vaeltavat ihmisten lapset, ja joskus pienet
poimijattaret vaipuivat kukkaskoriensa viereen, juuri saavuttuaan
tielle, jolle aikovat kukkia sirotella.
Tämä nuori, ylhäinen nainen oli kuin olikin pieni rakastettava
sankaritar. Ei hän ollut kulkenut sellaisia teitä ennen kotimaassaan.
Ehkäpä hän nyt, istuessaan tämän kauhean, hirvittävän järven
rannalla märkänä, uupuneena, onnettomana, ajatteli eteläisen
isänmaansa lempeitä, kukkasten reunaamia polkuja.
Voi, ei häntä liikuta nyt etelä, ei pohjola. Hän on keskellä elämää.
Hän ei itke koti-ikävää. Hän itkee, tuo pikku kukkastenpoimija, tuo
pieni sankaritar sitä, että on niin uupunut ettei ehdi sen tielle, jolle
tahtoo kukkia sirotella. Hän itkee siksi, että luulee tulleensa liian
myöhään.
Silloin juoksee väkeä rannalle. He kiiruhtavat hänen ohitseen
häntä huomaamatta, mutta hän kuulee heidän sanansa:
"Jos pato särkyy, menee paja", sanoo joku. "Ja mylly ja verstaat ja
seppien asumukset", lisää toinen.
Silloin hän rohkaistuu jälleen, nousee ja seuraa heitä.
* * * * *
Ekebyn mylly ja paja olivat kaidalla niemellä, jonka ympäri kiertää
pauhaava Björksjön-joki. Se tulee viuhuen nientä kohti, ylemmän,
valtavan kosken valkeaksi kuohuttamana, ja niemen rakennusten
perustaa oli siellä siihen aikaan vedeltä suojaamassa mahtava
aallonmurtaja niemen nokassa. Mutta sulku oli jo vanha ja kavaljeerit
talon ohjissa. Heidän aikanaan tanssia keikuttiin tehtaan mäillä,
kukaan ei huolinut katsoa, kuinka virta ja pakkanen ja aika kuluttivat
vanhaa kivipatoa.
Sitten tulee kevättulva ja sulku alkaa horjua.
Ekebyn putous on kuin valtavat harmaakiviportaat, joita myöten
Björksjö-joen laineet hyrskyten tulevat alas. Ne tulevat vauhdista
huimiksi, tuupertuvat nurinniskoin ja ryntäävät toisiaan vastaan. Ne
hypähtävät ilmaan vihoissaan ja pärskyttävät vaahtoa toistensa yli,
kompastuvat taaskin kiveen, tukkiin ja kepsahtavat jälleen pystyyn
mennäkseen samassa nurin, ja niin yhä vain vaahdoten, kähisten,
karjuen.
Ja nyt karkaavat nämä villit, hurjistuneet aallot, kevätsäästä
juopuneina ja äsken saadun vapauden huumauksessa, vanhan
kivimuurin kimppuun. Ne tulevat, kähisten ja raastaen, kimpoavat
korkealle sen harjalle ja vetäytyvät takaisin kuin olisivat loukanneet
valkokutriset päänsä. Se on väkirynnäkkö jos mikään, ne tempaavat
suuria jäälauttoja suojakatoiksi, ne ottavat hirsiä muurinmurtajiksi,
ne yhdistyvät, karkaavat hyökkäykseen, pauhaavat tuota
muuriraukkaa vasten, kunnes tuntuu yht'äkkiä siltä kuin joku olisi
niille huutanut: pitäkää varanne! Silloin ne rynkäisevät takaisin ja
niiden jäljestä tulee iso kivi, joka irtautuu sulusta ja vaipuu kolisten
virran syliin.
Näyttää kuin se olisi niitä ällistyttänyt, ne ovat hiljaa, ne
riemuitsevat, ne neuvottelevat … ja sitten uusi ryntäys! Siellä ne
taaskin ovat jäälauttoineen ja hirsineen, nuo vallattomat,
armottomat, rajut hävityshalun hullaannuttamat.
Jos vain pato olisi poissa tieltä — sanovat aallot — jos vain pato
olisi tieltä, niin silloin tulee pajan ja myllyn vuoro.
Nyt on vapauden päivä … pois ihmiset ja ihmisten työt! Ne ovat
noenneet meidät hiilillään, ne ovat tomunneet meitä jauhoillaan, ne
ovat kytkeneet meidät työn ikeeseen kuin härkänsä, ajaneet meitä
pyörylässä, sulkeneet meidät kammioihin, estäneet kulkumme
patoluukuilla, pakottaneet meidät kiskomaan raskaita pyöriä,
kantamaan kömpelöitä tukkeja. Mutta nyt me anastamme vapauden.
Vapauden päivä on tullut! Kuulkaa, te Björksjön ulapan aallot,
kuulkaa, siskot ja veikot, te rämeitten ja lampien, vuoripurojen ja
metsäjokien vedet! Se on tullut, on tullut! Rynnätkää alas Björksjön
jokeen, tulkaa vereksin voimin, jyristen, viuhuen, murtamaan
vuosisatain sortoa, tulkaa! Hirmuvalan paalutus kaatukoon. Kuolema
Ekebylle!
Ja ne tulevat — aalto aallon perästä ryntää putoukseen iskeäkseen
päänsä sulkumuuriin, antaakseen oman osuutensa suureen työhön.
Juopuneina kevään äsken saadusta vapaudesta, lukemattomina,
yksimielisinä ne tulevat, ne irroittavat kiven toisensa jälkeen,
mättään mättään perästä horjuvasta aallonmurtajasta.
Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.
More than just a book-buying platform, we strive to be a bridge
connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.
Join us on a journey of knowledge exploration, passion nurturing, and
personal growth every day!
ebookbell.com

More Related Content

PDF
Designing Evolvable Web APIs with ASP NET 1st Edition Glenn Block
PDF
C50 In A Nutshell 5 Wow Joseph Albahari Ben Albahari
PDF
A Practical Guide to Content Delivery Networks Second Edition Gilbert Held
PDF
Apache Axis2 Web Services 2nd Edition Deepal Jayasinghe
PDF
Beginning Aspnet 35 In C 2008 From Novice To Professional 2nd Ed Matthew Macd...
PDF
Scalable and Secure Internet Service and Architecture 1st Edition Cheng-Zhong Xu
PDF
(Ebook) Component Software: Beyond Object-Oriented Programming by Szyperski C...
PDF
Building Microservices With Net Core Converted Soumya Mukherjee
Designing Evolvable Web APIs with ASP NET 1st Edition Glenn Block
C50 In A Nutshell 5 Wow Joseph Albahari Ben Albahari
A Practical Guide to Content Delivery Networks Second Edition Gilbert Held
Apache Axis2 Web Services 2nd Edition Deepal Jayasinghe
Beginning Aspnet 35 In C 2008 From Novice To Professional 2nd Ed Matthew Macd...
Scalable and Secure Internet Service and Architecture 1st Edition Cheng-Zhong Xu
(Ebook) Component Software: Beyond Object-Oriented Programming by Szyperski C...
Building Microservices With Net Core Converted Soumya Mukherjee

Similar to Programming Wcf Services 4th Edition Juval Lwy Michael Montgomery (12)

PDF
Microservice Apis Using Python Flask Fastapi Openapi And More 1st Edition Jos...
PDF
Windows Phone 7 Developer Guide Building Connected Mobile Applications With M...
PDF
DevOps with OpenShift 1st Edition Mike Hepburn
PDF
Enterprise SOA Service Oriented Architecture Best Practices 9th Edition Dirk ...
PDF
Palvelujen ohjelmointi
PDF
Microsoft Hyper V Cluster Design 1st Edition Eric Siron
PDF
Oracle Soa Bpel Process Manager 11gr1 A Handson Tutorial Ravi Saraswathi
PDF
Spring Start Here Learn what you need and learn it well 1st Edition Laurentiu...
PDF
Convergence Technologies for 3G Networks IP UMTS EGPRS and ATM 1st Edition Je...
PDF
Tieturi: It governance - muuttuvat standardit
PDF
Servicenow Top 375 Interview Questions By Srinivas Sunkara 2nd Edition Sriniv...
Microservice Apis Using Python Flask Fastapi Openapi And More 1st Edition Jos...
Windows Phone 7 Developer Guide Building Connected Mobile Applications With M...
DevOps with OpenShift 1st Edition Mike Hepburn
Enterprise SOA Service Oriented Architecture Best Practices 9th Edition Dirk ...
Palvelujen ohjelmointi
Microsoft Hyper V Cluster Design 1st Edition Eric Siron
Oracle Soa Bpel Process Manager 11gr1 A Handson Tutorial Ravi Saraswathi
Spring Start Here Learn what you need and learn it well 1st Edition Laurentiu...
Convergence Technologies for 3G Networks IP UMTS EGPRS and ATM 1st Edition Je...
Tieturi: It governance - muuttuvat standardit
Servicenow Top 375 Interview Questions By Srinivas Sunkara 2nd Edition Sriniv...
Ad

Programming Wcf Services 4th Edition Juval Lwy Michael Montgomery

  • 1. Programming Wcf Services 4th Edition Juval Lwy Michael Montgomery download https://ebookbell.com/product/programming-wcf-services-4th- edition-juval-lwy-michael-montgomery-5238676 Explore and download more ebooks at ebookbell.com
  • 2. Here are some recommended products that we believe you will be interested in. You can click the link to download. Programming Wcf Services 2nd Edition Second Edition Juval Lowy https://ebookbell.com/product/programming-wcf-services-2nd-edition- second-edition-juval-lowy-2399036 Programming Wcf Services Juval Lowy https://ebookbell.com/product/programming-wcf-services-juval- lowy-37208962 Professional Wcf Programming Net Development With The Windows Communication Foundation Scott Klein https://ebookbell.com/product/professional-wcf-programming-net- development-with-the-windows-communication-foundation-scott- klein-4106444 Programming Net 35 Build Ntier Applications With Wpf Ajax Silverlight Linq Wcf And More 1st Edition Jesse Liberty https://ebookbell.com/product/programming-net-35-build-ntier- applications-with-wpf-ajax-silverlight-linq-wcf-and-more-1st-edition- jesse-liberty-1021740
  • 3. Programming Languages And Systems 31st European Symposium On Programming Esop 2022 Held As Part Of The European Joint Conferences On Theory And Practice Of Software Etaps 2022 Munich Germany April 27 2022 Proceedings Ilya Sergey https://ebookbell.com/product/programming-languages-and-systems-31st- european-symposium-on-programming-esop-2022-held-as-part-of-the- european-joint-conferences-on-theory-and-practice-of-software- etaps-2022-munich-germany-april-27-2022-proceedings-ilya- sergey-44887738 Programming 101 Learn To Code Using The Processing Programming Language 2nd Edition 2nd Jeanine Meyer https://ebookbell.com/product/programming-101-learn-to-code-using-the- processing-programming-language-2nd-edition-2nd-jeanine-meyer-46238180 Programming 101 The How And Why Of Programming Revealed Using The Processing Programming Language Jeanine Meyer https://ebookbell.com/product/programming-101-the-how-and-why-of- programming-revealed-using-the-processing-programming-language- jeanine-meyer-46318424 Programming And Gui Fundamentals Tcltk For Electronic Design Automation Suman Lata Tripathi https://ebookbell.com/product/programming-and-gui-fundamentals-tcltk- for-electronic-design-automation-suman-lata-tripathi-46318712 Programming With Openscad A Beginners Guide To Coding 3dprintable Objects 1st Edition Justin Gohde https://ebookbell.com/product/programming-with-openscad-a-beginners- guide-to-coding-3dprintable-objects-1st-edition-justin-gohde-46410140
  • 7. 4TH EDITION Programming WCF Services Juval Lowy & Michael Montgomery Boston
  • 8. Programming WCF Services by Juval Lowy and Michael Montgomery Copyright © 2016 Juval Lowy and Michael Montgomery. All rights reserved. Printed in the United States of America. Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472. O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles (http://safaribooksonline.com). For more information, contact our corporate/ institutional sales department: 800-998-9938 or corporate@oreilly.com. Editors: Brian MacDonald and Rachel Roumeliotis Interior Designer: David Futato Production Editor: Melanie Yarbrough Cover Designer: Randy Comer Proofreader: Jasmine Kwityn Illustrator: Rebecca Demarest Indexer: WordCo Indexing Services December 2015: Fourth Edition Revision History for the Fourth Edition 2015-11-04: First Release See http://oreilly.com/catalog/errata.csp?isbn=9781491944837 for release details. The O’Reilly logo is a registered trademark of O’Reilly Media, Inc. Programming WCF Services, the cover image, and related trade dress are trademarks of O’Reilly Media, Inc. While the publisher and the author have used good faith efforts to ensure that the information and instructions contained in this work are accurate, the publisher and the author disclaim all responsibility for errors or omissions, including without limitation responsibility for damages resulting from the use of or reliance on this work. Use of the information and instructions contained in this work is at your own risk. If any code samples or other technology this work contains or describes is subject to open source licenses or the intellectual property rights of others, it is your responsibility to ensure that your use thereof complies with such licenses and/or rights. 978-1-491-94483-7 [LSI]
  • 9. Table of Contents Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii 1. WCF Essentials. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 What Is WCF? 1 Services 3 Service Execution Boundaries 4 WCF and Location Transparency 5 Addresses 5 TCP Addresses 6 HTTP Addresses 7 IPC Addresses 7 MSMQ Addresses 8 WebSocket Addresses 8 UDP Addresses 8 Contracts 8 The Service Contract 9 Hosting 13 IIS Hosting 14 Self-Hosting 15 WAS Hosting 21 Custom Hosting in IIS/WAS 21 Choosing a Host 22 Bindings 23 The Common Bindings 24 Choosing a Binding 26 Additional Bindings 27 Using a Binding 30 Endpoints 30 iii
  • 10. Administrative Endpoint Configuration 31 Programmatic Endpoint Configuration 35 Default Endpoints 37 The Configure() Method 40 Metadata Exchange 43 Metadata over HTTP-GET 44 The Metadata Exchange Endpoint 47 The Metadata Explorer 54 More on Behavior Configuration 56 Client-Side Programming 58 Generating the Proxy 59 Administrative Client Configuration 64 Programmatic Client Configuration 71 The WCF-Provided Test Client 72 Programmatic Versus Administrative Configuration 75 Configuration Policy 75 WCF Architecture 76 Host Architecture 77 Working with Channels 78 The InProcFactory Class 80 Transport-Level Sessions 84 Transport Session and Binding 84 Transport Session Termination 85 Reliability 86 Bindings, Reliability, and Ordered Messages 87 Configuring Reliability 88 Requiring Ordered Delivery 89 2. Service Contracts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Operation Overloading 93 Contract Inheritance 96 Client-Side Contract Hierarchy 97 Service Contract Factoring and Design 101 Contract Factoring 101 Factoring Metrics 103 Contract Queries 105 Programmatic Metadata Processing 106 The MetadataHelper Class 109 3. Data Contracts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 Serialization 115 .NET Serialization 117 iv | Table of Contents
  • 11. The WCF Formatters 119 Data Contract via Serialization 122 Data Contract Attributes 123 Importing a Data Contract 125 Data Contracts and the Serializable Attribute 129 Inferred Data Contracts 130 Composite Data Contracts 131 Data Contract Events 133 Shared Data Contracts 136 Data Contract Hierarchy 137 Known Types 138 Service Known Types 140 Multiple Known Types 141 Configuring Known Types 142 Data Contract Resolvers 143 Objects and Interfaces 155 Data Contract Equivalence 157 Serialization Order 158 Versioning 160 New Members 161 Missing Members 162 Versioning Round-Trip 166 Data Contract Factoring and Design 169 Data Contract Design 169 Data Contract Factoring 169 Operation Factoring 181 The Data Transfer Object Pattern 183 Enumerations 184 Delegates and Data Contracts 186 Generics 187 Collections 191 Concrete Collections 192 Custom Collections 194 The CollectionDataContract Attribute 194 Referencing a Collection 196 Dictionaries 196 4. Instance Management. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201 Behaviors 201 Per-Call Services 203 Benefits of Per-Call Services 204 Configuring Per-Call Services 204 Table of Contents | v
  • 12. Per-Call Services and Transport Sessions 206 Designing Per-Call Services 206 Choosing Per-Call Services 209 Per-Session Services 209 Configuring Private Sessions 210 Sessions and Reliability 215 The Session ID 216 Session Termination 218 Singleton Service 218 Initializing a Singleton 220 Choosing a Singleton 223 Demarcating Operations 223 Instance Deactivation 226 Configuring with ReleaseInstanceMode.None 227 Configuring with ReleaseInstanceMode.BeforeCall 228 Configuring with ReleaseInstanceMode.AfterCall 229 Configuring with ReleaseInstanceMode.BeforeAndAfterCall 229 Explicit Deactivation 230 Using Instance Deactivation 231 Durable Services 231 Durable Services and Instance Management Modes 232 Instance IDs and Durable Storage 233 Explicit Instance IDs 234 Instance IDs in Headers 236 Context Bindings for Instance IDs 239 Automatic Durable Behavior 245 Throttling 252 Configuring Throttling 255 5. Operations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 Request-Reply Operations 261 One-Way Operations 262 Configuring One-Way Operations 262 One-Way Operations and Reliability 263 One-Way Operations and Sessionful Services 263 One-Way Operations and Exceptions 264 Callback Operations 266 The Callback Contract 267 Client Callback Setup 268 Service-Side Callback Invocation 272 Callback Connection Management 275 The Duplex Proxy and Type Safety 278 vi | Table of Contents
  • 13. The Duplex Factory 281 Callback Contract Hierarchy 283 Events 285 Streaming 289 I/O Streams 289 Streaming and Binding 290 Streaming and Transport 291 6. Faults. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293 Error Isolation and Decoupling 293 Error Masking 294 Channel Faulting 295 Fault Propagation 299 Fault Contracts 301 Fault Debugging 305 Faults and Callbacks 312 Error-Handling Extensions 315 Providing a Fault 316 Handling a Fault 319 Installing Error-Handling Extensions 322 The Host and Error Extensions 325 Callbacks and Error Extensions 329 7. Transactions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333 The Recovery Challenge 333 Transactions 334 Transactional Resources 335 Transaction Properties 335 Transaction Management 337 Resource Managers 341 Transaction Propagation 341 Transaction Flow and Bindings 341 Transaction Flow and the Operation Contract 343 One-Way Calls 345 Transaction Protocols and Managers 345 Protocols and Bindings 346 Transaction Managers 348 Transaction Manager Promotion 350 The Transaction Class 352 The Ambient Transaction 352 Local Versus Distributed Transactions 353 Transactional Service Programming 354 Table of Contents | vii
  • 14. Setting the Ambient Transaction 354 Transaction Propagation Modes 357 Voting and Completion 365 Transaction Isolation 369 Transaction Timeout 371 Explicit Transaction Programming 373 The TransactionScope Class 373 Transaction Flow Management 375 Non-Service Clients 383 Service State Management 384 The Transaction Boundary 385 Instance Management and Transactions 386 Per-Call Transactional Services 387 Per-Session Transactional Services 391 Transactional Durable Services 406 Transactional Behavior 408 Transactional Singleton Service 415 Instancing Modes and Transactions 418 Callbacks 419 Callback Transaction Modes 420 Callback Voting 422 Using Transactional Callbacks 422 8. Concurrency Management. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427 Instance Management and Concurrency 428 Service Concurrency Modes 428 429 ConcurrencyMode.Single 429 ConcurrencyMode.Multiple 433 ConcurrencyMode.Reentrant Instances and Concurrent Access 436 Per-Call Services 436 Sessionful and Singleton Services 437 Resources and Services 438 Deadlocked Access 438 Deadlock Avoidance 439 Resource Synchronization Context 441 .NET Synchronization Contexts 441 The UI Synchronization Context 445 Service Synchronization Context 451 Hosting on the UI Thread 452 A Form as a Service 458 The UI Thread and Concurrency Management 461 viii | Table of Contents
  • 15. Custom Service Synchronization Contexts 464 The Thread Pool Synchronizer 464 Replacing the I/O Completion Thread Pool 469 Thread Affinity 471 Priority Processing 473 Callbacks and Client Safety 477 Callbacks with ConcurrencyMode.Single 478 Callbacks with ConcurrencyMode.Multiple 479 Callbacks with ConcurrencyMode.Reentrant 479 Callbacks and Synchronization Contexts 480 Callbacks and the UI Synchronization Context 480 Callback Custom Synchronization Contexts 484 Asynchronous Calls 488 Requirements for an Asynchronous Mechanism 488 Proxy-Based Asynchronous Calls 489 Asynchronous Invocation 492 Polling or Waiting for Completion 494 Continuations 497 One-Way Asynchronous Operations 508 Asynchronous Error Handling 512 Asynchronous Calls and Transactions 515 Synchronous Versus Asynchronous Calls 516 Asynchronous Service Operations 517 9. Queued Services. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543 Disconnected Services and Clients 543 Queued Calls 544 Queued Calls Architecture 545 Queued Contracts 545 Configuration and Setup 546 Transactions 554 Delivery and Playback 554 Service Transaction Configuration 556 Nontransactional Queues 559 Instance Management 560 Per-Call Queued Services 561 Sessionful Queued Services 563 Singleton Service 566 Concurrency Management 567 Throttling 568 Delivery Failures 569 The Dead-Letter Queue 570 Table of Contents | ix
  • 16. Time to Live 571 Configuring the Dead-Letter Queue 571 Processing the Dead-Letter Queue 573 Playback Failures 578 Poison Messages 579 Poison Message Handling 579 Queued Versus Connected Calls 584 Requiring Queuing 586 The Response Service 587 Designing a Response Service Contract 588 Client-Side Programming 592 Queued Service-Side Programming 595 Response Service-Side Programming 597 Transactions 598 The HTTP Bridge 602 Designing the Bridge 602 Transaction Configuration 603 Service-Side Configuration 604 Client-Side Configuration 606 10. Security. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 609 Authentication 609 Authorization 610 Transfer Security 611 Transfer Security Modes 612 Transfer Security Mode Configuration 614 Transport Security and Credentials 617 Message Security and Credentials 617 Identity Management 618 Overall Policy 618 Scenario-Driven Approach 619 Intranet Application Scenario 620 Securing the Intranet Bindings 620 Constraining Message Protection 628 Authentication 629 Identities 632 The Security Call Context 633 Impersonation 635 Authorization 643 Identity Management 650 Callbacks 651 Internet Application Scenario 652 x | Table of Contents
  • 17. Securing the Internet Bindings 652 Message Protection 655 Authentication 660 Using Windows Credentials 662 Using the ASP.NET Providers 663 Identity Management 673 Business-to-Business Application Scenario 673 Securing the Business-to-Business Bindings 674 Authentication 674 Authorization 677 Identity Management 679 Host Security Configuration 679 Anonymous Application Scenario 680 Securing the Anonymous Bindings 680 Authentication 681 Authorization 681 Identity Management 681 Callbacks 682 No Security Scenario 682 Unsecuring the Bindings 682 Authentication 683 Authorization 683 Identity Management 683 Callbacks 683 Scenarios Summary 684 Declarative Security Framework 684 The SecurityBehaviorAttribute 685 Host-Side Declarative Security 693 Client-Side Declarative Security 695 Security Auditing 702 Configuring Security Audits 703 Declarative Security Auditing 706 11. The Azure Service Fabric. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 709 Why Azure Service Fabric 709 An Integrated Platform 710 Design Consistency 710 Programming Model Consistency 711 Future Compatible 711 Preparing for the Service Fabric 713 ServiceModelEx.ServiceFabric 713 Configuring the Service Fabric 714 Table of Contents | xi
  • 18. IT Operations 714 Development 716 Both 718 Programming the Service Fabric 723 The Service Programming Model 724 Reliable Services 724 Reliable Actors 734 State Management 737 Hosting 745 The Client Programming Model 746 Modeling the Service Fabric 756 Modeling Approach 757 Modeling Reliable Services 758 Modeling Reliable Actors 761 Modeling Hosting 770 Testing 771 A. Introduction to Service Orientation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 779 B. Headers and Contexts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 795 C. Discovery. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 819 D. Publish-Subscribe Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 883 E. Generic Interceptor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 911 F. WCF Coding Standard. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 929 G. ServiceModelEx Catalog. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 943 Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 969 xii | Table of Contents
  • 19. Preface On the software time scale, WCF is ancient. In August 2001, I first learned the details of a Microsoft effort to rewrite COM+ using managed code. Nothing much happened after that. Then, during a C# 2.0 Strategic Design Review in July 2002, the remoting program manager outlined in broad strokes plans to rework remoting into something that developers should actually use. At the same time, Microsoft was also working on incorporating the new security specs for web services into the ASMX stack and actively working with others on drafting a score of additional web services specs. In July 2003, I was given access to a new transactional infrastructure that improved on the deficiencies in transactional .NET programming. At the time, there was no cohesive programming model that unified these distinct technologies. Toward the end of 2003, I was privileged to be invited to join a small team of outside industry experts and to participate in the strategic design review of a new development plat­ form codenamed Indigo. Some of the smartest and nicest people I ever worked with were part of that team. Over the next two to three years, Indigo went through some three generations of programming models. The final declarative, endpoint-driven object model debuted in early 2005, was stabilized by August of that year, and was named the Windows Communication Foundation (WCF). WCF was released in November 2006 as part of .NET 3.0 On the software relevancy scale, WCF is a titan. It has all the correct elements required to build a modern software system including the foundational pattern of all modern software; an extensible, interception-based pipeline. It is the basis for the upcoming Azure Service Fabric and it integrates with the Service Fabric as-is. In fact, the previous three editions of this book showed how to implement all the elements of the Service Fabric already. As such, WCF is as paramount as ever. WCF has several facets, and is the only technology today that offers interoperability, productivity and extensibility. It is the ultimate interoperability solution, an imple­ mentation of a long list of industry standards. To the distributed application devel­ oper, it is the easiest way of making remote calls and even queued calls. To the system xiii
  • 20. developer, it is the next generation of productivity-oriented features, such as transac­ tions and hosting, that provide off-the-shelf plumbing for applications. To the appli­ cation developer, it is a declarative programming model for structuring applications. And to the architect, it is a tool for building service-oriented applications. WCF is, in actuality, all of those, simply because it was designed that way—to be the unified offering of Microsoft’s disparate technologies. To me, WCF is a superior development platform, which to a large extent subsumed raw .NET programming. All .NET developers should use WCF, regardless of their application types, sizes, or industry domains. WCF is a fundamental technology that provides an easy and clean way to generate services and applications in compliance with what I regard as sound design principles. WCF was engineered from the ground up to simplify application development and deployment and to lower the overall cost of ownership. WCF services allow you to build service-oriented applications, from standalone desktop applications to web-based applications and services to high-end Enterprise applications. How This Book Is Organized This book covers the topics and skills you need to design and develop service­ oriented WCF-based applications, illustrating how to take advantage of built-in fea­ tures such as service hosting, instance management, concurrency management, transactions, disconnected queued calls, security, and the new Windows Azure Ser­ vice Fabric. But in fact, this book is not about WCF. It is about modern software engi­ neering, using WCF as a medium to express these design ideas. The various concepts disused in this book transcend technologies. So while the book shows you how to use these features in WCF, it focuses on the “why” and on the rationale behind particular design decisions. You’ll learn about not only WCF programming and the related sys­ tem issues, but also relevant design options, tips, best practices, and pitfalls. I approach almost every topic and aspect from a software engineering standpoint, because my objective is to make you not just a WCF expert, but also a better software engineer. Armed with the insights this text provides, you can engineer your applica­ tions for maintainability, extensibility, reusability, and productivity. This fourth edition has provided me with several opportunities: first, to catch up with WCF in .NET 4.6 with its new features of parallel processing and configuration. Sec­ ond, I wanted to present the upcoming Azure Service Fabric, which is a fundamen­ tally disruptive technology because of the sort of applications it allows developers to build and how it unifies development and operations. Third, I have had a few more years’ worth of WCF techniques, ideas, and helper classes, as well as improvement of the ideas I had in the previous editions. I believe this new material will make this edi­ tion valuable even to readers of the third edition. xiv | Preface
  • 21. This book avoids many implementation details of WCF and largely confines its cov­ erage to the possibilities and practical aspects of using WCF: how to apply the tech­ nology and how to choose among the available design and programming models. It makes the most of what .NET 4.6 and the Service Fabric has to offer, and in some respects is an advanced C# book as well. In addition, the book contains many useful utilities, tools, and helper classes I have written, collectively known as ServiceModelEx. My tools, helper classes, and attributes aim at increasing your productivity and the quality of your WCF services. ServiceMo­ delEx is literally a small framework that sits on top of WCF and compensates for some oversights in its design. ServiceModelEx also simplifies and automates certain tasks. This book is as much about my tools, ideas, and techniques as it is about native WCF, and my framework also demonstrates how you can extend WCF. Many readers have told me that aside from the explanations in this book, ServiceModelEx is the most valuable asset the book offers. I have also kept to my guideline that, in principle, readers should not have to use all (or any part) of ServiceModelEx. In practice, Serv­ iceModelEx is your WCF power tools collection. You can also use each helper class, utility, or framework individually, as there are few, if any, interdependencies. Each chapter addresses a single topic and discusses it in depth. However, the chapters often rely on those that precede them, so you should read the book in order. Here is a brief summary of the chapters and appendixes in this book: Chapter 1, WCF Essentials This first chapter starts by explaining what WCF is, then describes essential WCF concepts and building blocks (such as addresses, contracts, bindings, endpoints, hosting, and clients) and key concepts such as reliability and transport sessions. The chapter includes a discussion of the WCF architecture, which is really the linchpin of all that follows in the subsequent chapters. This chapter assumes that you understand the basic motivation and benefit of service orientation. If that is not the case, you should first read Appendix A. Even if you are already familiar with the basic concepts of WCF, I recommend that you give this chapter at least a cursory reading, not only to ensure that you have a solid foundation, but also because some of the helper classes and terms introduced here will be used and extended throughout the book. Chapter 2, Service Contracts Chapter 2 is dedicated to the topic of designing and working with service con­ tracts. First, it covers some useful techniques for service contract overloading and inheritance, as well as some advanced techniques. The chapter also discusses how to design and factor contracts that cater to reuse, maintainability, and extensibil­ ity. It ends by showing you how to interact programmatically with the metadata of the exposed contracts at runtime. Preface | xv
  • 22. Chapter 3, Data Contracts Chapter 3 deals with how the client and the service can exchange data without ever actually sharing the data type itself or using the same development technol­ ogy. In this chapter, you will see how to deal with some interesting real-life issues, such as data versioning, and how to pass collections of items. This chapter also extends the contract design and factoring discussion of Chapter 2 to data con­ tracts. Chapter 4, Instance Management This chapter answers the question of which service instance handles which cli­ ent’s request. WCF supports several service instance management, activation, and lifetime management techniques, and your choices will have drastic implications for scalability, performance, the programming model, and the business workflow. This chapter presents the rationale behind each of the instance management modes, offers guidelines on when and how to best use them, and also addresses some related topics, such as durability and throttling. Chapter 5, Operations Chapter 5 deals with the types of operations clients can invoke on a service and related design guidelines, such as how to improve on and extend the basic WCF offering to support callback setup and teardown, manage callback ports and channels, and provide for type-safe duplex proxies. Chapter 6, Faults This chapter discusses the best practices of error handling, enabling you to decouple the client’s error handling from the service’s. When required, the chap­ ter shows how services can report errors and exceptions back to their clients, since constructs such as exceptions and exception handling are technology­ specific and should not transcend the service boundary. This chapter also dem­ onstrates how you can extend and improve on WCF’s basic error-handling mechanism. Chapter 7, Transactions This chapter begins by explaining the motivation for transactions in general, then discusses the many aspects of transactional services: the transaction man­ agement architecture, transaction propagation configuration, the declarative transaction support offered by WCF, and how clients can create transactions. The chapter ends by discussing relevant design guidelines such as transactional ser­ vice state management and instancing modes. Chapter 8, Concurrency Management Chapter 8 first describes the powerful yet simple declarative way WCF offers for managing concurrency and synchronization, both for the client and the service. The chapter then presents more advanced aspects of concurrency management, xvi | Preface
  • 23. such as callbacks, reentrancy, thread affinity, and synchronization context, best practices and guidelines for avoiding deadlocks, and asynchronous call manage­ ment. The chapter also explores the Task-based Asynchronous Pattern (TAP) and how this style of asynchrony relates to WCF, highlighting best practice techni­ ques, as well as, discussing potential pitfalls. Chapter 9, Queued Services Chapter 9 shows how clients can queue up calls to services, thus enabling asyn­ chronous, disconnected work. The chapter starts by showing how to set up and configure queued services, then focuses on aspects such as transactions, instance management, and failures and their impact on both the business model of the service and its implementation. It also presents techniques for streamlining queues, call management, and several original design ideas (such as a queued response service). Chapter 10, Security This chapter demystifies service-oriented security by breaking down this multi­ faceted task into its basic elements, such as message transfer, authentication, and authorization. It also demonstrates how to provide security for key scenarios such as intranet and Internet applications. Finally, it presents my framework for declarative WCF security, designed to automate security setup and to considera­ bly simplify managing security. Chapter 11, The Azure Service Fabric Chapter 11 introduces you to the Azure Service Fabric. This chapter starts by briefly explaining the value and rationale behind the new platform and continues by presenting the Service Fabric’s many capabilities. The chapter ends by present­ ing ServiceModelEx.ServiceFabric, our operational Service Fabric that simpli­ fies how you prepare for the Service Fabric and allows you to deploy Service Fabric code to any Windows environment that can host WCF services. Appendix A, Introduction to Service Orientation This appendix is designed for readers who want to understand what service ori­ entation is all about: it presents my take on service orientation and puts it in a concrete context. The appendix defines service-oriented applications (as opposed to mere architecture) and the services themselves and examines the benefits of the methodology. It then presents the principles of service orientation and aug­ ments the abstract tenets with a few more practical points required by most applications. In this appendix, I also share my perspective on where SOA and WCF are heading. Appendix B, Headers and Contexts This appendix introduces two distinct techniques for enabling the client to pass out-of-band parameters to the service, resulting in a custom logical context: you Preface | xvii
  • 24. will see how to use either the message headers or the context binding to achieve this goal. This appendix also presents my helper classes, which greatly simplify and encapsulate the required programming. These helper classes and custom contexts are used in several places in the book. Appendix C, Discovery This appendix starts by describing the basic offering of service discovery and availability announcements introduced in .NET 4.0. Discovery simplifies service and client deployment and management, and allows for great volatility across time and deployment sites. The appendix then shows some simple techniques and helper classes you can use to streamline the programming model. The appendix ends with our technique for TCP-based discovery that mimics regular WCF discovery, benefiting from discovery even where UDP is disallowed. Appendix D, Publish-Subscribe Service Appendix D presents several techniques for implementing a publish-subscribe event management solution. It starts with my framework, which lets you develop a publishing and a subscription service in, at most, one line of code. The appen­ dix ends with a discovery-enabled publish-subscribe solution that requires no explicit subscriptions steps. Appendix E, Generic Interceptor This appendix presents a general-purpose extensible framework for intercepting calls to your WCF services. It walks through the technique and thought process behind such an extension and shows two examples of how to utilize this simple yet powerful and useful technique. Appendix F, WCF Coding Standard Appendix F is basically a consolidated list of all the best practices and dos and don’ts mentioned throughout this book. The standard is all about the “how” and the “what,” not the “why.” The rationale behind it is found in the rest of the book. The standard also uses the terms and helper classes discussed in this book. Appendix G, ServiceModelEx Catalog The final appendix presents a catalog of the 100 or so public helper types (exclud­ ing internal helper types) of ServiceModelEx mentioned in the book, arranged by categories and techniques, with a short description of each. Introducing Michael “Monty” Montgomery In 2009 at my annual Architect’s Master Class I met Monty, who at the time was the chief architect of a large enterprise. Over the next few years we kept in touch since Monty was one of the best architects I have ever met. Monty has a natural knack for service-oriented design and the related system issues. He also proved to be a WCF expert. In 2012 he finally made the jump and joined IDesign. The reason I wanted xviii | Preface
  • 25. him had almost nothing to do with his technical expertise. Monty has a fundamental appreciation for what it takes to make a developer team of a broad spectrum of acu­ men productive. Over the years Monty has mentored many architects on how to ach­ ieve just that objective, so he was a natural fit to help with this fourth edition of the WCF ‘Bible’. Together we bounced new and old ideas off each other, culminating in the new techniques you read in this book. With the addition of a second author, I wanted to keep the original author’s voice from the previous three editions when referring to personal opinions or contribu­ tions. As with the previous editions, when the text mentions “I” or “my,” it refers to Juval. When it says “we” or “our,” it refers to both Juval and Monty. Some Assumptions About the Reader I assume that you, the reader, are an experienced developer and that you are comfort­ able with object-oriented concepts such as encapsulation and inheritance. I will take advantage of your existing understanding of object and component technology and terminology, and port that knowledge to WCF. You should ideally have a fair under­ standing of .NET and know C# 4.5. Although the book uses C# for the most part, it is just as pertinent to Visual Basic developers. What You Need to Use This Book To use this book, you will need .NET 4.5 or .NET 4.6 and Visual Studio 2015 or 2016. For the Service Fabric appendix, you will need the Windows Azure Service Fabric SDK. Unless I explicitly mention otherwise, the contents apply to any platform that can run WCF. You may also install additional Windows components, such as MSMQ and IIS. Conventions Used in This Book The following typographical conventions are used in this book: Italic Used for technical terms, URLs, email addresses, filenames, and file extensions. Constant width Used for code samples, statements, namespaces, classes, assemblies, interface directives, operators, attributes, and reserved words. Constant width bold Used for emphasis in code samples. Preface | xix
  • 26. Constant width italic Shows text that should be replaced with user-supplied values or by values deter­ mined by context. This element signifies a tip or suggestion. This element signifies a general note. This element indicates a warning or caution. Whenever I wish to make a point in a code sample, I do so with the static Assert method of the Debug class: int number = 1+2; Debug.Assert(number = 3); The Assert method accepts a Boolean value and throws an exception when it is false. The book follows the recommended naming guidelines and coding style available at iDesign. Whenever it deviates from that standard, it is likely the result of space or line-length constraints. As for naming conventions, I use “Pascal casing” for public member methods and properties; this means the first letter of each word in the name is capitalized. For local variables and method parameters I use “camel casing,” in which the first letter of each word in the name is capitalized, with the exception of the first word. The names of private member variables are prefixed with m_: class SomeClass { int m_Number; public int Number {get;set}; } I use ellipses between curly braces to indicate the presence of code that is necessary but unspecified: xx | Preface
  • 27. class SomeClass {...} In the interest of clarity and space, code examples often do not contain all the using statements needed to specify all the namespaces the examples require; instead, such examples include only the new namespaces introduced in the preceding text. Safari® Books Online Safari Books Online is an on-demand digital library that deliv­ ers expert content in both book and video form from the world’s leading authors in technology and business. Technology professionals, software developers, web designers, and business and crea­ tive professionals use Safari Books Online as their primary resource for research, problem solving, learning, and certification training. Safari Books Online offers a range of plans and pricing for enterprise, government, education, and individuals. Members have access to thousands of books, training videos, and prepublication manuscripts in one fully searchable database from publishers like O’Reilly Media, Prentice Hall Professional, Addison-Wesley Professional, Microsoft Press, Sams, Que, Peachpit Press, Focal Press, Cisco Press, John Wiley & Sons, Syngress, Morgan Kauf­ mann, IBM Redbooks, Packt, Adobe Press, FT Press, Apress, Manning, New Riders, McGraw-Hill, Jones & Bartlett, Course Technology, and hundreds more. For more information about Safari Books Online, please visit us online. How to Contact Us Please address comments and questions concerning this book to the publisher: O’Reilly Media, Inc. 1005 Gravenstein Highway North Sebastopol, CA 95472 800-998-9938 (in the United States or Canada) 707-829-0515 (international or local) 707-829-0104 (fax) We have a web page for this book, where we list errata, examples, and any additional information. You can access this page at http://bit.ly/prog-wcf-services. You can also contact the author at: http://www.idesign.net. The author has posted a comprehensive code library on the IDesign website with more than 150 downloads related to WCF essentials, contract design, instance man‐ Preface | xxi
  • 28. agement, operations and calls, faults, transactions, concurrency, queuing, security, and the service bus. The downloads articulate many of the code snippets in this book in a working fashion. However, because of the large number of the downloads, the maintenance involved, and the fact that these secondary, accompanying examples do not themselves appear in the book, they are provided separately from the official sources. To comment or ask technical questions about this book, send email to bookques­ tions@oreilly.com. For more information about our books, courses, conferences, and news, see our web­ site at http://www.oreilly.com. Find us on Facebook: http://facebook.com/oreilly Follow us on Twitter: http://twitter.com/oreillymedia Watch us on YouTube: http://www.youtube.com/oreillymedia Acknowledgments I would not have been able to come to terms with WCF in its early days without the constant support of and interaction with the WCF (then Indigo) program managers. I am especially grateful to Steve Swartz, one of the WCF architects, not just for his knowledge and insight, but also for his patience with me and those long IM sessions. Thanks go to Yasser Shohoud, Doug Purdy, and Shy Cohen for the fascinating strate­ gic design reviews and to Krish Srinivasan for his almost philosophical approach to engineering. Working with you guys has been the best part of learning WCF and a privilege in its own right. The following WCF program managers also shared their time and helped clarify WCF: Andy Milligan, Brian McNamara, Eugene Osovetsky, Kenny Wolf, Kirill Gavrylyuk, Max Feingold, Michael Marucheck, Mike Vernal, and Steve Millet. Thanks also to the group manager, Angela Mills. Outside Microsoft, I am grateful to Nicholas Paldino for his help. This is the sixth book that Nick has reviewed for me, and by now I am hooked. I simply cannot imag­ ine going to print without Nick’s insight, meticulous scrutiny, and diligent help, to say nothing about Nick’s technical competence, which is nothing short of awe-striking and humbling. The books are always a superior product as a result of his editing and feedback. I dedicate the book to the IDesign Alumni. A unique post-class benefit of attending one of the IDesign Master Classes is joining this private forum where you can discuss practicing our techniques, share observation and insights, and ask pertinent ques­ tions. The members of the forum are all world-class developers, architects, and project leads, and the discussion amongst this group is profound, insightful, and of the highest quality. Many of the ideas and techniques in this book were first tried on xxii | Preface
  • 29. and trialed by the fire of the Alumni. The best emails I get each day are the discussion of the Alumni forum, and the level of mutual involvement, empathy, excellence, pro­ fessional integrity and responsiveness is second to none. It is truly inspiring that a community of mostly virtual peers can care about their trade and each other that much. I thank you for every time you made us stop and think about the best way of answering a question, a smarter way of solving an Alumni’s design problem, or the need for an improved technique. It is people like you that we write books for. Preface | xxiii
  • 31. CHAPTER 1 WCF Essentials This chapter describes the essential concepts and building blocks of Windows Com­ munication Foundation (WCF) and its architecture enabling you to build simple services. You will learn the basic terms regarding addresses, bindings, contracts, and endpoints; see how to host a service; learn how to write a client; understand related topics, such as in-process (in-proc) hosting reliability, and transport sessions; and see how to utilize WCF in Visual Studio. Even if you are already familiar with the basic concepts of WCF, I recommend that you give this chapter at least a cursory reading, not only to ensure that you have a solid foundation, but also because some of the helper classes and terms introduced here will be used and extended throughout the book. What Is WCF? WCF is a software development kit for developing and deploying services on Win­ dows (I will describe what a service is in the next section). But WCF is much more— it is literally a better .NET. WCF provides a runtime environment for your services, enabling you to expose Common Language Runtime (CLR) types as services and to consume other services as CLR types. Although in theory you could build services without WCF, in practice, building services is significantly easier with WCF. WCF is Microsoft’s implementation of a set of industry standards defining service interac­ tions, type conversions, marshaling, and the management of various protocols. Con­ sequently, WCF provides interoperability between services. WCF provides developers with the essential off-the-shelf plumbing required by almost all applications, and as such, it greatly increases productivity. The first release of WCF (as part of .NET 3.0) provided many useful facilities for developing services, such as hosting, service instance management, asynchronous calls, reliability, transac­ tion management, disconnected queued calls, and security. The second release of 1
  • 32. WCF (as part of .NET 3.5) provided additional tools and extended the original offer­ ing with additional communication options. The third release (as part of .NET 4.0) included configuration changes, a few extensions, and the new features of discovery (discussed in Appendix C) and routers (not discussed in this book). With WCF’s fourth release (as part of .NET 4.5), WCF has several new simplification features and additional bindings, including UDP and WebSocket bindings. WCF has an elegant extensibility model you can use to enrich the basic offering. In fact, WCF itself is written using this extensibility model. This book is dedicated to exploring these aspects and features. WCF is part of .NET 4.5, so it can run only on operating systems that support it. Presently, this list consists of Windows XP and later and Windows Server 2003 and later. Most of the WCF functionality is included in a single assembly called System.Service­ Model.dll, located in the System.ServiceModel namespace. Azure Service Bus Microsoft originally designed the Azure Service Bus to solve the broad and challeng­ ing connectivity issues of consuming web services over the Internet. The Azure Service Bus has since established itself as an indispensable tool for the modern developer who is creating connected systems on any platform. The Azure Service Bus has grown into a fully fledged connectivity platform with a diverse set of features. Recognizing that the challenges of providing service connectivity are not limited to the Internet, Microsoft has released an Intranet version of the Azure Service Bus named Service Bus for Windows Server. This version of the Service Bus targets the on­ premises versions of Windows Server and SQL Server. As a connectivity platform, the Service Bus offers a wide array of options for dis­ tributed computing solutions. These include service relay features, event publishing and subscription, persistent queues, and topics (queued events). The Service Bus also supports a modern, federated security model through claim-based access control. The Service Bus now supports a variety of programming models including classic WCF, REST-based and even Advanced Message Queuing Protocol (AMQP). From this set of building blocks, developers can create even more sophisticated patterns that enhance the scalability, throughput, discoverability, availability, and security of their solutions. The previous edition of this book devoted an in-depth chapter and a num­ ber of appendix sections to the Service Bus, along with several extensions and original enhancements. We consider the Service Bus nothing short of a fundamentally disruptive, essential platform for modern distributed computing. There is no question the Service Bus 2 | Chapter 1: WCF Essentials
  • 33. now merits a book in its own right to fully explore its many features and patterns in depth. We have therefore removed the chapters on the Service Bus from this edition. The material from those chapters will appear in greater and up-to-date detail in our forthcoming book dedicated to the Service Bus platform. Services A service is a unit of functionality exposed to the world. In that respect, it is the next evolutionary step in the long journey from functions to objects to components to services. Service orientation (SO) is an abstract set of principles and best practices for building service-oriented applications. Appendix A provides a concise overview and outlines the motivation for using this methodology. The rest of this book assumes you are familiar with these principles. A service-oriented application aggregates serv­ ices into a single logical application, similar to the way a component-oriented applica­ tion aggregates components and an object-oriented application aggregates objects, as shown in Figure 1-1. Figure 1-1. A service-oriented application The services can be local or remote, can be developed by multiple parties using any technology, can be versioned independently, and can even execute on different time­ lines. Inside a service, you will find concepts such as languages, technologies, plat­ forms, versions, and frameworks, yet between services, only prescribed communication patterns are allowed. The client of a service is merely the party consuming its functionality. The client can be literally anything—for instance, a Windows Forms, WPF, Silverlight, or Windows Store App class, an ASP.NET page, or another service. Clients and services interact by sending and receiving messages. Messages may be transferred directly from the client to the service or be sent via an intermediary such Services | 3
  • 34. as the Azure Service Bus. With WCF, messages are SOAP messages. These messages are independent of transport protocols—unlike web services, WCF services may communicate over a variety of transports (not just HTTP). WCF clients may intero­ perate with non-WCF services, and WCF services can interact with non-WCF clients. That said, if you develop both the client and the service, you can typically construct the application so that both ends require WCF in order to utilize WCF-specific advantages. Because the making of the service is opaque from the outside, a WCF service typically exposes metadata describing the available functionality and possible ways of commu­ nicating with the service. The metadata is published in a predefined, technology­ neutral way, such as using Web Services Description Language (WSDL) over HTTP­ GET or an industry standard for metadata exchange over any protocol. A non-WCF client can import the metadata to its native environment as native types. Similarly, a WCF client can import the metadata of a non-WCF service and consume it as native CLR classes and interfaces. Service Execution Boundaries With WCF, the client never interacts with a service directly, even when dealing with a local, in-memory service. Instead, the client always uses a proxy to forward calls to the service. The proxy exposes the same operations as the service, plus some proxy­ management methods. WCF allows the client to communicate with a service across all execution boundaries. On the same machine, the client can consume services in the same app domain, across app domains in the same process, or across processes (see Figure 1-2). Figure 1-2. Same-machine communication using WCF Across machine boundaries (Figure 1-3), the client can interact with services in its intranet or across the Internet. 4 | Chapter 1: WCF Essentials
  • 35. Figure 1-3. Cross-machine communication using WCF WCF and Location Transparency In the past, distributed computing technologies such as DCOM and .NET remoting aspired to provide the same programming model to the client regardless of whether the object was local or remote. In the case of a local call, the client used a direct refer­ ence, and when dealing with a remote object, the client used a proxy. The problem with trying to use the local programming model as the remote programming model was that there is much more to a remote call than an object with a wire. Complex issues such as lifecycle management, reliability, state management, and security reared their heads, making the remote programming model significantly more com­ plex. Numerous problems arose, all because the remote object was trying to be what it is not—a local object. WCF also strives to provide the client with the same programming model regardless of the location of the service. However, the WCF approach is the exact opposite: it takes the remote programming model of instantiating and using a proxy and uses it even in the most local case. Because all interactions are done via a proxy, requiring the same configuration and hosting, WCF maintains the same programming model for the local and remote cases; thus, it not only enables you to switch locations without affecting the client, but also significantly simplifies the application program­ ming model. Another important benefit of always using a proxy is that it enables WCF to intercept the calls and add its value, as you will see later on. Addresses In WCF, every service is associated with a unique address. The address provides two important elements: the location of the service and the transport protocol, or trans­ port scheme, used to communicate with the service. The location portion of the address indicates the name of the target machine, site, or network; a communication port, pipe, or queue; and an optional specific path, or Uniform Resource Ifepvkfier Addresses | 5
  • 36. (URI). A URI can be any unique string, such as the service name or a globally unique identifier (GUID). Out of the box, WCF supports the following transport schemes: • HTTP/HTTPS • TCP • IPC • MSMQ • Service Bus • WebSocket • UDP Addresses always have the following format: [base address]/[optional URI] The base address is always in this format: [transport]://[machine or domain][:optional port] Here are a few sample addresses: http://localhost:8001 http://localhost:8001/MyService net.tcp://localhost:8002/MyService net.pipe://localhost/MyPipe net.msmq://localhost/private/MyQueue net.msmq://localhost/MyQueue ws://localhost/MyService soap.udp://localhost:8081/MyService The way to read an address such as: http://localhost:8001 is like this: “Using HTTP, go to the machine called localhost, where on port 8001 someone is waiting for my calls.” If there is also a URI, as in: http://localhost:8001/MyService the address will read as follows: “Using HTTP, go to the machine called localhost, where on port 8001 someone called MyService is waiting for my calls.” TCP Addresses TCP addresses use net.tcp for transport and typically include a port number, as in: 6 | Chapter 1: WCF Essentials
  • 37. net.tcp://localhost:8002/MyService When a port number is not specified, the TCP address defaults to port 808: net.tcp://localhost/MyService It is possible for two TCP addresses (from the same host, as discussed later in this chapter) to share a port: net.tcp://localhost:8002/MyService net.tcp://localhost:8002/MyOtherService TCP-based addresses are used throughout this book. You can configure TCP-based addresses from different service hosts to share a port. HTTP Addresses HTTP addresses use http for transport and can also use https for secure transport. You typically use HTTP addresses with outward-facing Internet-based services, and you can specify a port as shown here: http://localhost:8001 If you do not specify the port number, it defaults to 80 (and port 443 for HTTPS). As with TCP addresses, two HTTP addresses from the same host can share a port, even on the same machine. HTTP-based addresses are also used throughout this book. IPC Addresses Inter-process communication (IPC) addresses use net.pipe for transport, to indicate the use of the Windows named pipe mechanism. In WCF, services that use IPC can only accept calls from the same machine. Consequently, you must specify either the explicit local machine name or localhost for the machine name, followed by a unique string for the pipe name: net.pipe://localhost/MyPipe You can open a named pipe only once per machine, so it is not possible for two named pipe addresses to share a pipe name on the same machine. IPC-based addresses are used throughout this book. Addresses | 7
  • 38. The IPC address format as provided by Microsoft is incorrect, indi­ cating the mechanism instead of the protocol. The correct scheme format should have been net.ipc instead of net.pipe, much like the TCP address uses net.tcp rather than net.socket. MSMQ Addresses MSMQ addresses use net.msmq for transport, to indicate the use of the Microsoft Message Queue (MSMQ). You must specify the queue name. When you’re dealing with private queues, you must also specify the queue type, but you can omit that for public queues: net.msmq://localhost/private/MyService net.msmq://localhost/MyService Chapter 9 is dedicated to making queued calls. WebSocket Addresses WebSocket addresses are unique in that they are asymmetrical between client and service. The client uses ws for transport and wss for secure transport, while the ser­ vice always uses http or https respectively. WebSocket addresses are required when you need callbacks over the Internet, and you can specify a port as shown here: ws://localhost:8080 If you do not specify the port number, a WebSocket defaults to the standard HTTP port 80 (and port 443 for wss or HTTPS). As with TCP addresses, two WebSocket addresses on the same machine from the same host can share a port. UDP Addresses UDP addresses use soap.udp for transport, to indicate SOAP over UDP is being used. You can also specify a port as shown here: soap.udp://localhost:8081 Contracts In WCF, all services expose contracts. The contract is a platform-neutral and standard way of describing what the service does. WCF defines four types of contracts: Service contracts Describe which operations the client can perform on the service. Service con­ tracts are the subject of Chapter 2, but they are used extensively in every chapter in this book. 8 | Chapter 1: WCF Essentials
  • 39. Data contracts Define which data types are passed to and from the service. WCF defines implicit contracts for built-in types such as int and string, but you can easily define explicit opt-in data contracts for custom types. Chapter 3 is dedicated to defining and using data contracts, and subsequent chapters make use of data contracts as required. Fault contracts Define which errors are raised by the service and how the service handles and propagates errors to its clients. Chapter 6 is dedicated to defining and using fault contracts. Message contracts Allow the service to interact directly with messages. Message contracts can be typed or untyped and are useful in interoperability cases when another party has already dictated some explicit (typically proprietary) message format. This, how­ ever, is by no means the usual case for common WCF applications, so this book makes no use of message contracts. Unless you are required to leverage the flexi­ bility, power, and extensibility of message contracts, you should avoid them, as they add no value, but do add complexity. In many cases, the desire to use mes­ sage contracts indicates a need for a custom application context, which you can address using custom headers (a useful alternative technique used throughout this book). For more on message headers, see Appendix B. The Service Contract The ServiceContractAttribute is defined as: [AttributeUsage(AttributeTargets.Interface|AttributeTargets.Class, Inherited = false)] public sealed class ServiceContractAttribute : Attribute { public string Name {get;set;} public string Namespace {get;set;} //More members } This attribute allows you to define a service contract. You can apply the attribute on an interface or a class, as shown in Example 1-1. Example 1-1. Defipkpg and implementing a service contract [ServiceContract] interface IMyContract { Contracts | 9
  • 40. [OperationContract] string MyMethod(string text); //Will not be part of the contract string MyOtherMethod(string text); } class MyService : IMyContract { public string MyMethod(string text) { return "Hello " + text; } public string MyOtherMethod(string text) { return "Cannot call this method over WCF"; } } The ServiceContract attribute maps a CLR interface (or inferred interface, as you will see later) to a technology-neutral service contract. The ServiceContract attribute exposes a CLR interface (or a class) as a WCF contract independently of that type’s visibility. The type visibility has no bearing on WCF, because visibility is a CLR concept. Applying the ServiceContract attribute on an internal interface exposes that interface as a public service contract, ready to be consumed across the assembly boundary. Without the ServiceContract attribute, the interface is not visible to WCF clients, in line with the service-oriented tenet that service boundaries should be explicit. To enforce that tenet, all contracts must explicitly opt in: only interfaces (or classes) decorated with the ServiceContract attribute will be considered WCF con­ tracts; other types will not. In addition, none of the members of the type will ever be part of the contract when using the ServiceContract attribute. You must explicitly indicate to WCF which methods to expose as part of the WCF contract using the OperationContractAttri bute, defined as: [AttributeUsage(AttributeTargets.Method)] public sealed class OperationContractAttribute : Attribute { public string Name {get;set;} //More members } You can apply the OperationContract attribute only on methods, not on properties, indexers, or events, which are CLR concepts. WCF only understands operations—log­ ical functions—and the OperationContract attribute exposes a contract method as a logical operation to perform as part of the service contract. Other methods on the interface (or class) that do not have the OperationContract attribute will not be part 10 | Chapter 1: WCF Essentials
  • 41. of the contract. This enforces explicit service boundaries and maintains an explicit opt-in model for the operations themselves. In addition, a contract operation cannot use object references as parameters: only primitive types or data contracts are allowed. Applying the ServiceContract attribute WCF lets you apply the ServiceContract attribute on an interface or on a class. When you apply it on an interface, some class needs to implement that interface. In general, you use plain C# or VB to implement the interface, and nothing in the ser­ vice class code pertains to it being a WCF service: [ServiceContract] interface IMyContract { [OperationContract] string MyMethod(); } class MyService : IMyContract { public string MyMethod() { return "Hello WCF"; } } You can use implicit or explicit interface implementation: class MyService : IMyContract { string IMyContract.MyMethod() { return "Hello WCF"; } } Because the client can never use the service class directly and must always go through a proxy, using explicit interface implementation is less important in WCF than it is in regular .NET programming. A single class can support multiple contracts by deriving and implementing multiple interfaces decorated with the ServiceContract attribute: [ServiceContract] interface IMyContract { [OperationContract] string MyMethod(); Contracts | 11
  • 42. } [ServiceContract] interface IMyOtherContract { [OperationContract] void MyOtherMethod(); } class MyService : IMyContract,IMyOtherContract { public string MyMethod() {...} public void MyOtherMethod() {...} } There are, however, a few implementation constraints on the service implementation class. You should avoid parameterized constructors, because WCF will only use the default constructor. Also, although the class can use internal properties, indexers, and static members, no WCF client will ever be able to access them. WCF also lets you apply the ServiceContract attribute directly on the service class, without defining a separate contract first: //Avoid [ServiceContract] class MyService { [OperationContract] string MyMethod() { return "Hello WCF"; } } Under the covers, WCF will infer the contract definition. You can apply the Opera tionContract attribute on any method of the class, be it private or public. Avoid using the ServiceContract attribute directly on the service class. Always define a separate contract so that you can both con­ sume it independently of the class and have other classes imple­ ment it. Names and namespaces You can and should define a namespace for your contract. The contract namespace serves the same purpose in WCF as it does in .NET programming: to scope a type of contract and reduce the overall chance of a collision. You can use the Namespace property of the ServiceContract attribute to provide a namespace: 12 | Chapter 1: WCF Essentials
  • 43. [ServiceContract(Namespace = "MyNamespace")] interface IMyContract {...} Unspecified, the contract namespace defaults to http://tempuri.org. For outward­ facing services, you typically use your company’s URL, and for intranet services, you can use any meaningful unique name, such as MyApplication. By default, the exposed name of the contract will be the name of the interface. How­ ever, you can use an alias for a contract to expose a different name to the clients in the metadata, by using the Name property of the ServiceContract attribute: [ServiceContract(Name = "IMyContract")] interface IMyOtherContract {...} Similarly, the name of the publicly exposed operation defaults to the method name, but you can use the Name property of the OperationContract attribute to alias it to a different publicly exposed name: [ServiceContract] interface IMyContract { [OperationContract(Name = "SomeOperation")] void MyMethod(string text); } You will see a use for these properties in Chapter 2. Hosting The WCF service class cannot exist in a void. Every WCF service must be hosted in a Windows process called the host process. A single host process can host multiple serv­ ices, and the same service type can be hosted in multiple host processes. WCF has no restrictions regarding whether or not the host process is also the client process, although having a separate process promotes fault and security isolation. It is also immaterial who provides the process and what kind of process is involved. The host can be provided by Internet Information Services (IIS), by the Windows Activation Service (WAS) on versions of Windows before Windows Server 2008 R2 and Win­ dows 7, or by the developer as part of the application. In-process (or in-proc) hosting, where the service resides in the same process as the client, is a special case. By definition, the devel­ oper provides the host for the in-proc case. Hosting | 13
  • 44. IIS Hosting The main advantage of hosting a service on the Microsoft IIS web server is that the host process is launched automatically upon the first client request, and IIS manages the lifecycle of the host process. The main disadvantage of IIS hosting is that you can only use HTTP. Hosting in IIS is very similar to hosting a web service or ASP.NET Web API service. You need to provide a virtual directory under IIS and supply an .svc file. IIS uses the .svc file to identify the service code behind the file and class. Example 1-2 shows the syntax for the .svc file. Example 1-2. A .svc fine <%@ ServiceHost Language = "C#" Debug = "true" CodeBehind = "~/App_Code/MyService.cs" Service = "MyService" %> You can even inject the service code inline in the .svc file, but that is not advisable. When you use IIS hosting, the base address used for the service always has to be the same as the address of the .svc file. Using Visual Studio You can use Visual Studio to generate a boilerplate IIS-hosted service. From the File menu, select New Web Site, then select WCF Service from the New Web Site dialog box. Visual Studio creates a new website, service code, and a matching .svc file. You can also use the Add New Item dialog box to add another service later. The Web.Eonfii fiffle The website config file (yeb.eqpfig) typically lists the types you want to expose as services. You need to use fully qualified type names, including the assembly name if the service type comes from an unreferenced assembly: <system.serviceModel> <services> <service name = "MyNamespace.MyService"> ... </service> 14 | Chapter 1: WCF Essentials
  • 45. </services> </system.serviceModel> Instead of defining an .svc file, you can provide the service type and its address infor­ mation directly in the application yeb.eqpfig file in the serviceHostingEnvironment section. In fact, you can list as many services as you like there: <system.serviceModel> <serviceHostingEnvironment> <serviceActivations> <add relativeAddress = "MyService.svc" service = "MyNamespace.MyService"/> <add relativeAddress = "MyOtherService.svc" service = "MyOtherService"/> </serviceActivations> </serviceHostingEnvironment> <services> <service name = "MyNamespace.MyService"> ... </service> <service name = "MyOtherService"> ... </service> </services> </system.serviceModel> Self-Hosting Self-hosting is the technique in which the developer is responsible for providing and managing the lifecycle of the host process. Use self-hosting when you want a process (or machine) boundary between the client and the service and when you are using the service in-proc—that is, in the same process as the client. You can provide any Windows process, such as a Windows Forms application, a WPF application, a Con­ sole application, or a Windows Service. Note that the process must be running before the client calls the service, which typically means you have to prelaunch it. This is not an issue for Windows Services or in-proc hosting. You can provide a host with only a few lines of code. Unlike IIS, a self-hosted service can use any WCF transport proto­ col, and you can take advantage of all the WCF features, including the Service Bus, discovery, and utilizing a singleton service. As with IIS hosting, the hosting application config file (app.eqpfig) typically lists the types of the services you wish to host and expose to the world: <system.serviceModel> <services> <service name = "MyNamespace.MyService"> ... </service> </services> </system.serviceModel> Hosting | 15
  • 46. In addition, the host process must explicitly register the service types at runtime and open the host for client calls, which is why the host process must be running before the client calls arrive. Creating the host is typically done in the Main() method using the class ServiceHost, defined in Example 1-3. Example 1-3. The ServiceHost class public interface ICommunicationObject { void Open(); void Close(); //More members } public abstract class CommunicationObject : ICommunicationObject {...} public abstract class ServiceHostBase : CommunicationObject,IDisposable,... {...} public class ServiceHost : ServiceHostBase { public ServiceHost(Type serviceType,params Uri[] baseAddresses); //More members } You need to provide the constructor of ServiceHost with the service type and optionally with default base addresses. The set of base addresses can be an empty set, and even if you provide base addresses, you can configure the service to use different base addresses. Having a set of base addresses enables the service to accept calls on multiple addresses and protocols and to use only a relative URI. Note that each ServiceHost instance is associated with a particular service type, and if the host process needs to host multiple types of services, you will need a matching number of ServiceHost instances. By calling the Open() method on the host, you allow calls in, and by calling the Close() method, you gracefully exit the host instance, allowing calls in progress to complete while refusing future client calls even if the host process is still running. Closing the service host is typically done when the host process shuts down. For example, to host this service in a Windows Forms appli­ cation: [ServiceContract] interface IMyContract {...} class MyService : IMyContract {...} you would write the following hosting code: static void Main() { ServiceHost host = new ServiceHost(typeof(MyService)); 16 | Chapter 1: WCF Essentials
  • 47. host.Open(); //Can do blocking calls: Application.Run(new MyForm()); host.Close(); } Opening a host loads the WCF runtime and launches worker threads to monitor incoming requests. The monitoring threads dispatch incoming calls to worker threads from the I/O completion thread pool (where there are up to 1,000 threads by default). Because worker threads are involved, you can perform blocking operations after opening the host. Because the host is closed gracefully, the amount of time it will take is undetermined. By default, the host will block for 10 seconds waiting for Close() to return and will proceed with the shutdown after that timeout has expired. Before opening the host, you can configure a different close timeout with the CloseTimeout property of ServiceHostBase: public abstract class ServiceHostBase : ... { public TimeSpan CloseTimeout {get;set;} //More members } For example, you can use programmatic calls to set the close timeout to 20 seconds: ServiceHost host = new ServiceHost(...); host.CloseTimeout = TimeSpan.FromSeconds(20); host.Open(); You can do the same in a config file by placing the close timeout in the host section of the service: <system.serviceModel> <services> <service name = "MyNamespace.MyService"> <host> <timeouts closeTimeout = "00:00:20" /> </host> ... </service> </services> </system.serviceModel> Hosting | 17
  • 48. Using Visual Studio Visual Studio allows you to add a WCF service to any application project by selecting WCF Service from the Add New Item dialog box. A service added this way is, of course, in-proc toward the host process, but out-of-proc clients can also access it. Self-hosting and base addresses You can launch a service host without providing any base address by omitting the base addresses altogether: ServiceHost host = new ServiceHost(typeof(MyService)); Do not provide a null instead of an empty list, because that will throw an exception: ServiceHost host; host = new ServiceHost(typeof(MyService),null); You can also register multiple base addresses separated by commas, as in the follow­ ing snippet, as long as the addresses do not use the same transport scheme (note the use of the params qualifier in Example 1-3): Uri tcpBaseAddress = new Uri("net.tcp://localhost:8001/"); Uri httpBaseAddress = new Uri("http://localhost:8002/"); ServiceHost host = new ServiceHost(typeof(MyService), tcpBaseAddress,httpBaseAddress); WCF also lets you list the base addresses in the host config file: <system.serviceModel> <services> <service name = "MyNamespace.MyService"> <host> <baseAddresses> <add baseAddress = "net.tcp://localhost:8001/"/> <add baseAddress = "http://localhost:8002/"/> </baseAddresses> </host> ... </service> </services> </system.serviceModel> When you create the host, it will use whichever base addresses it finds in the config file, plus any base addresses you provide programmatically. Take extra care to ensure the configured base addresses and the programmatic ones do not overlap in the scheme. 18 | Chapter 1: WCF Essentials
  • 49. On any machine running Windows XP or later, for HTTP addresses other than port 80, you will need to launch the host pro­ cess (or Visual Studio while testing or debugging) as an adminis­ trator. Instead of doing that every time, you can instruct Windows to reserve the port namespace for the user running the host. Do this using the netsh.exe command-line utility. For example, to reserve the HTTP port 8002 on the local machine, you will need to run this command at a command prompt launched as an adminis­ trator: netsh http add urlacl url=http://+:8002/user= "MachineOrDomainUserName" You can even register multiple hosts for the same type, as long as the hosts use differ­ ent base addresses: Uri baseAddress1 = new Uri("net.tcp://localhost:8001/"); ServiceHost host1 = new ServiceHost(typeof(MyService),baseAddress1); host1.Open(); Uri baseAddress2 = new Uri("net.tcp://localhost:8002/"); ServiceHost host2 = new ServiceHost(typeof(MyService),baseAddress2); host2.Open(); However, with the exception of some threading issues discussed in Chapter 8, open­ ing multiple hosts this way offers no real advantage. In addition, opening multiple hosts for the same type does not work with base addresses supplied in the config file and requires use of the ServiceHost constructor. Advanced hosting features The ICommunicationObject interface that ServiceHost supports offers some advanced features, listed in Example 1-4. Example 1-4. The ICommunicationObject interface public interface ICommunicationObject { void Open(); void Close(); void Abort(); event EventHandler Closed; event EventHandler Closing; event EventHandler Faulted; event EventHandler Opened; event EventHandler Opening; IAsyncResult BeginClose(AsyncCallback callback,object state); IAsyncResult BeginOpen(AsyncCallback callback,object state); void EndClose(IAsyncResult result); Hosting | 19
  • 50. void EndOpen(IAsyncResult result); CommunicationState State {get;} //More members } public enum CommunicationState { Created, Opening, Opened, Closing, Closed, Faulted } If opening or closing the host is a lengthy operation, you can do so asynchronously with the BeginOpen() and BeginClose() methods. You can subscribe to hosting events such as state changes or faults, and you can use the State property to query for the host status. Finally, the ServiceHost class also offers the Abort() method. Abort() is an ungraceful exit—when called, it immedi­ ately aborts all service calls in progress and shuts down the host. Active clients will each get an exception. The ServiceHost<T> class You can improve on the WCF-provided ServiceHost class by defining the Service Host<T> class, as shown in Example 1-5. Example 1-5. The ServiceHost<T> class public class ServiceHost<T> : ServiceHost { public ServiceHost() : base(typeof(T)) {} public ServiceHost(params string[] baseAddresses) : base(typeof(T), baseAddresses.Select(address=>new Uri(address)).ToArray()) {} public ServiceHost(params Uri[] baseAddresses) : base(typeof(T),baseAddresses) {} } ServiceHost<T> provides simple constructors that do not require the service type as a construction parameter and that can operate on raw strings instead of the cumber­ some Uri. I’ll add quite a few extensions, features, and capabilities to ServiceHost<T> throughout this book. 20 | Chapter 1: WCF Essentials
  • 51. WAS Hosting The problem with hosting in IIS is that it is a web server, not a hosting engine. It therefore requires you to masquerade your service as a website. While ASP.NET encapsulates this step for you, it causes a significant increase in internal complexity, involving the HTTP modules and the ASP.NET pipeline. The problem is that the more moving parts involved, the higher the likelihood of something going wrong. Moreover, limiting the service to using only HTTP makes IIS ill-suited for intranet applications. With the next wave of Windows, Microsoft rectified this issue by providing a general­ purpose hosting engine called the Windows Activation Service (WAS). WAS is a sys­ tem service available with Windows versions Windows Server 2008 or later. The WAS is a true general-purpose hosting engine. It can host websites (in fact, IIS 7 or later will host its websites in the WAS by default), but it can just as easily host your serv­ ices, allowing you to use any transport, such as TCP, IPC, or MSMQ. You can install and configure the WAS separately from IIS. Hosting a WCF service in the WAS is designed to look just like hosting in IIS. You need to either supply an .svc file, just as with IIS, or provide the equivalent information in the config file. All the other devel­ opment aspects, such as support in Visual Studio, remain exactly the same. Because the WAS is a system service, you do not need to pre-launch your service host process. When the first client call arrives, the WAS will intercept it, launch a worker process to host your service, and forward it the call. WAS offers many features beyond self-hosting, including application pooling, recy­ cling, idle time management, identity management, and isolation. To use the WAS, you must target a platform that supports it, such as a Windows Server 2008 (or later) machine for scalability, or a Windows 7 (or later) client machine for a handful of cli­ ents. That said, self-hosted processes do offer singular advantages, such as in-proc hosting, dealing well with unknown customer environments, and easy programmatic access to the advanced hosting features described previously. Custom Hosting in IIS/WAS It is often the case that you need to interact with the host instance. While this is inte­ gral to the use of a self-hosting solution, when using IIS or WAS, you have no direct access to the host. To overcome this hurdle, WCF provides a hook called a host fac­ tory. Using the Factory tag in the .svc file, you can specify a class you provide that creates the host instance: <%@ ServiceHost Language = "C#" Debug = "true" CodeBehind = "~/App_Code/MyService.cs" Hosting | 21
  • 52. Service = "MyService" Factory = "MyServiceFactory" %> You can also specify the host factory in the config file when not using an .svc file explicitly: <serviceActivations> <add relativeAddress = "MyService.svc" service = "MyService" factory = "MyServiceFactory" /> </serviceActivations> The host factory class must derive from the ServiceHostFactory class and override the CreateServiceHost() virtual method: public class ServiceHostFactory : ... { protected virtual ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses); //More members } For example: class MyServiceFactory : ServiceHostFactory { protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) { ServiceHost host = new ServiceHost(serviceType,baseAddresses); //Custom steps here return host; } } The CreateServiceHost() method is logically the Main() method of an IIS or WAS hosted service, and you can use it just for that purpose. Choosing a Host Although WCF offers such a variety of options, from IIS, to the WAS, to self-hosting, it is easy to choose the correct host, as shown in Figure 1-4. For an Internet applica­ tion (i.e., an application that receives calls from clients across the Internet), IIS or the WAS provide the best capabilities to harden your services against the security con­ 22 | Chapter 1: WCF Essentials
  • 53. cerns of access over the Internet. Otherwise prefer self-hosting your services. Self­ hosting provides your organization with a hosting model that significantly simplifies the administration and provisioning of intranet services. WCF services do not require the many additional lifecycle management facilities that the WAS provides. Figure 1-4. Choosing a host for any service Microsoft will retire Windows Server AppFabric in April 2016. You should not target any of its features, particularly the service autos­ tart feature, for any of your systems. Bindings There are multiple aspects of communication with any given service, and there are many possible communication patterns. Messages can follow a synchronous request­ reply or asynchronous fire-and-forget pattern, messages can be bidirectional, mes­ sages can be delivered immediately or queued, and the queues can be durable or volatile. As discussed previously, there are many possible transport protocols for the messages, such as HTTP (or HTTPS), TCP, IPC, MSMQ. There are also a few possi­ ble message encoding options. You can choose plain text to enable interoperability, binary encoding to optimize performance, or the Message Transport Optimization Bindings | 23
  • 54. Mechanism (MTOM) for large payloads. Finally, there are multiple options for secur­ ing messages. You can choose not to secure them at all, to provide transport-level security only, or to provide message-level privacy and security, and of course, there are numerous ways to authenticate and authorize the clients. Message delivery might be unreliable or reliable end-to-end across intermediaries and dropped connections, and the messages might be processed in the order they were sent or in the order they were received. Your service might need to interoperate with other services or clients that are aware of only the basic web service protocol, or with clients and services capable of using the score of WS-* protocols, such as WS-Security and WS-Atomic Transactions. Your service may need to have the capability to interoperate with any client or you may want to restrict your service to interoperate only with another WCF service or client. If you were to count all the possible communication and interaction options, you’d probably find that the number of permutations is in the tens of thousands. Some of those choices may be mutually exclusive and some may mandate other choices. Clearly, both the client and the service must be aligned on all these options in order to communicate properly. Managing this level of complexity adds no business value to most applications, and yet the productivity and quality implications of making the wrong decisions are severe. To simplify these choices and make them manageable, WCF groups together sets of communication aspects in bindings. A binding is merely a consistent, canned set of choices regarding the transport protocol, message encoding, communication pattern, reliability, security, transaction propagation, and interoperability. All you need to do is determine the target scenario for your service, and WCF makes a correct multidi­ mensional decision for you regarding all the aspects of the communication. Ideally, you can extract all these “plumbing” aspects from your service code and allow the service to focus solely on the implementation of the business logic. Bindings allow you to use the same service logic over drastically different plumbing. You can use the WCF-provided bindings out of the box, you can tweak their proper­ ties, or you can write your own custom bindings from scratch. The service publishes its choice of binding in its metadata, enabling clients to query for the type and spe­ cific properties of the binding. This is important because the client must use the exact same binding values as the service. A single service can support multiple bindings on separate addresses. The Common Bindings WCF defines five frequently used bindings: Basic binding Offered by the BasicHttpBinding class, basic binding is designed to expose a WCF service as a legacy ASMX web service so that old clients can work with new 24 | Chapter 1: WCF Essentials
  • 55. Random documents with unrelated content Scribd suggests to you:
  • 56. "Tarkoitatko, että olet valehdellut?" "Tyhjää valhetta kaikki!" "Sinä olet ilkeä, Anna." "Kai lienen. En ole muuten kovin onnellinenkaan, se minun on sanottava. — Mutta rouvat ovat jo heränneet ja herrat tulevat saliin. Mennään sinne!" Kynnyksellä hänet pysäyttää Gösta Berling, joka tulee nuorten naisten seuraan. "Teidän pitää nyt olla minulle kärsivällisiä", hän sanoo nauraen. "Kiusaan teitä vain kymmenen minuuttia, mutta nyt teidän täytyy kuunnella runoa." Hän kertoo heille, että oli viime yönä nähnyt unta elävämmin kuin juuri koskaan, hän oli nähnyt sellaista unta, että oli muka kirjoittanut runon. Hän, jota ihmiset sanoivat "runoilijaksi", vaikka hän oli tähän asti saanut aivan aiheetta omistaa tuon lisänimen, hän oli silloin, keskellä yötä, noussut ja puolittain unessa, puolittain valveilla alkanut kirjoittaa. Ja runoelman hän oli sitten aamulla löytänyt kirjoituspöydältään. Hän ei ollut ikinä uskonut mokomaa itsestään. Ja nyt piti naisten se kuulla. Ja hän lukee: Nousi nyt kuu, ihanimman vuorokauden hetkistä toi. Sinikirkkaalta, kalvaalta holviltaan läpi köynnösten hohtoa parvekkeelle se seuloi, jonk' alla värisi uurnassaan punalilja, min terään päivätär kultapäärmehet neuloi. Kiviportaill' istuen unelmoi siin' ääneti nuoret ja vanhat, kuunnellen noita
  • 57. sydämen vanhoja lauluja, muistoon joita ihanimpana vuorokauden hetkistä tunne toi. Reseedaryhmästä nous' sulotuoksu, meit' ympäröi, ja viidoista tummien pensastoin varjoja hiipii kasteisen, välkkyvän nurmikon laitaa. Sielukin ruumiin varjosta noin valon ilmoihin, seutuihin, joita se tuskin tajuta taitaa, sinihohto-holveihin ikävöi, kirkkauteen, johon verraten tähdet on kelmeet. Oi, kuka torjuu tunteiden leikit ja telmeet, yön varjot, reseedain suruisa tuoksu kun ympäröi. Terät köynnösruusun tippui viimeiset, vaalenneet, vaikkei niit' uhriksi vaatinut tuulonen vallaton. Noin — mietittiin — elon jättää soisimme, haipuin ilmaan kuin sävel kantelon, kuin lehti syyskelmeä tyhjiin vaikertamatta vaipuin. Pitkät miks' iän taipaleet? Luontoa häiriten nauttimaan elon harhasta jäämme. Kuolema on elon palkka; siis hiljaa se jättäkäämme, kuin terät köynnösruusun viimeiset, vaalenneet. Yösiippa häilähtäin ohi liipotti, minne lie, häipyi pois, kuun kohdalla häämötti taas. Vaan silloin nous poven ankeen alta tuo kysymys raskas kuin haudan paas, tuo yhä vastaamaton, tuo vanha kuin tuskan valta: "Oi, mihin kuljemme, oi, mik' on eessämme tie, konsa maan vihreät niityt ei enää allamme loista?" Hengen tielle voipiko toinen neuvoa toista, — yösiippaa helpommin neuvot, mi liipotti, minne lie.
  • 58. Ja olkaani päänsä hän, pehmeät kutrinsa, kallistaa, hän, joka minua lempi, ja kuiskivi hiljaa näin: Elä usko, ei kaukaisiin avaruuksihin sielut lennä; kun kuolen, el' usko, ett' etäällä oon. Mihin koditon sieluni vois, jos ei lemmityn sieluun mennä? Sun luonas se ainian asukoon! Oi ahdistus! Suru sydämen murtaa tahtoi. Hänet kuoloko veis, pian veis? Yö viimeinen olla jo mahtoi? Viimeisen kerranko suutelin kutria aaltoavaa? On vuosia vierinyt. Viel' yhä varjohon siell' usein istun, kun yö tutun paikan on tummentanut. Mut parvekkeell' läpi köynnösten kuultavan kuun näen kammoin. Se yksin tietää, kuink' usein armasta suudellut siell' oon, se värjyen kirkkaasti kyyneleet ammoin, joit' armaani kutreille vierinyt on. Voi, muistojen tuskaa! Se syntisen sieluni vaiva on tietää: hän asuvi siinä! Minkä rangaistuksen se sietää, ken sitoi itseensä sielun, mi niin oli puhdas ja tahraton. "Gösta", sanoo Anna leikillisesti, vaikka tuska kuristaa hänen kurkkuaan, "sinusta sanotaan, että olet elänyt useampia runoja kuin toiset ovat kirjoittaneet, vaikk'eivät olisi elämässään muuta tehneetkään, mutta tiedätkös: sinun on parasta runoilla omalla tavallasi. Tuo oli yötyötä, tiedätkös." "Et ole lempeä, Anna." "Tulla lukemaan tuollaista, kuolemasta ja surkeudesta, — ettet häpeä!"
  • 59. Gösta ei kuule enää häntä. Hänen silmänsä ovat suunnatut nuoreen kreivittäreen. Kreivitär istuu aivan jäykkänä, liikkumattomana kuin kuvapatsas. Göstasta hän näyttää kuin pyörtyvän. Mutta sanomattoman työläästi saa kreivitär sanan huuliltaan. "Menkää!" hän sanoo. "Kuka, menkää? Pitääkö minun mennä?" "Papin pitää mennä", änkyttää kreivitär. "Elisabet, ole toki vaiti!" "Juoppo pappi saa mennä ulos huoneestani!" "Anna, Anna", kysyy Gösta, "mitä hän tarkoittaa?" "Parasta on sinun mennä, Gösta." "Miksi minun pitää mennä? Mitä tämä merkitsee?" "Anna", sanoo kreivitär Elisabet, "sano hänelle, sano hänelle…!" "En, sano itse, kreivitär!" Kreivitär puree hampaansa yhteen ja masentaa liikutuksensa. "Herra Berling", hän sanoo ja astuu hänen eteensä, "teillä on merkillinen kyky saada ihmiset unohtamaan, kuka olette. Minä en ole tiennyt sitä ennen kuin tänään. Olen juuri kuullut kertomuksen Ebba Dohnan kuolemasta ja saanut samalla tietää, että tieto, että hän rakasti arvotonta, tappoi hänet. Teidän runonne on selittänyt
  • 60. minulle, että se mies olette te. En voi ymmärtää, miten kukaan sellaisen jälkeen, kuin te olette elänyt, voi olla kunniallisen naisen seurassa. Minä en voi sitä ymmärtää, herra Berling. Puhuinko nyt kyllin selvästi?" "Kyllä, kreivitär. Tahdon vain sanoa yhden ainoan sanan puolustuksekseni. Olin vakuuttunut siitä, koko ajan olen ollut varma siitä, että te tiesitte kaiken minusta. En ole koskaan yrittänyt salata mitään, mutta eipä liene hauska huudella elämänsä katkerimpia onnettomuuksia turuilla ja teillä, kaikkein vähimmin itse huudella." Hän menee. Ja samassa painaa kreivitär Dohna kapean jalkansa pienen, sinitähtisen vuokkokimpun päälle. "Sinä olet nyt tehnyt niinkuin minä toivoin", sanoo Anna Stjärnhök kreivittärelle kylmästi, "mutta nyt tuli myös loppu ystävyydestämme. Älä luulekaan, että minä voin antaa anteeksi sitä, että olet ollut hänelle julma. Olet ajanut hänet pois, ivannut ja haavoittanut häntä, ja minä, minä tahtoisin seurata häntä vankeuteen, häpeäpenkille, jos niin vaadittaisiin. Minä tahdon vartioida häntä, säilyttää hänet. Sinä olet tehnyt niinkuin minä tahdoin, mutta en anna sinulle koskaan anteeksi!" "Mutta Anna, Anna!" "Kun äsken kerroin sinulle, niin uskotko, että tein sen iloisin mielin! Enkö ole tässä kappale kappaleelta raastanut omaa sydäntäni rinnasta?" "Miksi sitten teit sen?"
  • 61. "Miksi? Siksi, etten halunnut — etten halunnut, että hänestä tulee vihityn vaimon rakastaja…" Kolmastoista luku MAMSELLI MARIE Hiljaa, ihan hiljaa! Pääni ympärillä surisee. Kai se on kimalainen, joka tulla pörisee. Ei, hiljaa nyt! Ah, millaista tuoksua! Niin totta kuin olen tässä, eikö se ole koimarunan ja lavendelin ja tuomen ja sireenin ja valkonarsissien tuoksua. Ihanaa on tuntea sellaista harmaana syysiltana, keskellä kaupunkia. Kun vain etsinkin ajatuksiini tuon pienen, siunatun maakaistaleen, heti alkaa ympärilläni surista ja lennellä, ja siirryn aivan huomaamattani pieneen, nelisnurkkaiseen ruususarkaan, joka on täynnä kukkia, ligusterpensaisen aidan takana. Nurkissa on sireenimajat ja niissä kaidat lautapenkit, ja kukkalavain ympärillä, jotka on järjestetty sydämien ja tähtien muotoon, kiertelevät kapeat polut, valkealla merihiekalla ripotetut. Kolmelta puolen ympäröi ruususarkaa metsä. Pihlaja ja tuomi, nuo puolisivistyneet ja kauniskukkaiset, seisovat likinnä ja yhdistävät tuoksunsa sireenien lemuun. Niiden takana kohoaa muutamia koivusikermiä, ja sitten alkaa kuusimetsä, oikea metsä, hiljainen ja tumma ja partainen ja pistävä. Ja neljännellä puolella on pieni, harmaa tupa.
  • 62. Se ruususarka, jota minä nyt ajattelen, oli kuusikymmentä vuotta sitten Svartsjössä Moreuksen vanhalla rouvalla, hänellä, joka elätti itseään tikkaamalla peitteitä talonpojille ja valmistamalla ruokaa heidän pitoihinsa. Rakkaat ystävät! Kaikesta hyvästä, jota teille toivon, mainitsen ensiksi tikkauspuut ja ruususaran. Suuret, huojuvat, vanhanaikaiset tikkauspuut, joissa on somat linkut ja kuluneet rissat, minä toivon teille, sellaiset, joiden ympärillä viisi, kuusi henkeä voi yhtaikaa työskennellä, joiden ääressä ommellaan kilpaa ja koetellaan, kuka saa kauniimmat pisteet nurealle puolelle; joiden ääressä syödään omenapaistikkaita ja rupatellaan ja "matkustetaan Grönlantiin" ja "kätketään sormusta", ja nauretaan niin, että oravat metsässä nakkelevat kuperkeikkaa pelästyksestä. Tikkauspuut talveksi, rakkaat ystävät, ja ruususarka kesäksi! Ei puutarhaa, johon uppoaa rahaa enemmän kuin huvi kannattaa, ei, vaan ruususarka, kuten ennen maailmassa sanottiin. Sellainen pitää teillä olla, sellainen jota voitte hoidella omin käsin. Pienoisten orjanruusupensaiden tulee siellä rehottaa pienten maakumpareiden huipulla, ja lemmikkirivin kierrellä niiden juurella; suuri, lehahtava unikko, joka kylvää itse itsensä, leviää siellä kaikkialle, sekä ruohoreunustalle että hiekkakäytävälle, ja siellä pitää olla ruskeaksi kulottunut turvesohva, jossa kasvaa akilleioja ja keisarinkruunuja, sekä istuimella että selkänojalla. Vanhalla Moreuksen rouvalla oli ennen aikaan paljon hyvää. Hänellä oli kolme iloista ja ahkeraa tytärtä sekä pieni tupa tienposkessa. Hänellä oli kirstunpohjalla säästöjä, hänellä oli jäykkiä silkkisaaleja, suoraselkäisiä nojatuoleja ja tietoja monenlaisista asioista, mitkä ovat tarpeellisia tietää sellaisen, jonka itse täytyy hankkia leipänsä.
  • 63. Mutta parhainta olivat hänen tikkauspuunsa, jotka tuottivat hänelle työtä läpi vuoden, ja ruususarka, joka antoi hänelle iloa koko kesän ajan. Ja nyt on kerrottava, että Moreuksen rouvan pienessä tuvassa eleli vuokralainen, pieni kuiva mamselli, nelikymmenvuotias, joka asui ullakkokamarissa. Mamselli Mariella, joksi häntä aina sanottiin, oli omat käsityksensä monista asioista, kuten usein on sellaisella ihmisellä, joka oleksii paljon yksinään ja antaa ajatuksensa pyöriskellä havaitsemissaan asioissa. Mamselli Marie uskoi, että rakkaus on kaiken pahan alku tässä matoisessa maailmassa. Joka ilta hän ennen nukkumistaan pani kätensä ristiin ja luki iltarukouksensa. Luettuaan "Isä meidän" ja "Herra siunatkoon meitä", hän päätti aina rukouksensa pyytämällä Jumalaa varjelemaan häntä rakkaudesta. "Siitä vasta viheliäisyyttä koituisi", hän sanoi. "Minä olen vanha ja ruma ja köyhä. Ei, kunpa vain säästyisin rakastumasta!" Hän istui päivät päästään Moreuksen rouvan pienessä yliskamarissa ja koukkusi ikkunaverhoja ja suomusvirkkauksia. Ne hän sitten myi emännille ja herrasväelle. Hän koukkusi sillä tavoin itselleen tupaa. Sillä pieni tupa, töyrylle vastapäätä Svartsjön kirkkoa, hänen piti saada, tupa, joka olisi niin korkealla paikalla, että sieltä voi nähdä mukavasti kauas; se oli hänen unelmansa. Mutta rakkaudesta hän ei tahtonut kuulla puhuttavan.
  • 64. Kun hän kesäiltoina kuuli viulun soivan tienhaarassa, missä peluri istui veräjälaudalla ja nuori väki hölkkäsi polkkaa niin että tanner pölisi, silloin hän kaarsi pitkät matkat metsän kautta päästäkseen kuulemasta ja näkemästä moista. Toisena joulupäivänä, kun maalaismorsiamia tuli viisin ja kuusin Moreuksen rouvan ja hänen tyttäriensä luo puetuttamaan itseään; jolloin heidät koristettiin myrttiseppeleillä ja korkeilla silkkisillä ja lasihelmisillä kruunuilla ja koreilla silkkivöillä, pantiin rintaan kotitekoiset ruusunkimput ja hame reunustettiin taftikankaisilla kiehkuroilla, silloin hän pysyi itsepintaisesti huoneessaan päästäkseen näkemästä, miten toisia hepenöitiin rakkauden kunniaksi. Kun Moreuksen tytöt istuivat talvi-iltoina tikkauspuiden ääressä ja suuri, porstuan vasemmalla puolella oleva huone säteili kodikkuutta, kun lasiomenat heiluivat ja hikoilivat uunin luona tulen loimuun ripustettuina, kun kaunis Gösta Berling tai kiltti Ferdinand, jotka olivat tulleet vieraisille, aina kepposiin valmiina nykäsivät tytöiltä rihman neulansilmästä tahi narrasivat heidät ompelemaan vääriä pistoksia; ja kun huone raikui iloa ja remua ja kuhertelua ja kädet puristelivat toisiaan tikkauspuiden alla, silloin kääri mamselli Marie ärtyneenä neuleensa kokoon ja meni tiehensä, sillä hän vihasi rakkautta ja rakkauden teitä. Mutta rakkauden ilkiteot hän tunsi, ja niistä hän tiesi kertoella. Hän ihmetteli, että rakkaus vielä tohti näyttäytyä maan päällä, ettei sitä karkottanut täältä hyljättyjen valitus ja niiden kiroukset, jotka se oli tehnyt rikollisiksi, eikä niiden vaikerrukset, jotka se oli kytkenyt vihattaviin kahleihin. Hän ihmetteli, miten sen siivet saattoivat
  • 65. kantaa niin vapaasti ja keveästi, miten se ei tuskan ja häpeän painamana jo uponnut nimettömiin syvyyksiin. Ei, nuori hän oli ollut kuten kaikki muutkin, mutta rakkautta hän ei ollut koskaan maistanut. Koskaan hän ei ollut antanut houkutella itseään tanssiin ja hyväilyihin. Hänen äitinsä kitara riippui pölyisenä ja kielettömänä ullakolla. Koskaan hän ei ollut näpännyt sitä vienoon lemmenvirteen. Hänen äitinsä ruusupuut kasvoivat hänen ikkunallaan. Hän antoi niille nipin napin vettä. Hän ei rakastanut kukkia, noita lemmen lapsia. Niiden lehdet riippuivat tomuisina. Hämähäkit keikkuivat oksien välissä, ja nuput eivät koskaan puhjenneet. Ja Moreuksen rouvan ruususaralle, jossa perhot liehuivat ja linnut lauloivat, jossa tuoksuvat kukkaset lähettivät lemmenviestejä lentäville mehiläisille, jossa kaikki puhui tuosta vihattavasta, sinne hän harvoin pisti jalkansa. Tulipa sitten aika, jolloin Svartsjön kunta panetti urut kirkkoonsa. Se oli sen vuoden edellisenä kesänä, jolloin valta oli kavaljeerien käsissä. Paikkakunnalle tuli nuori urkujenrakentaja. Ja hänkin tuli rouva Moreukselle asumaan, ja hänet sijoitettiin toiseen pieneen ullakkokamariin. Ja sitten hän asetti paikoilleen nuo urut, joilla on niin ihmeelliset äänet, joiden hirmuinen pasuuna tuon tuostakin vongahtaa keskellä rauhallista virttä — kuka ties miksi ja miten — ja pelästyttää lapset joulukirkossa itkemään. Oliko nuori urkujenrakentaja alallaan mestari, sitä epäiltäköön kernaasti. Mutta iloinen velikulta hän oli ainainen päivänpaiste
  • 66. silmissään. Hän puheli aina ystävällisesti kaikille, rikkaalle ja köyhälle, vanhalle ja nuorelle. Hänestä tuli pian talonväkensä hyvä ystävä, ah, enemmän kuin ystävä. Kun hän iltaisin tuli kotiin työstä, hän piteli Moreuksen rouvan lankavyyhteä ja aherteli nuorten tyttöjen apuna ruususaralla. Hän lausuili "Axelia" ja lauloi "Frithiofia". Hän poimi maasta mamselli Marien lankakerän, pudottipa tämä sen miten usein tahansa, ja korjasi vielä hänen pöytäkellonsakin käymään. Hän ei hellittänyt yksissäkään tanssiaisissa ennen kuin oli tanssittanut kaikki naiset, vanhimmasta rouvasta nuorimpaan tyttöseen, ja jos vastoinkäyminen häntä kohtasi, hän istahti heti ensiksi näkemänsä naisen viereen, olipa tämä kuka tahansa, ja teki hänestä uskottunsa. Niin, hän oli sellainen mies, joita naiset luovat unelmissaan! Älköön hänestä sanottako, että hän puhui kenenkään kanssa rakkaudesta. Mutta kun hän oli vain pari viikkoa asunut Moreuksen rouvan ullakkokamarissa, olivat kaikki tytöt rakastuneet häneen, ja mamselli Marie parka tiesi, hänkin, rukoilleensa turhaan. Ne olivat surun päiviä ja riemun päiviä. Kyynelet tippuivat tikattavalle kankaalle ja huuhtoivat liituviivat pois. Iltaisin istui tavallisesti joku kalpea uneksijatar sireenimajassa, ja mamselli Marien pienessä ullakkokamarissa näppäiltiin äskenviritettyä kitaraa vienoihin lemmen virsiin, joita hän oli oppinut äidiltään. Nuori urkujenrakentaja heippaili talossa yhtä suruttomana ja iloisena kuin ennenkin ja siroitteli hymyjä ja palveluksia noille riutuneille naisille, jotka kiistelivät hänestä kun hän oli poissa kotoa työssään. Ja viimein tuli päivä, jolloin hänen oli matkustettava pois.
  • 67. Kyytihevonen seisoi kuistin edessä. Matkalaukku oli köytetty kärryjen takalautaan, ja nuori mies teki jäähyväiset. Hän suuteli rouva Moreuksen kättä ja sulki itkevät tytöt syliinsä ja suuteli heitä poskelle. Hän itsekin itki sitä, että hänen oli pakko lähteä, sillä hänen kesänsä oli ollut päivänpaistetta siinä pienessä, harmaassa tuvassa. Viimein hän alkoi katsella, missä mamselli Marie oli. Silloin mamselli tulikin alas vinnin kapeita portaita, parhaassa asussaan. Kitara riippui hänen kaulassaan leveässä, viheriässä silkkinauhassa, ja kädessä hänellä oli ruusunippu, sillä tänä vuonna olivat hänen äitinsä ruusut kukkineet. Hän pysähtyi nuoren miehen eteen, näppäsi kitaraansa ja lauloi: "Sa lähdet pois. Tervetuloa taas! Ole, rakkahin, murheita vailla! Äl' unhoita armasta tuttavaas, joka huokaa Vermlannin mailla!" Sitten hän pisti kukat hänen napinläpeensä ja suuteli häntä suoraan suulle. Ja niin: sitten hän katosi taas ullakolle, tuo vanha ilmestys. Rakkaus oli kostanut hänelle ja tehnyt hänestä yleisen naurun kohteen. Mutta hän ei moittinut enää koskaan rakkautta. Hän ei heittänyt enää koskaan kitaraa joutilaaksi eikä unohtanut koskaan vaalia äitinsä ruusupuita. * * * * * Aika vieri. Ekebyn majurinrouva karkotettiin talostaan, kavaljeerit pääsivät valtaan, ja tapahtui sitten, niinkuin taannoin on tarinoitu, että Gösta Berling eräänä sunnuntai-iltana luki nuorelle Borgin
  • 68. kreivittärelle runon, jonka jälkeen kreivitär kielsi häntä näyttäytymästä kodissaan. Kerrotaan, että kun Gösta sinä iltana talosta lähtiessään sulki eteisen oven, niin hän näki pari kolme rekeä tulevan Borgin pihaan. Hän katsahti pientä naista, joka istui etumaisessa reessä. Jos hän jo ennestäänkin oli synkkä, niin vielä synkemmäksi hän tämän nähdessään tuli. Hän kiiruhti pois, ettei häntä tunnettaisi, mutta onnettomuuden aavistus täytti hänen mielensä. Olivatko juuri nuo äskeiset puheet mananneet tänne tämän naisen? Ei onnettomuus mene ilman toista onnettomuutta. Mutta palvelijat kiiruhtivat ulos, rekipeitot päästettiin, vällyt leväytettiin auki. Ken oli tuo tulija? Kuka oli tuo pieni nainen, joka nyt nousi seisomaan reessä? Ah, se on todellakin itse Märta Dohna, tuo kuuluisa kreivitär! Hän oli naisista hupaisin ja huimamielisin. Maailman ilo oli nostanut hänet valtaistuimelleen ja kruunannut hänet kuningattarekseen. Leikit ja sulohymyt olivat hänen alamaisiaan. Soitto ja tanssi ja seikkailu olivat sattuneet hänen osakseen silloin, kun elämän arpaa heitettiin. Hän oli nyt jo melkein viisissäkymmenissä, mutta hän oli niitä viisaita, jotka eivät laske vuosien lukua. "Se, jonka jalka ei nouse tanssiin tai suu sula hymyyn", hän sanoi, "on vanha. Se tuntee vuosien kamalan painon, mutta en minä." Ilolla ei suinkaan ollut vakaata valtaistuinta hänen nuoruutensa päivinä, mutta vaihtelu ja epävarmuus lisäsivät vain elämän suloisuutta. Ilon perhossiipinen majesteetti piti yhtenä päivänä kahvikekkerit hovinaisten saleissa Tukholman linnassa ja tanssi
  • 69. huomispäivänä hännystakissa ja pahkasauva kourassa Pariisissa. Se käväisi Napoleonin kenttäleirissä, se matkasi Nelsonin laivastossa sinisellä Välimerellä, se käväisi Wienin kongressissa, se uskalsi Brysseliin tanssiaisiin erään kuuluisan taistelun edellisenä yönä. Ja missä ikinä ilo oleksi, siellä oli Märta Dohna, hänen valiokuningattarensa. Soitellen, tanssien, ilveillen samosi kreivitär Märta ympäri maailmaa. Mitä ei hän olisi nähnyt, mitä elänyt? Hän oli tanssinut kumoon valtaistuimia, pelannut écartéta[10] ruhtinaskunnista, sytytellyt pilahuulin hävittäviä sotia! Hilpeyttä ja hullutusta oli hänen elämänsä ollut ja oli edelleen oleva. Ei ollut hänen ruumiinsa liian vanha tanssimaan, ei hänen sydämensä liian vanha lempimään. Milloin hän väsyisi naamiaisiin ja huvinäytelmiin, hupaisiin tarinoihin ja kaihoisiin lauluihin? Kun ilo joskus jäi kodittomaksi maailmassa, joka oli muuttunut sotatantereeksi, se vetäytyi pitemmäksi tai lyhemmäksi aikaa vanhaan kreivinhoviin Lövenin pitkän järven rannalle. Samoin matkasi kreivitärkin sinne silloin, kun ruhtinaat ja hovit kävivät hänestä pyhän allianssin aikana liian synkiksi. Tällaisella käynnillä hän oli nähnyt hyväksi ottaa Gösta Berlingin kotiopettajaksi pojalleen. Kreivitär viihtyi kyllä täällä pohjoisessa. Missään ei ilolla ollut ihanampaa valtakuntaa. Siellä oli laulua ja soittoa, seikkailunhaluisia miehiä ja kauniita, iloisia naisia. Siellä siltä ei puuttunut pitoja ja tanssiaisia, ei venematkoja kuutamoisilla järvillä, ei rekiretkiä halki tummain metsäin, ei myöskään sydäntä järisyttäviä tapahtumia ja rakkauden tuskaa ja vaivaa. Mutta tyttärensä kuoltua oli kreivitär lakannut käymästä Borgissa. Hän ei ollut nähnyt sitä viiteen vuoteen. Nyt hän tuli katsomaan, jaksoiko hänen miniänsä elää kuusikkojen, karhujen ja lumikinosten
  • 70. keskellä. Hänestä oli hänen velvollisuutensa mennä katsomaan, eikö tuhma Henrik ollut jo kiduttanut kuivuudellaan nuorta kreivitärtä kuoliaaksi. Nyt hän tahtoi tulla kotirauhan laupiaaksi enkeliksi. Päivänpaiste ja onni oli tuotu mukaan ladottuina hänen neljäänkymmeneen nahkaiseen matkalaukkuunsa, hupi oli hänen kamarineitsyensä, pila hänen kuskinsa, leikki hänen seuranaisensa. Ja kun hän juoksi ylös portaita, otettiin hänet avosylin vastaan. Hänen entinen huoneensa alakerrassa odotti häntä. Hänen palvelijansa, seuranaisensa ja kamarineitsyensä, hänen neljäkymmentä nahkaista matkalaukkuaan, hänen kolmekymmentä hatturasiaansa, hänen toalettivehkeensä, monet saalinsa ja turkkinsa, kaikki ne saatiin vähitellen huoneeseen. Siitäkös riitti touhua ja hälinää! Ovet paukkuivat ja portaissa juostiin. Kyllä näki, että kreivitär Märta oli tullut. * * * * * Oli kerran keväinen ilta, oikein kaunis ilta, vaikkei vielä ollut kuin huhtikuu parhaillaan, eikä jää ollut vielä lähtenyt. Mamselli Marie oli avannut ikkunansa. Hän istui huoneessaan, näppäili kitaraansa ja lauloi. Hän oli niin kiintynyt kitaraansa ja muistoihinsa, ettei huomannut, että vaunut vierivät tiellä ja pysähtyivät tuvan eteen. Vaunuissa istui kreivitär Märta, ja hänestä oli aika hauskaa nähdä, kuinka mamselli Marie istui ikkunassaan, kitaranauha kaulassa ja silmät käännettyinä taivasta kohti, ja lauloi vanhoja, kuluneita rakkauslauluja. Viimein laskeusi kreivitär vaunuista ja meni tupaan, jossa nuo kiltit tytöt istuivat peitettä tikkaamassa. Hän ei ollut koskaan ollut kopea:
  • 71. vallankumouksen tuuli oli puhaltanut häneen ja täyttänyt hänen keuhkonsa raikkaalla ilmalla. Hän ei voinut sille mitään, että oli kreivitär, oli hänen tapanaan sanoa; mutta joka tapauksessa hän aikoi elää sellaista elämää, joka häntä miellytti. Hänellä oli yhtä hauska talonpoikaishäissä kuin hovitanssiaisissa. Hän näytteli hovinäytelmiä piioilleen, kun ei muita katselijoita ollut saapuvilla, ja toi tullessaan riemua seuraan, mihin kulloinkin ilmestyi pienine somine kasvoineen ja kuohuvine elämäntunteineen. Hän tilasi peitteitä Moreuksen rouvalta ja kehui tyttäriä. Hän katseli ruususarkaa ja kertoi matkaseikkailujaan. Hänellä oli aina seikkailuja, tällä kreivittärellä. Ja viimein hän tohti nousta ullakon portaille, jotka olivat pelottavan jyrkät ja kaidat, ja meni mamselli Marien luo hänen päätykamariinsa. Siellä hän väläytteli mustia silmiään tuon yksinäisen pikku olennon edessä ja antoi sulosointuisen äänensä hyväillä tämän korvia. Hän osti Marielta uutimia. Hän ei voinut elää Borgissa, jollei hänen kaikissa ikkunoissaan ollut suomussilmäisiä verhoja ja joka pöydällä mamselli Marien virkkaamaa liinaa. Hän lainasi sitten hänen kitaraansa ja lauloi hänelle riemusta ja rakkaudesta. Ja hän kertoi hänelle juttuja, ja mamselli Marie huomasi ennen pitkää liitävänsä keskellä hauskaa, humuavaa maailmaa. Ja kreivittären nauru oli sellaista musiikkia, että kohmettuneet lintuset ruususaralla alkoivat sen kuullessaan laulaa, ja hänen kasvonsa, jotka tuskin enää olivat kauniit — sillä ihomaali oli turmellut hipiän, ja suupielissä oli aistillisuuden piirteitä — näyttivät mamselli Mariesta niin kauniilta, että hän ihmetteli, kuinka pikku peili
  • 72. hennoo ne jälleen kadottaa, saatuaan ne kerran kiiltävälle pinnalleen vangituiksi. Lähtiessään hän suuteli mamselli Marieta ja pyysi tätä käymään Borgissa. Mamselli Marien sydän oli autio kuin pikku pääskysten pesä joulunaikaan. Hän oli vapaa, mutta hän halusi kahleita kuin vanhuuden päivillä vapaaksi päästetty orja. Nyt koittivat taaskin riemun päivät ja surun päivät mamselli Marielle; mutta ei pitkät, ainoastaan kahdeksan lyhyttä päivää. Kreivitär nouti hänet vähän väliä Borgiin. Hän näytteli hänelle huvinäytelmiään ja kertoi kosijoistaan, ja mamselli Marie nauroi niin, ettei siten ollut ikänään nauranut. Heistä tuli iki-hyvät ystävät. Kreivitär sai pian tietää kaikki nuoresta urkujenrakentajasta ja jäähyväisistä. Ja hämärissä hän antoi mamselli Marien istua sinisen pikku kabinetin ikkunakomerossa. Ja hän pujotti kitarannauhan hänen kaulaansa ja sai hänet laulamaan lemmenlauluja. Sitten istui kreivitär katsellen, miten ikäneidon kuiva, laiha vartalo ja pieni, ruma pää kuvastuivat punaista iltavalaistusta vasten, ja hän sanoi, että mamselliraukka muistuttaa riutuvaa linnanneitoa. Mutta jokainen laulu tarinoi hellistä paimenista ja julmista paimentytöistä, ja mamselli Marien ääni oli kovin ohut ja kovin kimeä, ja voi hyvin ymmärtää, että kreivitär iloitsi sellaisesta ilveilystä. Ja sitten hommattiin Borgiin kemut, kuten luonnollista, koska kerran kreivin äiti oli tullut kotiin. Ja oli hauskaa kuten tavallisesti. Vierasjoukko ei ollut kuitenkaan suuri. Sinne oli kutsuttu ainoastaan oman pitäjän väkeä.
  • 73. Ruokasali oli alakerrassa, ja illallisen jälkeen sattui, etteivät vieraat nousseet yläkertaan, vaan jäivät alas kreivitär Märtan huoneisiin, jotka olivat ruokasalin takana. Ja kreivitär sai käsiinsä mamselli Marien kitaran ja alkoi laulaa vieraille. Hän oli hupainen nainen, tuo kreivitär, ja osasi matkia ketä tahansa. Nyt hänen päähänsä pälkähti matkia mamselli Marieta. Hän kohotti silmänsä taivasta kohti ja alkoi ohuella, kimakalla lapsenäänellä laulaa. "Älkäähän, kreivitär!" rukoili Marie. Mutta kreivittärellä oli hauskaa, ja vieraat eivät voineet olla nauramatta, niin surkeata kuin se olikin mamselli Marien kannalta. Kreivitär otti käsityölippaasta kourallisen kuihtuneita ruusunlehtiä, astui traagillisin elein mamselli Marien luo ja lauloi syvästi liikuttuneella äänellä: "Sa lähdet pois. Tervetuloa taas! Ole, rakkahin, murheita vailla! Äl' unhoita armasta tuttavaas, joka huokaa Vermlannin mailla!" Sitten hän ripotteli ruusunlehdet hänen päähänsä. Ihmiset nauroivat; mutta mamselli Marie raivostui. Näytti kuin hän olisi tahtonut repiä kreivittäreltä silmät päästä. "Sinä olet huono nainen, Märta Dohna", hän sanoi. "Kenenkään kunniallisen naisen ei sopisi seurustella sinun kanssasi." Kreivitär Märta suuttui nyt hänkin. "Ulos, mamselli!" hän sanoi. "Olen kyllästynyt hupsutuksiisi."
  • 74. "Kyllä minä menenkin", sanoi mamselli Marie, "mutta ensin minun pitää saada maksu liinoista ja uutimista, jotka olet tänne ripustellut." "Vanhoista rääsyistä!" huusi kreivitär. "Tahtooko hän maksua sellaisista rääsyistä? Ota ja vie ne! En tahdo nähdä niitä enää silmissäni! Ota heti ja vie!" Sitten nakkaa kreivitär hänelle liinat ja repii alas uutimet, sillä nyt hän on raivon vallassa. Seuraavana päivänä pyysi nuori kreivitär anoppiaan sopimaan mamselli Marien kanssa; mutta kreivitär ei tahtonut. Hän oli kyllästynyt mamselliin. Elisabet kreivitär lähti silloin itse ja osti mamselli Marielta koko uudinvaraston ja koristi niillä kaikki yläkerran ikkunat. Niin mamselli Marie tyytyi ja sai hyvityksen. Kreivitär Märta laski sitten monta kertaa leikkiä miniänsä mieltymyksestä suomusneuleihin. Hän osasi myös kätkeä vihansa — säilyttää sitä tuoreena ja uutena vuosikausia. Hän oli varsin lahjakas nainen. JÄLKIMMÄINEN OSA
  • 75. Ensimmäinen luku KRISTOFFER-SERKKU Heillä oli vanha petolintu siellä kavaljeerien rakennuksessa. Hän istui aina uuninnurkassa ja vaali takkavalkeaa, ettei se päässyt sammumaan. Pörröinen ja harmaa hän oli. Pieni pää, jossa oli iso nokka ja sammuvat silmät, nuokkui surullisesti pitkän, laihan kaulan päässä, joka pisti esiin tuuheasta turkinkauluksesta. Sillä petolintumme kulki turkki yllään sekä kesällä että talvella. Muinoin hän oli kuulunut siihen parveen, joka samosi suuren keisarin seurassa saalista ajaen yli Euroopan; mutta hänen nimeään ja arvoaan ei kukaan nykyjään uskalla käydä arvailemaan. Vermlannissa tiedettiin vain, että hän oli ollut noissa suurissa sodissa, että hän oli mahtavasti riehunut jylisevissä taisteluissa ja että hänen vuoden 1815 jälkeen täytyi suunnata siipiensä lento pois kiittämättömästä isänmaastaan. Hän sai suojaa Ruotsin kruununprinssin hovissa ja tämä neuvoi häntä kaukaiseen Vermlantiin. Sellainen oli aika, että hän, jonka nimi muinoin oli pannut maailmat vapisemaan, sai nyt olla iloinen, kun ei kukaan tuntenut enää hänen nimeään, tuota aikoinaan niin pelättyä. Hän oli kunniasanalla luvannut kruununprinssille, ettei lähtisi Vermlannista eikä mainitsisi tarpeettomasti kuka oli. Ja niin hänet lähetettiin Ekebyhyn, kädessään kruununprinssin omakätinen kirjelmä majurille, jossa suositeltiin häntä mitä lämpimimmin. Silloin aukaisi kavaljeerirakennus hänelle ovensa. Aluksi arvailtiin innokkaasti, kuka oli tuo kuuluisuus, joka kätkeytyi uuden, tekaistun nimen taakse. Mutta vähitellen hän muuttui
  • 76. kavaljeeriksi ja vermlantilaiseksi. Kaikki sanoivat häntä Kristoffer- serkuksi, tietämättä oikein kuinka hän oli saanut juuri tämän nimen. Mutta ei ole petolinnun hyvä elää häkissä. Ymmärtää, että se on tottunut muuhun kuin hyppäämään pienalta pienalle ja ottamaan ruokansa hoitajan kädestä. Alituinen kuolemanvaara on muinoin sytyttänyt hänen valtimonsa tuleen. Häntä iljettää tämä untelo rauha. On kyllä totta, etteivät nuo toisetkaan kavaljeerit olleet juuri kesyjä lintuja; mutta kenenkään veri ei ollut kiehunut niin kuumana kuin Kristoffer-serkun. Vain karhunjahti saattoi elähyttää hänen lamaantunutta elinintoaan, karhunjahti tahi nainen, yksi ainoa nainen. Hän oli vironnut henkiin kymmenen vuotta sitten nähtyään ensi kerran Märta-kreivittären, joka silloin jo oli leski. Nainen, vaihtelevainen kuin sotaonni, kiihoittava kuin vaara, räiskyvä, ylimielinen olento — sotaurho rakasti häntä. Ja nyt hän istui siellä ja vanheni ja harmeni voimatta pyytää häntä vaimokseen. Hän ei ollut nähnyt häntä viiteen vuoteen. Hän kuihtui ja riutui vitkalleen, niin kuin vangitut kotkat riutuvat. Vuosi vuodelta hän kävi yhä kuivemmaksi ja viluisemmaksi. Hänen täytyi piiloutua paremmin turkkiinsa ja vääntäytyä lähemmäksi takkaa. * * * * * Niin hän istuu siellä, viluisena, pörröisenä ja harmaana senkin päivän aamuna, jonka iltana pääsiäispaukut ammutaan ja poltetaan pääsiäisakka. Kavaljeerit ovat kaikki kylillä, mutta hän istuu kotona uuninnurkassa.
  • 77. Oi, Kristoffer-serkku, Kristoffer-serkku, etkö sinä sitä tiedä? Hymyillen on tullut viettelevä kevät. Hereille kapsahtaa luonto untelosta unestaan, ja sini-ilmoissa hulmuavat perhossiipiset henget huimassa leikissä. Lukemattomina kuin villipensaan ruusut kimmeltävät heidän muotonsa ylhäältä hattaroiden lomista. Maa, suuri emo, alkaa elää. Huimana kuin lapsi hän nousee kevätvirran kylvystä, kevätsateiden vihman alta. Kivet ja multa kimaltavat halusta. "Ylös, elon kiertokulkuun!" riemuitsee pieninkin hiukkanen. "Me matkaamme kuin siivet kirkkaassa ilmassa. Me helotamme nuorten tyttöjen punehtuvilla poskilla." Kevään hupaisat henget uivat ilman ja veden mukana ruumiiseen, hyppivät kuin ankeriaat veressä, panevat sydämen ailahtamaan. Samaa ääntä on kaikkialla. Sydämiin ja kukkiin, kaikkeen, joka häilyy ja väräjää, tarttuvat nuo perhossiipiset ja soittavat yhä kuin tuhansin myrskynkelloin: "Intoa ja iloa, huvia ja iloa! Tullut on hän, hymyilevä kevät!" Mutta Kristoffer-serkku istuu sopessaan eikä ymmärrä mitään. Hän nojaa päänsä jäykistyneihin sormiinsa ja uneksii kuulatuiskuista ja taistotanterella kasvaneesta kunniasta. Sisäisen silmänsä eteen hän loihtii laakereita ja ruusuja, jotka eivät kukoistaakseen kaipaa kevään vienoa ihanuutta. Sääli on kumminkin häntä, tuota yksinäistä, vanhaa tungeksijaa, joka istuu ylhäällä kavaljeerien rakennuksessa, ilman kansaa, ilman maata; sääli häntä, joka ei koskaan kuule kotimaansa kielen sointua,
  • 78. häntä, joka saa nimettömän haudan Bron kirkkomaalla. Voiko hän mitään sille, että on kotka ja syntynyt vainoamaan, tappamaan? Oi, Kristoffer-serkku, olet jo kyllin kauan istunut uneksien kavaljeerirakennuksessa! Nouse ja juo elämän pulppuavaa viiniä uljaiden linnojen saleissa. Tiedä, serkku Kristoffer, että tänä päivänä on majurille tullut kirje, kuninkaallinen kirje, joka on suljettu Svean kuningaskunnan sinetillä. Se on osoitettu majurille, mutta sisältö koskee sinua. Merkillistä nähdä kuinka sinä, vanha petolintu, luet kirjettä. Silmä syttyy loistoon ja pää kohoaa. Näet häkin ovien avautuvan ja avaruuden leviävän kaipaavien siipiesi nousta. * * * * * Kristoffer-serkku kaivaa ja penkoo vaatekirstunsa pohjia. Hän vetää esiin kultakoristeisen univormunsa, jota on säilyttänyt kuin silmäteräänsä, ja pukeutuu siihen. Hän painaa töyhtökorskan hatun päähänsä ja kiitää pian Ekebystä pois, ratsastaen mainiolla valkealla ratsullaan. Tämä on toki toista kuin istua viluisena uuninnurkassa. Nyt näkee hänkin, että kevät on tullut. Hän kohottautuu satulassa ja laskee laukkaa. Turkitettu dolma, husaarijakku hulmuaa. Lakin töyhtö häilyy. Nuortunut on mies kuten maaemo itse. Herännyt on hän pitkästä talvesta. Vanha kulta voi vielä välähdellä. Nuo rohkeat sotilaskasvot ovat kolmikulmaisen lakin alla ylväs näky. Ihmeellistä on hänen ratsastuksensa. Maasta pulppuaa puroja, ja vuokkoja versoo mistä hän ratsastaa. Muuttolinnut kirkuvat ja
  • 79. riemuitsevat vapautetun vangin ympärillä. Koko luonto yhtyy hänen iloonsa. Komeana kuin triumfaattori hän tulee. Itse kevät ratsastaa edeltä väikkyvällä pilvellä. Kevyt ja ilmava on hän, tuo valon henki. Hänellä on käyrätorvi huulillaan, ja hän hypähtelee ilosta, keikkuen ylös alas satulassaan. Ja Kristoffer-serkun ympärillä tepastelee esikunta vanhoja asetovereja hevosineen: onni on varpaillaan satulassa, ja kunnia uljaan juoksijansa selästä, ja rakkaus kiitää tulisella Arabian orhilla. Ihmeellistä on ratsastus; ihmeellinen ratsastaja. Kielitaitoinen lahorastas huutaa hänelle: "Kristoffer-serkku, Kristoffer-serkku. Minne ratsastat? Minne ratsastat?" "Borgiin kosimaan, Borgiin kosimaan", vastaa Kristoffer-serkku. "Älä mene Borgiin, älä mene Borgiin! Poikamiehellä ei surua", huutaa lahorastas perästä. Mutta hän ei kuule varoitusta. Hän karauttaa mäet ylös, mäet alas, kunnes vihdoinkin saapuu perille. Hän hypähtää alas satulasta, ja hänet viedään saliin kreivitärten luo. Kaikki käy hyvin. Märta-kreivitär on hänelle armollinen. Kristoffer- serkku näkee kyllä, ettei kreivitär halua kieltäytyä kantamasta hänen loistavaa nimeään eikä hallitsemasta hänen linnassaan. Soturi puhelee ja lykkää tuonnemmaksi sen hurman hetken, jolloin hän on näyttävä kreivittärelle kuninkaallisen kirjeen. Hän nauttii tästä odotuksesta.
  • 80. Kreivitär pakisee ja hauskuuttaa häntä tuhansin jutuin. Kristoffer- serkku nauraa kaikelle, ihmettelee kaikkea. Mutta koska he istuvat eräässä niistä huoneista, joihin kreivitär Elisabet on ripustanut mamselli Marien uutimia, alkaa kreivitär kertoa myöskin niistä. Ja hän vääntää tapahtuman niin hauskaksi kuin voi. "Nähkääs", hän sanoo lopulta, "niin ilkeä minä olen. Täällä riippuvat nyt nämä uutimet, jotta joka päivä ja joka hetki ajattelisin syntiäni. Se on tavatonta parannuksen tekoa. Hyi näitä kauhistavia suomusneuleita!" Suuri Kristoffer-serkku katsoo häneen palavin silmin. "Minä olen myöskin vanha ja köyhä", hän sanoo, "ja olen kymmenen vuotta istunut takan ääressä kaivaten rakastettuani. Nauraako armollinen kreivitär sillekin?" "Oh, se on toinen asia", huudahtaa kreivitär. "Jumala on ottanut minulta onnen ja isänmaan ja pakottanut minut syömään vierasta leipää", sanoo Kristoffer-serkku vakavasti. "Minä olen saanut oppia kunnioittamaan köyhyyttä, minä." "Oh, tekin", huudahtaa kreivitär kohottaen käsiään. "Miten ihmiset ovat hurskaita. Ah, miten ihmiset ovat tulleet hurskaiksi!" "Niin", sanoo Kristoffer-serkku, "pankaa mieleenne, kreivitär, että jos Jumala antaa minulle vielä kerran rikkautta ja valtaa, niin osaanpa käyttää niitä paremmin kuin jakaa ne jonkun maailmannaisen kanssa, tuollaisen maalatun, sydämettömän marakatin, joka pilkkaa köyhyyttä." "Olettepa vallan oikeassa, Kristoffer-serkku."
  • 81. Ja niin marssii Kristoffer-serkku ulos huoneesta ja ratsastaa takaisin Ekebyhyn; mutta henget eivät seuraa häntä, lahorastas ei huuda hänelle, eikä hän enää voi nähdä hymyilevää kevättä. Ekebyhyn hän tuli juuri kun pääsiäispaukut piti laukaistaman ja pääsiäisakka poltettaman. Pääsiäisakka on suuri olkinukke, jonka riepunaamaan on hiilellä piirretty silmät, nenä ja suu. Ja yllään sillä on ruotuämmän joutovaatteet. Pitkävartinen hiilihanko ja luuta on asetettu sen viereen, ja rasvasarvi riippuu sen kaulassa. Se on aivan valmis Kyöpelin matkalle. Majuri Fuchs lataa pyssynsä ja laukoo sen kerta toisensa jälkeen suoraan ilmaan. Kuiva risurovio sytytetään, noita-akka heitetään tuleen ja palaa iloisesti hulmuten. Kavaljeerit kyllä tekevät kaiken voitavansa hävittääkseen pahuuden voimia vanhalla koetellulla tavallaan. Kristoffer-serkku seisoo ja katsoo tuikeasti roviota. Äkkiä hän tempaa suuren kuninkaallisen kirjeen hihansa käänteestä ja nakkaa sen tuleen. Jumala yksin tietää, mitä hän ajatteli. Kenties hän kuvitteli, että Märta kreivitär itse paloi tuossa roviolla. Kenties hän ajatteli, että koska se nainen sittenkin oli vain rääsyjä ja olkia, niin ei maailmassa enää ollut mitään muutakaan arvokasta. Hän menee takaisin kavaljeerirakennukseen, sytyttää takkavalkean ja kätkee univormunsa. Ja niin hän jälleen asettuu uuninnurkkaan, ja päivä päivältä hän käy yhä pörröisemmäksi ja harmaammaksi. Hän riutuu vitkalleen siinä, kuten vanhat kotkat riutuvat vankeudessa. Hän ei ole enää vanki; mutta hän ei huoli käyttää vapauttaan. Avaruus on hänelle avoinna. Taistelutanteret, kunnia, elämä
  • 82. odottavat häntä. Mutta hänellä ei ole enää voimia levittää siipiään lentoon. Toinen luku ELÄMÄN POLUT Raskaat ovat ne tiet, joita ihmisten on vaellettava maan päällä. Erämaan teitä, järvien teitä, tunturien teitä. Miksi saa niin moni suru käydä häiritsemättä, kunnes se eksyy erämaahan tahi vaipuu järveen tai suistuu tunturilta? Missä ovat pienet kukkasten poimijattaret, missä ovat pienet satuprinsessat, joiden askelilla ruusuja kasvaa, missä ovat ne, joiden pitäisi siroitella kukkasia raskaille teille? Nyt on Gösta Berling, runoilija, päättänyt mennä naimisiin. Hän etsii vielä vain morsianta, joka on kyllin köyhä, kyllin halpa, kyllin hyljeksitty hullun papin vaimoksi. Kauniit ja jalot naiset ovat rakastaneet häntä, mutta älkööt he yrittäkö kilpailla hänen suosiostaan. Hyljätty valitsee hyljättyjen joukosta. Kenet hän valitsee, ketä hän etsii? Ekebyssä käy joskus vastoja kaupalla köyhä tyttö yksinäisestä metsäkylästä, joka on kaukana vuorien keskellä. Tässä kylässä, jossa
  • 83. vallitsee alinomainen köyhyys ja suuri kurjuus, on monta, joilla ei ole täyttä ymmärrystä, ja vastatyttö on yksi niitä. Mutta kaunis hän on. Hänen runsas, musta tukkansa on niin paksuilla palmikoilla, että ne tuskin mahtuvat hänen päähänsä, hänen poskensa ovat hienosti pyöristyneet, nenä suora ja parhaan kokoinen, silmät siniset. Hän on sitä surumielistä, madonnamaista kaunotartyyppiä, jollaista vielä näkee Lövenin pitkän järven rannoilla. No, siinähän se nyt on se Göstan morsian — hassahtavasta vastatytöstä tulee mainio hullun papin vaimo, niin ettei paremmasta apua. Göstan ei tarvitse muuta kuin matkata Karlstadiin ostamaan sormuksia, ja sitten olkoon Lövenin rannalla taas ilon päivä. Naurakoot ihmiset vielä kerran Gösta Berlingille, kun tämä kihlaa vastatytön ja viettää häitä hänen kanssaan! Naurakoot vain! Onko hän ikänään keksinyt hauskempaa kujetta? Eikö hyljätyn pidä polkeman hyljätyn tietä, vihan tietä, surun tietä, onnettomuuden tietä! Mitäpä haittaa jos hän suistuu, jos hän turmeltuu? Onko ketään joka huolii häntä hillitä? Onko ketään joka ojentaa hänelle ohjaavan kätensä tai virkistävän juoman? Missä ovat pienet kukkasten poimijattaret, missä ovat pienet satuprinsessat, missä ovat ne, joiden pitäisi sirotella ruusuja raskaille teille? Ei, ei, nuori, lempeä Borgin kreivitär ei suinkaan häiritse Gösta Berlingiä hänen aikeissaan. Hänenhän on ajateltava mainettaan, ajateltava miehensä vihaa ja anoppinsa vihaa; ei, hän ei yritäkään pidättää Göstaa.
  • 84. Pitkän jumalanpalveluksen aikana Svartsjön kirkossa hän painaa päänsä alas, panee kätensä ristiin ja rukoilee Göstan puolesta. Unettomina öinä hän usein itkee ja pelkää hänen tähtensä, mutta hän ei sirottele kukkia hyljätyn tielle eikä anna pisaraa vettä janoavalle. Hän ei ojenna kättään vetääkseen toista perikadon partaalta. Gösta Berling ei huoli verhota valittuaan silkkiin eikä koruihin. Hän antaa tämän kaupustella vastoja talosta taloon entiseen tapaan, mutta sitten kun hän on kutsunut kaikki seudun mainittavat miehet ja naiset suuriin kemuihin Ekebyhyn, sitten hän julkaisee kihlauksensa. Silloin hän kutsuu hänet keittiöstä saliin sellaisena kuin hän on taivalluksensa jäljiltä, tien pöly ja lika vaatteissaan, ehkä rääsyisenä, ehkä hiukset pörröisinä, silmissä sekava ilme ja yhtä sekava sanatulva huulilla. Ja hän kysyy vierailta, eikö hän nyt ole valinnut sopivaa morsianta, eikö hullun papin pidä ylpeillä niin kauniista morsiamesta, tästä lempeästä madonnan muodosta, näistä sinisistä, haaveellisista silmistä. Hän oli aikonut olla hiiskumatta tästä kenellekään ennen aikojaan, mutta hän ei pystynyt varjelemaan salaisuuttaan, ja niin sai myös nuori kreivitär Dohna sen tietoonsa. Mutta mitä hän voi tehdä estääkseen Göstaa? Kihlauspäivä on tullut, sen myöhä hämärän hetki on käsissä. Kreivitär seisoo ikkunan edessä sinisessä kabinetissa ja katsoo pohjoiseen. Hän on melkein näkevinään Ekebyn, vaikka kyyneleet ja sumu peittävät hänen näköalansa. Yhtä kaikki hän näkee selvään, miten iso kolmikerroksinen rakennus loistaa kolmine valaistuine ikkunariveineen, hän kuvittelee, miten samppanja kaadetaan
  • 85. laseihin, miten maljahuuto raikuu ja hän, Gösta Berling, ilmoittaa kihlauksensa, hänen ja vastatytön liiton. Jos hän nyt olisi lähellä Göstaa ja panisi aivan hiljaa kätensä hänen käsivarrelleen tai vain soisi hänelle ystävällisen katseen, niin eiköpä Gösta kääntyisi huonolta hyljeksittyjen tieltä? Jos kerran kreivittären lausuma sana oli ajanut hänet niin epätoivoiseen tekoon, niin eikö myös hänen sanansa voisi häntä hillitä? Häntä kauhistuttaa rikos, jonka Gösta aikoo tehdä tuota kovaonnista lapsiparkaa kohtaan. Häntä pöyristyttää synti tuota poloista raukkaa kohtaan, joka nyt tulee houkutelluksi rakastamaan Göstaa, ehkäpä vain yhden päivän pilan tähden. Kenties häntä myös nyt kahta enemmän kauhistuttaa rikos, jonka Gösta tekee itseään kohtaan — tuo tyttö tulee kytketyksi kuin painava kahle hänen elämäänsä ja riistää hänen hengeltään korkeuteen pääsyn voimat. Ja kaikkeen oli kreivitär syynä. Hän oli syössyt tuomitsevalla sanalla Göstan huonolle tielle. Hän, joka oli tullut siunaamaan, lientämään, miksi juuri hän oli vääntänyt vielä lisäokaan syntisen orjantappuraiseen kruunuun? No niin, nyt hän tietää, mitä hänen on tehtävä. Hänpä menee ja valjastuttaa mustat hevoset reen eteen ja ajaa hurauttaa Lövenin yli, ryntää Ekebyn hoviin, asettuu Gösta Berlingin eteen ja sanoo hänelle, ettei hän halveksi häntä, ettei hän tiennyt mitä puhui karkottaessaan hänet kotoaan… Ei, hänen on sittenkin mahdoton tehdä niin, hän häpeäisi eikä uskaltaisi virkkaa sanaakaan. Hänhän oli naimisissa ja hänen piti varjella itseään panettelulta ja juoruilta. Mutta kuinka sitten kävisi Gösta Berlingin? Hänen on lähdettävä.
  • 86. Sitten hän ajattelee, että sellainen matka on mahdoton. Tänä vuonna ei enää yksikään hevonen voi päästä Lövenin yli. Jää sulaa, se on jo irtautunut maasta. Se on vapaana, puhkeillut, kamalan näköinen. Vesi porisee ylös ja alas railoista, paikoin se on kokoontunut mustiksi lammikoiksi, toisin paikoin jää on hohtavan valkeaa. Enimmäkseen se on kumminkin harmaata, likaista sulavasta lumesta, ja tiet kuultavat pitkinä, mustina juovina sen pinnalla. Miten hän voi ajatellakaan moista matkaa? Vanha Märta-kreivitär, hänen anoppinsa, ei millään ehdolla sallisi hänen sitä tehdä. Koko illan hänen on istuttava kreivittären vieressä salissa ja kuunneltava vanhoja hovijuttuja, jotka ovat vanhuksen suurin ilo. Mutta yö tulee, ja hänen miehensä on poissa; nyt hän on vapaa. Hevosella hän ei voi mennä, palvelijoita hän ei tohdi pyytää mukaansa, mutta tuska ajaa hänet kotoa ulkosalle. Hän ei muuta voi. Raskaita ovat ne tiet, joita ihmiset maan päällä vaeltavat: erämaan teitä, järvien teitä, tunturien teitä. Mutta tuota öistä tietä yli sulavan jään, mihin minä sitä vertaisin? Eikö se ole juuri se tie, jota pienten kukkainpoimijatarten on käytävä, epävarma, keinuva, liukas tie, niiden polku jotka tahtovat lääkitä iskettyjä haavoja, niiden polku jotka tahtovat hyvittää vääryydet; kevyen jalan, nopean silmän ja uljaan, rakastavan sydämen polku? Puoliyö oli jo ohi, kun kreivitär viimein pääsi Ekebyn rantaan. Hän oli lankeillut jäällä, hän oli hyppinyt railojen yli, hän oli juosten
  • 87. ylittänyt sellaiset paikat, joissa jalanjäljen täytti pulppuava vesi, hän oli liukastunut, hän oli ryöminyt. Se oli ollut raskasta vaellusta; hän oli itkenyt kulkiessaan. Hän oli märkä ja väsynyt, ja pimeys, kolkkous ja autius olivat tuoneet mieleen kamalia ajatuksia. Ekebyn rannassa hänen täytyi kahlata jalansyvyisessä vedessä päästäkseen maalle. Ja tultuaan rannalle hän ei saattanut muuta kuin istahtaa rannan kivelle ja itkeä väsymystään ja avuttomuuttaan. Raskaita teitä vaeltavat ihmisten lapset, ja joskus pienet poimijattaret vaipuivat kukkaskoriensa viereen, juuri saavuttuaan tielle, jolle aikovat kukkia sirotella. Tämä nuori, ylhäinen nainen oli kuin olikin pieni rakastettava sankaritar. Ei hän ollut kulkenut sellaisia teitä ennen kotimaassaan. Ehkäpä hän nyt, istuessaan tämän kauhean, hirvittävän järven rannalla märkänä, uupuneena, onnettomana, ajatteli eteläisen isänmaansa lempeitä, kukkasten reunaamia polkuja. Voi, ei häntä liikuta nyt etelä, ei pohjola. Hän on keskellä elämää. Hän ei itke koti-ikävää. Hän itkee, tuo pikku kukkastenpoimija, tuo pieni sankaritar sitä, että on niin uupunut ettei ehdi sen tielle, jolle tahtoo kukkia sirotella. Hän itkee siksi, että luulee tulleensa liian myöhään. Silloin juoksee väkeä rannalle. He kiiruhtavat hänen ohitseen häntä huomaamatta, mutta hän kuulee heidän sanansa: "Jos pato särkyy, menee paja", sanoo joku. "Ja mylly ja verstaat ja seppien asumukset", lisää toinen.
  • 88. Silloin hän rohkaistuu jälleen, nousee ja seuraa heitä. * * * * * Ekebyn mylly ja paja olivat kaidalla niemellä, jonka ympäri kiertää pauhaava Björksjön-joki. Se tulee viuhuen nientä kohti, ylemmän, valtavan kosken valkeaksi kuohuttamana, ja niemen rakennusten perustaa oli siellä siihen aikaan vedeltä suojaamassa mahtava aallonmurtaja niemen nokassa. Mutta sulku oli jo vanha ja kavaljeerit talon ohjissa. Heidän aikanaan tanssia keikuttiin tehtaan mäillä, kukaan ei huolinut katsoa, kuinka virta ja pakkanen ja aika kuluttivat vanhaa kivipatoa. Sitten tulee kevättulva ja sulku alkaa horjua. Ekebyn putous on kuin valtavat harmaakiviportaat, joita myöten Björksjö-joen laineet hyrskyten tulevat alas. Ne tulevat vauhdista huimiksi, tuupertuvat nurinniskoin ja ryntäävät toisiaan vastaan. Ne hypähtävät ilmaan vihoissaan ja pärskyttävät vaahtoa toistensa yli, kompastuvat taaskin kiveen, tukkiin ja kepsahtavat jälleen pystyyn mennäkseen samassa nurin, ja niin yhä vain vaahdoten, kähisten, karjuen. Ja nyt karkaavat nämä villit, hurjistuneet aallot, kevätsäästä juopuneina ja äsken saadun vapauden huumauksessa, vanhan kivimuurin kimppuun. Ne tulevat, kähisten ja raastaen, kimpoavat korkealle sen harjalle ja vetäytyvät takaisin kuin olisivat loukanneet valkokutriset päänsä. Se on väkirynnäkkö jos mikään, ne tempaavat suuria jäälauttoja suojakatoiksi, ne ottavat hirsiä muurinmurtajiksi, ne yhdistyvät, karkaavat hyökkäykseen, pauhaavat tuota muuriraukkaa vasten, kunnes tuntuu yht'äkkiä siltä kuin joku olisi niille huutanut: pitäkää varanne! Silloin ne rynkäisevät takaisin ja
  • 89. niiden jäljestä tulee iso kivi, joka irtautuu sulusta ja vaipuu kolisten virran syliin. Näyttää kuin se olisi niitä ällistyttänyt, ne ovat hiljaa, ne riemuitsevat, ne neuvottelevat … ja sitten uusi ryntäys! Siellä ne taaskin ovat jäälauttoineen ja hirsineen, nuo vallattomat, armottomat, rajut hävityshalun hullaannuttamat. Jos vain pato olisi poissa tieltä — sanovat aallot — jos vain pato olisi tieltä, niin silloin tulee pajan ja myllyn vuoro. Nyt on vapauden päivä … pois ihmiset ja ihmisten työt! Ne ovat noenneet meidät hiilillään, ne ovat tomunneet meitä jauhoillaan, ne ovat kytkeneet meidät työn ikeeseen kuin härkänsä, ajaneet meitä pyörylässä, sulkeneet meidät kammioihin, estäneet kulkumme patoluukuilla, pakottaneet meidät kiskomaan raskaita pyöriä, kantamaan kömpelöitä tukkeja. Mutta nyt me anastamme vapauden. Vapauden päivä on tullut! Kuulkaa, te Björksjön ulapan aallot, kuulkaa, siskot ja veikot, te rämeitten ja lampien, vuoripurojen ja metsäjokien vedet! Se on tullut, on tullut! Rynnätkää alas Björksjön jokeen, tulkaa vereksin voimin, jyristen, viuhuen, murtamaan vuosisatain sortoa, tulkaa! Hirmuvalan paalutus kaatukoon. Kuolema Ekebylle! Ja ne tulevat — aalto aallon perästä ryntää putoukseen iskeäkseen päänsä sulkumuuriin, antaakseen oman osuutensa suureen työhön. Juopuneina kevään äsken saadusta vapaudesta, lukemattomina, yksimielisinä ne tulevat, ne irroittavat kiven toisensa jälkeen, mättään mättään perästä horjuvasta aallonmurtajasta.
  • 90. Welcome to our website – the perfect destination for book lovers and knowledge seekers. We believe that every book holds a new world, offering opportunities for learning, discovery, and personal growth. That’s why we are dedicated to bringing you a diverse collection of books, ranging from classic literature and specialized publications to self-development guides and children's books. More than just a book-buying platform, we strive to be a bridge connecting you with timeless cultural and intellectual values. With an elegant, user-friendly interface and a smart search system, you can quickly find the books that best suit your interests. Additionally, our special promotions and home delivery services help you save time and fully enjoy the joy of reading. Join us on a journey of knowledge exploration, passion nurturing, and personal growth every day! ebookbell.com