100% found this document useful (4 votes)
31 views

Instant Access to Practical Spring LDAP: Using Enterprise Java-Based LDAP in Spring Data and Spring Framework 6 2nd Edition Balaji Varanasi ebook Full Chapters

Spring

Uploaded by

gabtamaotwe
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (4 votes)
31 views

Instant Access to Practical Spring LDAP: Using Enterprise Java-Based LDAP in Spring Data and Spring Framework 6 2nd Edition Balaji Varanasi ebook Full Chapters

Spring

Uploaded by

gabtamaotwe
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 66

Download Full Version ebookmass - Visit ebookmass.

com

Practical Spring LDAP: Using Enterprise Java-Based


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

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

OR CLICK HERE

DOWLOAD NOW

Discover More Ebook - Explore Now at ebookmass.com


Instant digital products (PDF, ePub, MOBI) ready for you
Download now and discover formats that fit your needs...

Practical Spring LDAP: Using Enterprise Java-Based LDAP in


Spring Data and Spring Framework 6 2nd Edition Varanasi
Balaji
https://ebookmass.com/product/practical-spring-ldap-using-enterprise-
java-based-ldap-in-spring-data-and-spring-framework-6-2nd-edition-
varanasi-balaji/
ebookmass.com

Pro Spring Security: Securing Spring Framework 6 and Boot


3–based Java Applications, Third Edition Massimo Nardone

https://ebookmass.com/product/pro-spring-security-securing-spring-
framework-6-and-boot-3-based-java-applications-third-edition-massimo-
nardone/
ebookmass.com

Beginning Spring Data: Data Access and Persistence for


Spring Framework 6 and Boot 3 Andres Sacco

https://ebookmass.com/product/beginning-spring-data-data-access-and-
persistence-for-spring-framework-6-and-boot-3-andres-sacco/

ebookmass.com

Psychology Applied to Modern Life: Adjustment in the 21st


Century Wayne Weiten

https://ebookmass.com/product/psychology-applied-to-modern-life-
adjustment-in-the-21st-century-wayne-weiten/

ebookmass.com
Partners of the Imagination: The Lives, Art and Struggles
of John Arden and Margaretta D’Arcy Robert Leach

https://ebookmass.com/product/partners-of-the-imagination-the-lives-
art-and-struggles-of-john-arden-and-margaretta-darcy-robert-leach/

ebookmass.com

The Whole Package Marie Harte

https://ebookmass.com/product/the-whole-package-marie-harte/

ebookmass.com

An Introduction to Data-Driven Control Systems Ali Khaki-


Sedigh

https://ebookmass.com/product/an-introduction-to-data-driven-control-
systems-ali-khaki-sedigh/

ebookmass.com

Whispered Darkness (The Curse of Hallows Hill Book 2)


Jessica Sorensen [Sorensen

https://ebookmass.com/product/whispered-darkness-the-curse-of-hallows-
hill-book-2-jessica-sorensen-sorensen/

ebookmass.com

Catalytic Air Pollution Control: Commercial Technology

https://ebookmass.com/product/catalytic-air-pollution-control-
commercial-technology/

ebookmass.com
The Librarian's Monsters: A Monster Reverse Harem
Standalone (Books & Monsters) Eve Newton

https://ebookmass.com/product/the-librarians-monsters-a-monster-
reverse-harem-standalone-books-monsters-eve-newton/

ebookmass.com
Balaji Varanasi and Andres Sacco

Practical Spring LDAP


Using Enterprise Java-Based LDAP in Spring Data
and Spring Framework 6
2nd ed.
Balaji Varanasi
Salt Lake City, UT, USA

Andres Sacco
Buenos Aires, Buenos Aires, Argentina

ISBN 979-8-8688-0001-6 e-ISBN 979-8-8688-0002-3


https://doi.org/10.1007/979-8-8688-0002-3

© Balaji Varanasi and Andres Sacco 2013, 2023

This work is subject to copyright. All rights are solely and exclusively
licensed by the Publisher, whether the whole or part of the material is
concerned, specifically the rights of translation, reprinting, reuse of
illustrations, recitation, broadcasting, reproduction on microfilms or in
any other physical way, and transmission or information storage and
retrieval, electronic adaptation, computer software, or by similar or
dissimilar methodology now known or hereafter developed.

The use of general descriptive names, registered names, trademarks,


service marks, etc. in this publication does not imply, even in the
absence of a specific statement, that such names are exempt from the
relevant protective laws and regulations and therefore free for general
use.

The publisher, the authors, and the editors are safe to assume that the
advice and information in this book are believed to be true and accurate
at the date of publication. Neither the publisher nor the authors or the
editors give a warranty, expressed or implied, with respect to the
material contained herein or for any errors or omissions that may have
been made. The publisher remains neutral with regard to jurisdictional
claims in published maps and institutional affiliations.
This Apress imprint is published by the registered company APress
Media, LLC, part of Springer Nature.
The registered company address is: 1 New York Plaza, New York, NY
10004, U.S.A.
To my grandparents who taught me the importance of learning new
things all the time.
To my wife and children for supporting me while writing this book.
Introduction
Practical Spring LDAP provides complete coverage of Spring LDAP, a
framework designed to take the pain out of LDAP programming. This
book starts by explaining the fundamental concepts of LDAP and
showing the reader how to set up the development environment. It
then dives into Spring LDAP, analyzing the problems it is designed to
solve. After that, the book focuses on the practical aspects of unit
testing and integration testing with LDAP. An in-depth treatment of
LDAP controls and Spring LDAP features, such as Object-Directory
Mapping and LDIF (LDAP Data Interchange Format) parsing, follows
this. Finally, it concludes with discussions on LDAP authentication and
connection pooling.
What the Book Covers
Chapter 1 starts with an overview of directory servers. It then discusses
the basics of LDAP and introduces the four LDAP information models. It
finishes with an introduction to the LDIF format used for representing
LDAP data.
Chapter 2 focuses on the Java Naming and Directory Interface
(JNDI). In this chapter, you look at creating applications that interact
with LDAP using plain JNDI.
Chapter 3 explains Spring LDAP and why it is an important option in
an enterprise developer’s repertoire. In this chapter, you set up the
development environment to create Spring LDAP applications and
other important tools, such as Maven and a test LDAP server. Finally,
you implement a basic but complete Spring LDAP application using
annotations.
Chapter 4 covers the fundamentals of unit and integration testing.
You then look at setting up an embedded LDAP server for unit testing
your application code; alternatively, you will see how to use
Testcontainers to run LDAP using a docker image. You also review
available tools for generating test data. Finally, you use the Mockito
library to mock test LDAP code.
Chapter 5 introduces the basics of JNDI object factories and uses
these factories for creating objects that are more meaningful to the
application. You then examine a complete Data Access Object (DAO)
layer implementation using Spring LDAP and object factories.
Chapter 6 covers LDAP search. This chapter begins with the
underlying ideas of LDAP search. I then introduce various Spring LDAP
filters that make LDAP searching easier. Finally, you look at creating a
custom search filter to address situations where the current set is
insufficient.
Chapter 7 provides an in-depth overview of LDAP controls that can
be used for extending LDAP server functionality. Then it moves on to
sorting and paging LDAP results using sort and page controls.
Chapter 8 deals with Object-Directory Mapping (ODM), a feature in
Spring LDAP. In this chapter, you look at bridging the gap between the
domain model and the directory server. You then re-implement the DAO
using ODM concepts.
Chapter 9 introduces the important ideas of transactions and
transactional integrity before analyzing the transaction abstractions
provided by Spring Framework. Finally, it takes a look at Spring LDAP’s
compensating transaction support.
Chapter 10 starts with implementing authentication, the most
common operation against LDAP. It then deals with parsing LDIF files
using another feature introduced in Spring. I end the chapter by looking
at the connection pooling support provided by Spring LDAP.

Target Audience
Practical Spring LDAP is intended for developers interested in building
Java/JEE applications using LDAP. It also teaches techniques for
creating unit/integration tests for LDAP applications. The book
assumes basic familiarity with Spring Framework; prior exposure to
LDAP is helpful but optional. Developers already familiar with Spring
LDAP will find best practices and examples to help them get the most
out of the framework.

Prerequisites
You should install Java JDK1 21 or higher on your machine, Maven2 3.8.0
or higher, and some IDE. Some options for the IDE could be Eclipse,3
IntelliJ IDEA,4 Visual Studio Code,5 and others, but you can choose
which is the best for you.
To reduce the complexity of installing all LDAP vendors on your
machine, I recommend you install Docker6 and use it to run each LDAP.
The use and installation of Docker are outside the scope of this book,
but there are some tutorials7 or cheatsheet8 with the most common
commands.

Note If you don’t have it installed on your machine, you can check
Appendixes A, B, and C, which have information about installing the
different tools and loading the information on LDAP.
After installing all the tools, you must check if they are correctly
installed before reading the different chapters.
In the case of Java, you need to run the following command:

% java -version
openjdk 21 2023-09-19
OpenJDK Runtime Environment (build 21+35-2513)
OpenJDK 64-Bit Server VM (build 21+35-2513, mixed
mode, sharing)

After that, you need to check if the version of Maven is correct using
this command:

% mvn --version
Apache Maven 3.9.1
Maven home: /usr/share/maven

Last, if you want to check whether Docker runs correctly on your


machine, you can do that using the following command:

% docker --version
Docker version 24.0.2, build cb74dfc

Remember that I mentioned that Docker is optional. It’s only


recommended for reducing the complexity of installing LDAP vendors
on your machine.

Downloading Source Code


The source code for the examples in this book can be downloaded from
www.apress.com. For detailed information about locating this book’s
source code, visit www.apress.com/gp/services/source-
code. The code is organized by chapter and can be built using Maven.

Questions?
If you have any questions or suggestions, contact the author at
sacco.andres@gmail.com.
Any source code or other supplementary material referenced by the
author in this book is available to readers on GitHub
(https://github.com/Apress). For more detailed information, please
visit https://www.apress.com/gp/services/source-code.
Acknowledgments
I would like to thank my family members and friends for their
encouragement and support during the writing of this book:
My wife, Gisela, who was always patient when I spent long hours at
my computer desk working on this book
My little daughter, Francesca, who helped me relax while writing
each chapter
My baby, Allegra, who is the new family member and my inspiration
to write this book
My friends, German Canale and Julian Delley, who always trusted me
to write a book and supported me during tough times
Specially mentioning Manuel Jordan for guiding me in improving
the quality of the book.
My sincere thanks to the beautiful team at Apress for their support
during the publication of this book. Thanks to Shonmirin P.A. for
providing excellent support. Finally, thanks to Mark Powers and Melissa
Duffy for suggesting and allowing me to write a book. Also, I want to
mention the great job that Balaji Varanasi did with the first edition of
this book which gave the base to write the second edition.
Table of Contents
Chapter 1:​Introduction to LDAP
LDAP Overview
Directory vs.​Database
Information Model
Object Classes
Directory Schema
Naming Model
Functional Model
Security Model
LDIF Format
LDAP History
LDAP Vendors
Sample Application
Summary
Chapter 2:​Java Support for LDAP
LDAP Using JNDI
Connect to LDAP
LDAP Operations
Closing Resources
Creating a New Entry
Updating an Entry
Removing an Entry
Searching Entries
Check How the Operations Work
JNDI Drawbacks
Summary
Chapter 3:​Introducing Spring LDAP
Motivation
Documentation and Source Code Spring LDAP
Spring LDAP Packaging
Installing Spring LDAP Using Maven
Spring LDAP Archetypes
Creating Projects Using IntelliJ
Spring LDAP Hello World
Spring ApplicationConte​xt
Spring-Powered Search Client
Spring LdapTemplate Operations
Add Operation
Modify Operation
Deleting Operation
Summary
Chapter 4:​Testing LDAP Code
Concepts About Testing
Unit Testing
Mock Testing
Integration Testing
Libraries to Do Tests
JUnit
Mockito
Testcontainers
Creating the Tests
Mocking the Templates
Testing Using Embedded Server
Moving to Tests with Testcontainers
Summary
Chapter 5:​Advanced Spring LDAP
JNDI Object Factories
Spring and Object Factories
DAO Implementation Using Object Factory
Implementing Finder Methods
Create Method
Update Method
Delete Method
Summary
Chapter 6:​Searching LDAP
LDAP Search Criteria
Base Parameter
Scope Parameter
Filter Parameter
Optional Parameters
LDAP Injection
Spring LDAP Filters
EqualsFilter
LikeFilter
PresentFilter
NotPresentFilter​
Not Filter
GreaterThanOrEqu​alsFilter
LessThanOrEquals​Filter
AndFilter
OrFilter
HardcodedFilter
WhitespaceWildca​rdsFilter
Handling Special Characters
LDAP Query Builder Parameters
Summary
Chapter 7:​Sorting and Paging Results
LDAP Controls
Identifying Supported Controls
JNDI and Controls
Spring LDAP and Controls
Sort Control
Implementing Custom DirContextProces​sor
Paged Search Controls
Summary
Chapter 8:​Object-Directory Mapping
Spring ODM Basics
ODM Metadata
ODM Service Class
Creating Custom Converter
Summary
Chapter 9:​LDAP Transactions
Transaction Basics
Local vs.​Global Transactions
Programmatic vs.​Declarative Transactions
Programmatically​
Declaratively
Spring Transaction Abstraction
Declarative Transactions Using Spring
LDAP Transaction Support
Spring LDAP Transaction Support
Compensating Transactions
Summary
Chapter 10:​Odds and Ends
Authentication Using Spring LDAP
Handling Authentication Exceptions
Parsing LDIF Data
LDAP Connection Pooling
Built-In Connection Pooling
Spring LDAP Connection Pooling
Pool Validation
Summary
Appendix A:​Setting Up Environment Tools
Appendix B:​Recommended and Alternative Tools
Appendix C:​Set Up LDAP Server
Appendix D:​Opening a Project
Appendix E:​Further Reading
Index
About the Authors
Balaji Varanasi
is a software development manager and technology entrepreneur. He
has over 13 years of experience architecting and developing Java/.NET
applications and, more recently, iPhone apps. During this period, he has
worked in the areas of security, web accessibility, search, and
enterprise portals. He has a master’s degree in computer science and
serves as adjunct faculty, teaching programming and information
system courses. When not programming, he enjoys spending time with
his lovely wife in Salt Lake City, Utah.

Andres Sacco
has been working as a developer since
2007 in different languages, including
Java, PHP, Node.js, Scala, and Kotlin. His
background is mostly in Java and the
libraries or frameworks associated with
this language. At most of the companies
he worked for, he researched new
technologies to improve the
performance, stability, and quality of the
applications of each company. In 2017,
he started to find new ways to optimize
the transference of data between
applications to reduce the cost of
infrastructure. He suggested some
actions, some applicable in all of the manual microservices and others
in just a few. All of this work includes creating a series of theoretic-
practical projects (available on Manning.com). Recently, he coauthored
an Apress book titled Beginning Scala 3. He also published a set of
theoretic-practical projects about uncommon ways of testing, such as
architecture tests and chaos engineering.
About the Technical Reviewer
Manuel Jordan
is an autodidactic developer and researcher who enjoys learning new
technologies for his own experiments about creating new integrations
among them.
Manuel won the 2010 Springy Award – Community Champion and
Spring Champion 2013. In his little free time, he reads the Bible and
composes music on his bass and guitar.
You can reach him through his Twitter account, @dr_pompeii.
© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2023
B. Varanasi, A. Sacco, Practical Spring LDAP
https://doi.org/10.1007/979-8-8688-0002-3_1

1. Introduction to LDAP
Balaji Varanasi1 and Andres Sacco2
(1) Salt Lake City, UT, USA
(2) Buenos Aires, Buenos Aires, Argentina

We all deal with directories daily. We use a telephone directory to look up phone numbers. When visiting a
library, we use the library catalog to look up the books we want to read. We use the file system directory
with computers to store our files and documents. Simply put, a directory is a repository of information. The
information is usually organized so that it can be retrieved easily.
Directories on a network are typically accessed using the client/server communication model.
Applications wanting to read or write data to a directory communicate with specialized servers. The
directory server performs a read or write operation on the actual directory. Figure 1-1 shows this
client/server interaction.

Figure 1-1 Directory server and client interaction

The communication between the directory server and client applications is usually accomplished using
standardized protocols. The Lightweight Directory Access Protocol (LDAP) provides a standard protocol for
communicating with a directory. The directory servers that implement the LDAP protocol are usually called
LDAP servers. The LDAP protocol is based on an earlier X.5001 standard but is significantly simpler
(lightweight) and easily extensible. Over the years, the LDAP protocol went through iterations and is
currently at version 3.0.

LDAP Overview
LDAP defines a message protocol used by directory clients and directory servers. LDAP can be better
understood by considering the following four models it is based on:
The Information model determines the structure of information stored in the directory.
The Naming model defines how information is organized and identified in the directory.
The Functional model defines the operations performed on the directory.
The Security model defines how to protect information from unauthorized access.
We will look at each of these models in the following sections.

Directory vs. Database


Beginners often need clarification and picture an LDAP directory as a relational database. Like a database,
an LDAP directory stores information. However, several key characteristics set a directory apart from
relational databases.
LDAP directories typically store data that is relatively static. For example, employee information stored
in LDAP, such as their phone number or name, does not change daily. However, users and applications look
up this information very frequently. Since the data in a directory is accessed more often than updated, LDAP
directories follow the WORM principle2, 3 and are heavily optimized for read performance. Placing data that
change quite often in LDAP does not make sense.
Relational databases employ referential integrity and locking techniques to ensure data consistency. The
type of data stored in LDAP usually does not warrant such strict consistency requirements. Hence, most of
these features need to be present on LDAP servers. Also, transactional semantics to roll back transactions
are not defined under LDAP specification.
Relational databases follow normalization principles to avoid data duplication and redundancy. On the
other hand, LDAP directories are organized in a hierarchical, object-oriented way. This organization violates
some of the normalization principles. Also, there needs to be a concept of table joins in LDAP.
Even though directories lack several of the RDBMS4 features mentioned earlier, many modern LDAP
directories are built on top of relational databases such as DB2,5 MySQL,6 and PostgreSQL.7
At some point, LDAP has similar characteristics to nonrelational databases like Cassandra,8 MongoDB,9
and many others where the performance of the write/read, high availability, and scalability are more
relevant than the consistency.

Information Model
The basic unit of information stored in LDAP is an entry. Entries hold information about real-world objects
such as employees, servers, printers, and organizations. Each entry in an LDAP directory comprises zero or
more attributes. Attributes are key-value pairs that hold information about the object the entry represents.
The key portion of an attribute is also called the attribute type and describes the information that can be
stored in the attribute. The value portion of the attribute contains the actual information. Table 1-1 shows a
portion of an entry representing an employee. The left column in the entry contains the attribute types, and
the right column holds the attribute values.

Table 1-1 Employee LDAP Entry

Employee Entry
objectClass inetOrgPerson

givenName John
surname Smith
mail john@inflix.com
jsmith@inflix.com
mobile +1 801 100 1000

Note Attribute names, by default, are case-insensitive. However, it is recommended to use camel case
format in LDAP operations.

You will notice that the mail attribute has two values. Attributes that are allowed to hold multiple values are
called multivalued attributes. Single-valued attributes, on the other hand, can only hold a single value. The
LDAP specification does not guarantee the order of the values in a multivalued attribute.
Each attribute type is associated with a syntax that dictates the format of the data stored as an attribute
value. For example, the mobile attribute type has a telephoneNumber syntax. This forces the attribute to
hold a string value with a length between 1 and 32.
Additionally, the syntax also defines the attribute value behavior during search operations. For example,
the givenName attribute has the syntax DirectoryString. This syntax enforces that only alphanumeric
characters are allowed as values. Table 1-2 lists some common attributes and their associated syntax
description.
Table 1-2 Common Entry Attributes

Attribute Type Syntax Description


commonName DirectoryString Stores the common name of a person.
company DirectoryString Stores the company’s name.
employeeNumber DirectoryString Stores the employee’s identification number in the organization.
givenName DirectoryString Stores the user’s first name.
jpegPhoto Binary Stores one or more images of the person.
mail IA5 String Stores a person’s SMTP mail address.
mobile TelephoneNumber Stores a person’s mobile number.
postalAddress Postal Address Stores the user’s ZIP or postal code.
postalCode DirectoryString Stores the user’s ZIP or postal code.
st DirectoryString Stores the state or province name.
street DirectoryString Stores the street address.
surname DirectoryString Stores the last name of the person.
telephoneNumber TelephoneNumber Stores the person’s primary telephone number.

uid DirectoryString Stores the user id.


title DirectoryString Stores the name of the position or the company’s function.
wwwhomepage DirectoryString Stores the official web page of the company.
The attributes in Table 1-2 are the most used for the developers and tools. Still, there is a big list of other
attributes depending on whether your vendor or the tool supports it or not; for example, on the official web
page10 of Microsoft, all the attributes are supported for the Active Directory.

Object Classes
In object-oriented languages, such as Java, we create a class and use it as a blueprint for creating objects. The
class defines the attributes/data (and behavior/methods) that these instances can have. Similarly, object
classes in LDAP determine the attributes an LDAP entry can have. These object classes also define which
attributes are mandatory and which are optional. Every LDAP entry has a special attribute aptly named
objectClass that holds the object class it belongs to. Looking at the objectClass value in the employee
entry in Table 1-1, we can conclude that the entry belongs to the inetOrgPerson class. Table 1-3 shows
the required and optional attributes in a standard LDAP person object class. The cn attribute holds the
person’s common name, whereas the sn attribute holds the person’s family name or surname.

Table 1-3 Person Object Class

Required Attributes Optional Attributes


sn description

telephoneNumber

cn userPassword
objectClass seeAlso

As in Java, an object class can extend other object classes. This inheritance will allow the child object
class to inherit parent class attributes. For example, the person object class defines attributes such as
common name and surname. The object class inetOrgPerson extends the person class and thus inherits
all the person’s attributes.
Additionally, inetOrgPerson defines attributes required for a person working in an organization, such
as departmentNumber and employeeNumber. One special object class, namely, top, does not have any
parents. All other object classes are decedents of top and inherit all the attributes declared in it. The top
object class includes the mandatory objectClass attribute. Figure 1-2 shows the object inheritance.
Figure 1-2 LDAP object inheritance
Most LDAP implementations come with standard object classes that can be used out of the box. Table 1-4
lists some of these LDAP object classes and their commonly used attributes.
Table 1-4 Common LDAP Object Classes

Object Class Attributes Description


top objectClass Defines the root object class. All other object classes must
extend this class.
organization o Represents a company or an organization.
The o attribute typically holds the name of the organization.
organizationalUnit ou Represents a department or similar entity inside an
organization.
person sn Represents a person in the directory and requires the sn
cn (surname) and cn (common name) attributes.
telephoneNumber
userPassword

organizationalPerson registeredAddress Subclasses that represent a person in an organization.


postalAddress postalCode
inetOrgPerson uid departmentNumber It provides additional attributes and can be used to represent a
employeeNumber givenName person working in today’s Internet- and intranet-based
manager organization. The uid attribute holds the person’s username or
user id.

On Oracle’s official website,11 you can find the list of LDAP object classes with information about the
Request for Comments (RFC), which added each object class.

Note In this book, you will see many references to RFCs. Request for Comments (RFC) is a series of
technical documents produced by the Internet Engineering Task Force (IETF)12 that specify certain
standards.
Each RFC has a number as part of the name and a series of sections with the specification. An RFC
could become obsolete to many other RFCs because a new specification about certain technology
appears, for example, a new version of LDAP.
On the RFC Editor web page,13 you can find information about RFCs and the publication process of the
new one.

Directory Schema
The LDAP directory schema is a set of rules determining the type of information stored in a directory.
Schemas can be considered packaging units and contain attribute type definitions and object class
definitions. The schema rules are verified before an entry can be stored in LDAP. This schema checking
ensures that the entry has all the required attributes and contains no attributes not part of the schema.
Figure 1-3 represents a generic LDAP schema.
Figure 1-3 LDAP generic schema
Like databases, directory schemas must be well designed to address issues like data redundancy. Before
implementing your schema, it is worth looking at publicly available standard schemas. These standard
schemas often contain all definitions to store the required data and, more importantly, ensure
interoperability across other directories.

Naming Model
The LDAP Naming model defines how entries are organized in a directory. It also determines how a
particular entry can be uniquely identified. The Naming model recommends that entries be stored logically
in a hierarchical fashion. This entry tree is often called a directory information tree (DIT). Figure 1-4
provides an example of a generic directory tree.

Figure 1-4 Generic DIT

The tree’s root is usually referred to as the base or suffix of the directory. This entry represents the
organization that owns the directory. The format of suffixes can vary from implementation to
implementation, but generally, there are three recommended approaches, as listed in Figure 1-5.

Figure 1-5 Directory suffix naming conventions

Note DC stands for domain component.

The first recommended technique is to use the organization’s domain name as the suffix. For example, if the
organization’s domain name is example.com, the directory suffix will be o=example.com. The second
technique also uses the domain name, but each name component is prepended with “dc=” and joined by
commas. So the domain name example.com would result in a suffix dc=example, dc=com. This technique
is proposed in RFC 224714 and is popular with Microsoft Active Directory. The third technique uses the
X.500 model and creates a suffix in the format o=organization name, c=country code. In the United States,
the suffix for the organization example would be o=example, c=us.
The naming model also defines naming and uniquely identifying entries in a directory. Entries with a
common immediate parent are uniquely identified via their relative distinguished name (RDN), also called
distinguished name (DN). The RDN is computed using one or more attribute/value pairs of the entry. In its
simplest case, RDN is usually of the form attribute-name = attribute value. Figure 1-6 provides a simplified
representation of an organization directory. Each person entry under ou=employees has a unique uid. So the
RDN for the first person entry would be uid=emp1, where emp1 is the employee’s user id.

Figure 1-6 Example of an organization directory

Note The distinguished name is not an actual attribute in the entry. It is a logical name associated with
the entry.

It is important to remember that RDN cannot be used to uniquely identify the entry in the entire tree.
However, this can be easily done by combining the RDNs of all the entries in the path from the top of the tree
to the entry. The result of this combination is referred to as distinguished name (DN). In Figure 1-6, the DN
for person 1 would be uid=emp1, ou=employees, dc=example, dc=com. Since the DN is made by combining
RDNs, if an entry’s RDN changes, the DNs of that entry and all its child entries also change.
There can be situations where a set of entries does not have a unique attribute. In those scenarios, one
option is to combine multiple attributes to create uniqueness. For example, we can use the consumer’s
common name and email address in the previous directory as an RDN. Multivalued RDNs are represented by
separating each attribute pair with a +, like so:

cn = Balaji Varanasi + mail=balaji@inflinx.com

Some special characters on the RDN must be escaped to prevent different problems. The special
characters are + (plus), = (equals), < (less than), > (greater than), ; (semicolon), , (comma), \ (backslash), #
(number sign), and ”.
There are different approaches to escape the characters, like adding the backslash (“\” ASCII 92) before
the special character; this approach is the most commonly used. The other replaces the special characters
with a backslash and hexadecimal digit, and the last one surrounds the attribute’s value with quotation
marks (“”).

Note Multivalued RDNs are usually discouraged. Creating a unique sequence attribute is recommended
in those scenarios to ensure uniqueness.

Functional Model
The LDAP Functional model describes the access and modification operations that can be performed on the
directory using the LDAP protocol. These operations fall into three categories: query, update, and
authentication.
The query operations are used to search and retrieve information from a directory. So whenever some
information needs to be read, a search query must be constructed and executed against LDAP. The search
operation takes a starting point within DIT, the search depth, and the attributes an entry must have for a
match. In Chapter 6, you’ll delve deep into searching and look at all the available options.
The update operations add, modify, delete, and rename directory entries. As the name suggests, the add
operation adds a new entry to the directory. This operation requires the DN of the entry to be created and a
set of attributes that constitute the entry. The delete operation takes a fully qualified DN of the entry and
deletes it from the directory. The LDAP protocol allows only the leaf entries to be deleted. The modified
operation updates an existing entry. This operation takes the entry’s DN and a set of modifications, such as
adding a new attribute, updating a new one, or removing an existing one. The rename operation can rename
or move entries in a directory.
The authentication operations are used for connecting and ending sessions between the client and the
LDAP server. A bind operation initiates an LDAP session between the client and server. Typically, this would
result in an anonymous session. The client can provide a DN and credentials to authenticate and create an
authenticated session. On the other hand, the unbind operation can be used to terminate an existing session
and disconnect from the server.
LDAP V3 introduced a framework for extending existing operations and adding new ones without
changing the protocol. You will take a look at these operations in Chapter 7.

Security Model
The LDAP Security model protects LDAP directory information from unauthorized access. The model
specifies which clients can access which parts of the directory and what kinds of operations (search vs.
update) are allowed.
The LDAP Security model is based on the client authenticating to the server. As discussed earlier, this
authentication process or bind operation involves the client supplying a DN identifying itself and a
password. An anonymous session is established if the client does not provide a DN and password. RFC
282915 defines a set of authentication methods that LDAP V3 servers must support. After successful
authentication, the access control models are consulted to determine whether the client has sufficient
privileges to do what is requested. Unfortunately, no standards exist for access control models, and each
vendor provides their implementations.

LDIF Format
The LDAP Data Interchange Format (LDIF) is a standard text-based format for representing directory
content and update requests. The LDIF format is defined in RFC 2849.16 LDIF files are typically used to
export data from one directory server and import it into another. It is also popular for archiving directory
data and applying bulk updates to a directory. You will use LDIF files to store your test data and refresh the
directory server between unit tests.
The basic format of an entry represented in LDIF is as follows:

#comment
dn: <distinguished name>
objectClass: <object class>
objectClass: <object class>
...
...
<attribute type>: <attribute value>
<attribute type>: <attribute value>
...

Lines in the LDIF file starting with a # character are considered comments. The dn and at least one
objectClass entry definition are considered required. Attributes are represented as name/value pairs
separated by a colon. Multiple attribute values are specified in separate lines and will have the same
attribute type. Since LDIF files are purely text based, binary data needs to be Base64 encoded before it is
stored as part of the LDIF file.
Blank lines separate multiple entries in the same LDIF file. Listing 1-1 shows an LDIF file with three
employee entries. Notice that the cn attribute is multivalued and is represented twice for each employee.

# Barbara’s Entry
dn: cn=Barbara J Jensen, dc=example, dc=com
# multi valued attribute
cn: Barbara J Jensen
cn: Babs Jensen
objectClass: personsn: Jensen
# Bjorn’s Entry
dn: cn=Bjorn J Jensen, dc=example, dc=com
cn: Bjorn J Jensen
cn: Bjorn Jensen
objectClass: person
sn: Jensen
# Base64 encoded JPEG photo
jpegPhoto:: /9j/4AAQSkZJRgABAAAAAQABAAD/2wBDABALD
A4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQ
ERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVG
# Jennifer’s Entry
dn: cn=Jennifer J Jensen, dc=example, dc=com
cn: Jennifer J Jensen
cn: Jennifer Jensen
objectClass: person
sn: Jensen
Listing 1-1 LDIF file with three employee entries

LDAP History
LDAP was developed by Tim Howes, Steve Kille, and Wengyik Yeong to create a network protocol to get data
out. In 1993 appeared the first draft of the RFC 1487,17 which contained the specification of LDAP based on
the access of X.500.
The first version acts as a proxy or gateway to X.500 directories, a comprehensive directory service
developed in the 1980s.
Tim Howes, with his colleagues, created the Open Source University of Michigan LDAP Implementation,
which became the reference for all the LDAP servers. The project’s website is active18 and accessible only for
historical reference.
The second version, the first to be operative (LDAPv2), was released in 1993 as an Internet Engineering
Task Force (IETF) Proposed Standard with basic operations like searching and modifying information. This
version offers limited functionality and has some problems related to the security mechanisms.
The third version, the latest available, was released in 1997, including many improvements related to
security, like Transport Layer Security (TLS) and the possibility of supporting referrals. It was based on RFCs
like RFC 225119 and RFC 4519,20 which explain the protocol and the supported data models. This version
became the de facto standard for directory services, and many applications have support to integrate and
use LDAP to obtain certain information.

LDAP Vendors
LDAP gained wide support from various vendors. There has also been a strong open source movement to
produce LDAP servers. Table 1-5 outlines some of the popular directory servers and include the information
about which is the docker image to run each of them with a small configuration.
Table 1-5 LDAP Vendors
Directory Vendor Open URL
Name Source?
Apache DS Apache Yes https://directory.apache.org/apacheds/ https://hub.docke
OpenLDAP OpenLDAP Yes https://www.openldap.org/ https://hub.d

Tivoli IBM No https://www.ibm.com/docs/en/i/7.5?topic=services-tivoli- No existing official i


Directory directory-server-i-ldap
Server
Active Microsoft No https://learn.microsoft.com/en-us/windows/win32/adsi/so- No existing official i
Directory what-is-active-directory?redirectedfrom=MSDN
eDirectory Novell No https://www.microfocus.com/en-us/cyberres/identity- No existing official
access-management/edirectory

Oracle Oracle No https://www.oracle.com/security/identity- No existing official i


Directory (formerly management/technologies/directory-server-enterprise-
Server Sun) edition
Enterprise
Edition
(ODSEE)
Oracle No https://www.oracle.com/middleware/technologies/internet- No existing official i
Internet directory.html
Directory
(OID)
OpenDJ ForgeRock Yes https://github.com/OpenIdentityPlatform/OpenDJ https://hub.docker
ApacheDS and OpenDJ are pure Java implementations of LDAP directories. You will be using these two
servers for unit and integration testing of the code throughout this book.

Sample Application
Throughout this book, you will be working with a directory for a hypothetical book library. I have chosen the
library because the concept is universal and easy to grasp. A library usually stores books and other
multimedia that patrons can borrow. Libraries also employ people to take care of daily library operations. To
keep things manageable, the directory will not store book information. A relational database is suitable for
recording book information. Figure 1-7 shows the LDAP directory tree for our library application.

Figure 1-7 Library DIT

I have used the RFC 224714 convention in this directory tree to name the base entry. The base entry has
two organizational unit entries that hold the employees’ and patrons’ information. The ou=employees part
of the tree will hold all the library employee entries. The ou=patrons part of the tree will hold the library
patron entries. Both library employee and patron entries are of the type inetOrgPerson objectClass.
Both employees and patrons access library applications using their unique login id. Thus, the uid attribute
will be used as the RDN for entries.
Summary
LDAP and applications that interact with LDAP have become a key part of every enterprise today. This
chapter covered the basics of the LDAP directory. You learned that LDAP stores information as entries. Each
entry is made up of attributes that are simply key-value pairs. These entries can be accessed via their
distinguished names. You also saw that LDAP directories have schemas that determine the type of
information that can be stored.
The next chapter will look at communicating with an LDAP directory using Java Naming and Directory
Interface (JNDI). In the chapters following Chapter 2, you will focus on using Spring LDAP for developing
LDAP applications.

Footnotes
1 https://docs.oracle.com/javase/jndi/tutorial/ldap/models/x500.html

2 https://en.wikipedia.org/wiki/Write_Once_Read_Many

3 https://www.techtarget.com/searchstorage/definition/WORM-write-once-read-many

4 https://www.oracle.com/in/database/what-is-a-relational-database/

5 https://www.ibm.com/products/db2

6 https://www.mysql.com/

7 https://www.postgresql.org/

8 https://cassandra.apache.org/_/index.html

9 https://www.mongodb.com/

10 https://learn.microsoft.com/en-us/windows/win32/adschema/attributes-all

11 https://docs.oracle.com/cd/E24001_01/oid.1111/e10035/schema_objclass.htm

12 https://www.ietf.org/

13 https://www.rfc-editor.org/

14 https://www.ietf.org/rfc/rfc2247.txt

15 https://www.ietf.org/rfc/rfc2829.txt
16 https://www.ietf.org/rfc/rfc2849.txt

17 https://datatracker.ietf.org/doc/html/rfc1487

18 www.umich.edu/~dirsvcs/ldap/ldap.html

19 https://datatracker.ietf.org/doc/html/rfc2251

20 https://datatracker.ietf.org/doc/html/rfc4519
© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2023
B. Varanasi, A. Sacco, Practical Spring LDAP
https://doi.org/10.1007/979-8-8688-0002-3_2

2. Java Support for LDAP


Balaji Varanasi1 and Andres Sacco2
(1) Salt Lake City, UT, USA
(2) Buenos Aires, Buenos Aires, Argentina

As the name suggests, the Java Naming and Directory Interface (JNDI) provides a standardized
programming interface for accessing naming and directory services. It is a generic Application
Programming Interface (API) that can access various systems, including file systems, Enterprise Java Beans
(EJB),1 Common Object Request Broker Architecture (CORBA),2 and directory services such as the Network
Information Service and LDAP. JNDI’s abstractions to directory services can be viewed as similar to Java
Database Connectivity (JDBC)’s abstractions to relational databases.
The JNDI architecture consists of an Application Programming Interface or API and a Service Provider
Interface or SPI. Developers program their Java applications using the JNDI API to access directory/naming
services. Vendors implement the SPI with details that deal with actual communication to their particular
service/product. Such implementations are referred to as service providers. Figure 2-1 shows the JNDI
architecture and a few naming and directory service providers. This pluggable architecture provides a
consistent programming model and prevents the need to learn a separate API for each product.

Figure 2-1 JNDI architecture

The JNDI has been part of the standard JDK distribution since Java version 1.3 and has not moved to
Jakarta like other packages. The API itself is spread across five packages:
The javax.naming3 package contains classes and interfaces for looking up and accessing objects in a
naming service.
The javax.naming.directory4 package contains classes and interfaces that extend the core javax.naming
package. These classes can access directory services and perform advanced operations such as filtered
searching.
The javax.naming.event5 package has functionality for event notification when accessing naming and
directory services.
The javax.naming.ldap6 package contains classes and interfaces that support the LDAP Version 3
controls and operations. Later chapters will examine controls and operations.
The javax.naming.ldap.spi7 package contains classes to support defining custom DNS for LDAP. The
support of this feature has appeared since Java 12.
The javax.naming.spi8 package contains the SPI interfaces and classes. As mentioned earlier, service
providers implement SPI, and we will not cover these classes in this book.
LDAP Using JNDI
While JNDI allows access to a directory service, it is essential to remember that JNDI is not a directory or a
naming service. Thus, we need a running LDAP directory server to access LDAP using JNDI.
Accessing LDAP using JNDI usually involves three steps:
Connect to LDAP
Perform LDAP operations
Close the resources

Note Check if you have installed the correct version of Java on your machine. To do this, look at
Appendix A, which explains how to do it.
If you don’t have a test LDAP server available, please refer to the steps in Appendix B for installing a
local LDAP server or running it using Docker. The explanation about how to install Docker and check if
everything is okay appears in Appendix A.
This chapter aims to show how you can do different operations on LDAP using Java without any
framework. With this approach, you will see the complexity of doing certain operations and writing
many lines of code to do something simple with the assistance of some framework like Spring LDAP.

Connect to LDAP
All the naming and directory operations using JNDI are performed relative to a context. So the first step in
using JNDI is to create a context that acts as a starting point on the LDAP server. Such a context is referred to
as an initial context. Once an initial context is established, it can look up other contexts or add new objects.
The Context interface and InitialContext class in the javax.naming package can be used for creating an
initial naming context. Since we are dealing with a directory here, we will use a more specific DirContext
interface and its implementation InitialDirContext. Both DirContext and InitialDirContext are available
inside the javax.naming.directory package. The directory context instances can be configured with
properties that provide information about the LDAP server. The code in Listing 2-1 creates a context for an
LDAP server running locally on port 1389.

Properties environment = new Properties();


environment.setProperty(DirContext.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
environment.setProperty(DirContext.PROVIDER_URL, "ldap://localhost:11389");
DirContext context = new InitialDirContext(environment);
Listing 2-1 How to create a basic connection with LDAP

Note In the following parts of the chapter, I will explain in detail the most relevant parts to connect
and execute some operations to LDAP.
By the end of this chapter, you will see the different outputs of the execution of the different methods.

In Listing 2-1, we have used the INITIAL_CONTEXT_FACTORY constant to specify the service provider class
that needs to be used. Here, we use the sun provider com.sun.jndi.ldap.LdapCtxFactory, which is part of
the standard JDK distribution. The PROVIDER_URL is used to specify the fully qualified URL of the LDAP
server. The URL includes the protocol (LDAP for nonsecure or LDAPs for secure connections), the server
hostname, and the port.

Note The declaration of the type on a variable has been optional since Java 14, so you don’t need to
declare that the variable environment has the type Properties; you can replace the keyword var, and the
compiler will infer the correct type.
This change does not add any feature related to the performance, so I decided to keep the code
simple.
Once a connection to the LDAP server is established, the application can identify itself by providing
authentication information. Contexts like the one created in Listing 2-1, where authentication information
is not provided, are called anonymous contexts. LDAP servers usually have ACLs (access list controls) that
restrict operations and information to certain accounts. So it is very common in enterprise applications to
create and use authenticated contexts. Listing 2-2 provides an example of creating an authenticated context.
Notice that we have used three additional properties to provide the binding credentials. The
SECURITY_AUTHENTICATION property is set to simple, indicating that we will use a plain text username
and password for authentication.

Properties environment = new Properties();


environment.setProperty(DirContext.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
environment.setProperty(DirContext.PROVIDER_URL, "ldap://localhost:11389");
environment.setProperty(DirContext.SECURITY_AUTHENTICATION, "simple");
environment.setProperty(DirContext.SECURITY_PRINCIPAL, "Directory Manager");
environment.setProperty(DirContext.SECURITY_CREDENTIALS, "secret");
DirContext context = new InitialDirContext(environment);
Listing 2-2 How to connect on LDAP using the credentials

Note On the declaration of the different properties, you can see the class DirContext appear many
times, which is not the best approach, so if you want to reduce the duplicates, you can simplify using
static imports. For example, you can declare the static import like this: import static
javax.naming.directory.DirContext.INITIAL_CONTEXT_FACTORY, and on the declaration of the variable,
just use PROVIDER_URL.

Any problems occurring during the context creation will be reported as instances of
javax.naming.NamingException. NamingException is the superclass of all the exceptions thrown by the
JNDI API. This is a checked exception and must be handled properly for the code to compile. Table 2-1 lists
common exceptions we will likely encounter during JNDI development.
Table 2-1 Common LDAP Exceptions

Exception Description
AttributeInUseException Thrown when an operation tries to add an existing attribute.
AttributeModificationException Thrown when an operation tries to add/remove/update an attribute and violates the
attribute’s schema or state. For example, adding two values to a single-valued attribute
would result in this exception.
CommunicationException Thrown when an application fails to communicate (network problems) with the LDAP
server.
InvalidAttributesException Thrown when an operation tries to add or modify an attribute set that has been specified
incompletely or incorrectly. For example, adding a new entry without specifying all the
required attributes would result in this exception.
InvalidAttributeValueException Thrown when an operation tries to add or modify a value of an attribute that enters a
conflict with the schema definition.
InvalidSearchFilterException Thrown when a search operation is given a malformed search filter.
LimitExceededException Thrown when a search operation abruptly terminates as a user- or system-specified result
limit is reached.
NameAlreadyBoundException Thrown to indicate that an entry cannot be added as the associated name is already bound
to a different object.
NotContextException Thrown when an operation process until the context is required to continue.
OperationNotSupportedException Thrown when a context implementation does not support a specific operation when
invoked.
PartialResultException Thrown to indicate that only a portion of the expected results is returned and the
Exception Description
operation cannot be completed.
SizeLimitExceededException Thrown when a method produces a result that exceeds a size-related limit.
TimeLimitExceededException Thrown when a method produces a result that exceeds a time-related limit.

LDAP Operations
Once we obtain an initial context, we can perform various operations on LDAP using the context. These
operations can involve looking up another context, creating a new one, and updating or removing an
existing one. Here is an example of looking up another context with DN
uid=emp1,ou=employees,dc=inflinx,dc=com:

DirContext
anotherContext = context.lookup("uid=emp1,ou=employees,dc=inflinx,dc=com");

We will closely examine each of these operations in the coming section.

Closing Resources
After completing all desired LDAP operations, it is important to close the context and any other associated
resources properly. Closing a JNDI resource simply involves calling the close method on it. Listing 2-3 shows
the code associated with closing a DirContext. The code shows that the close method also throws a
NamingException that needs to be properly handled.

try {
context.close();
} catch (NamingException e) {
//Do something with the exception, like log the error.
}
Listing 2-3 How to close the connection with LDAP

Note The previous block does not use “try-with-resources” because DirContext does not implement
the auto closeable.

Creating a New Entry


Consider the case where a new employee starts with our hypothetical library, and we are asked to add their
information to LDAP. As we have seen earlier, before an entry can be added to LDAP, it is necessary to obtain
an InitialDirContext. Listing 2-4 defines a reusable method for doing this.

private DirContext getContext() throws NamingException{


Properties environment = new Properties();
environment.setProperty(DirContext.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
environment.setProperty(DirContext.PROVIDER_URL,
"ldap://localhost:1389");
environment.setProperty(DirContext.SECURITY_PRINCIPAL, "cn=Directory
Manager");
environment.setProperty(DirContext.SECURITY_CREDENTIALS, "secret");
return new InitialDirContext(environment);
}
Listing 2-4 Create a method to connect with LDAP
Once we have the initial context, adding the new employee information is straightforward, as shown in
Listing 2-5.

public void addEmployee(Employee employee) {


DirContext context = null;
try {
context = getContext();
// Populate the attributes
Attributes attributes = new BasicAttributes();
attributes.put(new BasicAttribute("objectClass", "inetOrgPerson"));
attributes.put(new BasicAttribute("uid", employee.getUid()));
attributes.put(new BasicAttribute("givenName",
employee.getFirstName()));
attributes.put(new BasicAttribute("surname", employee.getLastName()));
attributes.put(new BasicAttribute("commonName",
employee.getCommonName()));
attributes.put(new BasicAttribute("departmentNumber",
employee.getDepartmentNumber()));
attributes.put(new BasicAttribute("mail", employee.getEmail()));
attributes.put(new BasicAttribute("employeeNumber",
employee.getEmployeeNumber()));
Attribute phoneAttribute =
new BasicAttribute("telephoneNumber");
for(String phone : employee.getPhone()) {
phoneAttribute.add(phone);
}
attributes.put(phoneAttribute);
// Get the fully qualified DN
String dn = "uid="+employee.getUid() + "," + BASE_PATH;
// Add the entry
context.createSubcontext("dn", attributes);
} catch(NamingException e) {
// Handle the exception and show the description of the problem
} finally {
closeContext(context);
}
}
Listing 2-5 Add a new entry on LDAP

As you can see, the first step in the process is to create a set of attributes that needs to be added to the
entry. JNDI provides the javax.naming.directory.Attributes interface and its implementation
javax.naming.directory.BasicAttributes to abstract an attribute collection. We then add the employee’s
attributes one at a time to the collection using JNDI’s javax.naming.directory.BasicAttribute class. Notice
that we have taken two approaches in creating the BasicAttribute class. In the first approach, we added the
single-valued attributes by passing the attribute name and value to BasicAttribute’s constructor. To handle
the multivalued attribute telephone, we first created the BasicAttribute instance by just passing in the
name. Then, we individually added the telephone values to the attribute. Once all the attributes are added,
we invoked the createSubcontext method on the initial context to add the entry. The createSubcontext
method requires the fully qualified DN of the entry to be added.
Notice that we have delegated the closing of the context to a separate method closeContext. Listing 2-6
shows its implementation.

private void closeContext(DirContext context) {


try {
if (null != context) {
context.close();
}
} catch (NamingException e) {
// Handle the exception and show the description of the problem
}
}
Listing 2-6 How to close the connection with LDAP

Updating an Entry
Modifying an existing LDAP entry can involve any of the following operations:
Add a new attribute and value(s) or add a new value to an existing multivalued attribute.
Replace an existing attribute value(s).
Remove an attribute and its value(s).
To allow modification of the entries, JNDI provides an aptly named
javax.naming.directory.ModificationItem class.
A ModificationItem consists of the type of modification to be made and the attribute under modification.
The following code creates a modification item for adding a new telephone number:

Attribute telephoneAttribute = new BasicAttribute("telephone",


"80181001000");
ModificationItem modificationItem = new ModificationItem(DirContext.
ADD_ATTRIBUTE, telephoneAttribute);

Notice that in the preceding code, we have used the constant ADD_ATTRIBUTE to indicate that we want
an add operation. Table 2-2 provides the supported modification types along with their descriptions.

Table 2-2 LDAP Modification Types

Modification Type Description


ADD_ATTRIBUTE Adds the attribute with the supplied value or values to the entry. If the attribute does not exist, then it
will be created. If the attribute is multivalued, this operation adds the specified value(s) to the
existing list. However, this operation on an existing single-valued attribute will result in the
AttributeInUseException.
REPLACE_ATTRIBUTE Replaces existing attribute values of an entry with the supplied values. If the attribute does not exist,
then it will be created. If the attribute already exists, all its values will be replaced.
REMOVE_ATTRIBUTE Removes the specified value from the existing attribute. If no value is specified, the entire attribute
will be removed. If the specified value does not exist in the attribute, the operation will throw a
NamingException. If the value to be removed is the only value of the attribute, then the attribute is
also removed.

The code for updating an entry is provided in Listing 2-7. The modifyAttributes method takes the entry’s
fully qualified DN and an array of modification items.

public void update(String dn, ModificationItem[] items) {


DirContext context = null;
try {
context = getContext();
context.modifyAttributes(dn, items);
} catch (NamingException e) {
// Handle the exception and show the description of the problem
} finally {
closeContext(context);
}
}
Listing 2-7 How to update an entry
Removing an Entry
Removing an entry using JNDI is a straightforward process shown in Listing 2-8. The destroySubcontext
method takes the fully qualified DN of the entry that needs to be deleted.

public void remove(String dn) {


DirContext context = null;
try {
context = getContext();
context.destroySubcontext(dn);
} catch (NamingException e) {
// Handle the exception and show the description of the problem
} finally {
closeContext(context);
}
}
Listing 2-8 How to remove an entry

Many LDAP servers don’t allow an entry to be deleted if it has child entries. In those servers, deleting a
non-leaf entry would require traversing the subtree and deleting all the child entries. Then the non-leaf
entry can be deleted. Listing 2-9 shows the code involved in deleting a subtree.

public void removeSubtree(DirContext ctx, String root) throws


NamingException {
NamingEnumeration enumeration = null;
try {
enumeration = ctx.listBindings(root);
while (enumeration.hasMore()) {
Binding childEntry = (Binding) enumeration.next();
LdapName childName = new LdapName(root);
childName.add(childEntry.getName());

try {
ctx.destroySubcontext(childName);
} catch (ContextNotEmptyException e) {
removeSubtree(ctx, childName.toString());
ctx.destroySubcontext(childName);
}
}
} catch (NamingException e) {
// Handle the exception and show the description of the problem
} finally {
try {
enumeration.close();
} catch (Exception e) {
// Handle the exception and show the description of the problem
}
}
}
Listing 2-9 How to remove a subtree of elements

Note The OpenDJ LDAP server supports a special subtree delete control that can cause the server to
delete the non-leaf entry and all its child entries when attached to a delete request. We will look at using
LDAP controls in Chapter 7.
Searching Entries
Searching for information is usually the most common operation against an LDAP server. To perform a
search, we need to provide information such as the scope of the search, what we are looking for, and what
attributes need to be returned. In JNDI, this search metadata is provided using the SearchControls class.
Listing 2-10 provides an example of a search control with subtree scope and returns the givenName and
telephoneNumber attributes. The subtree scope indicates that the search should start from the given base
entry and should search all its subtree entries. We will look at the different scopes available in detail in
Chapter 6.

SearchControls searchControls = new SearchControls();


searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setReturningAttributes(new String[]{"givenName",
"telephoneNumber"});
Listing 2-10 The attributes to return for each entry

Once the search controls are defined, the next step is invoking one of the many search methods in the
DirContext instance. Listing 2-11 provides the code that searches all the employees and prints their first
name and telephone number.

public void search() {


DirContext context = null;
NamingEnumeration<SearchResult> searchResults = null;
try {
context = getContext();
// Setup Search meta data
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setReturningAttributes(new String[] { "givenName",
"telephoneNumber" });
searchResults = context.search("dc=inflinx,dc=com", "
(objectClass=inetOrgPerson)", searchControls);

while (searchResults.hasMore()) {
SearchResult result = searchResults.next();
Attributes attributes = result.getAttributes();
String firstName = (String) attributes.get("givenName").get();

// Read the multi-valued attribute


Attribute phoneAttribute = attributes.get("telephoneNumber");
String[] phone = new String[phoneAttribute.size()];
NamingEnumeration phoneValues = phoneAttribute.getAll();

for (int i = 0; phoneValues.hasMore(); i++) {


phone[i] = (String) phoneValues.next();
}
//You can use logback or system.out
logger.info(firstName + "> " + Arrays.toString(phone));
}
} catch (NamingException e) {
// Handle the exception and show the description of the problem
} finally {
try {
if (null != searchResults) {
searchResults.close();
}
closeContext(context);
} catch (NamingException e) {
// Handle the exception and show the description of the problem
}
}
}
Listing 2-11 How to search elements
Here, we used the search method with three parameters: a base that determines the search’s starting
point, a filter that narrows down the results, and a search control. The search method returns an
enumeration of SearchResults. Each search result holds the LDAP entry’s attributes. Hence, we loop through
the search results and read the attribute values. Notice that we obtain another enumeration instance for
multivalued attributes and read its values one at a time. In the final part of the code, we close the result
enumeration and the context resources.

Check How the Operations Work


After that, reading all the source code of the different operations could be a good idea to check if everything
works fine or not. To do this, a possible approach is to create a class that invokes the different methods of
accessing LDAP using JNDI.
Listing 2-12 shows you a class App that creates an instance of a class JndiLdapDaoImpl, which contains
all the methods of the different operations you see from Listings 2-4 to 2-11. In the case of Listing 2-12, you
only will execute one operation because it’s more simple to analyze the logs.

public class App {


public static void main(String[] args) {
JndiLdapDaoImpl jli = new JndiLdapDaoImpl();
//Search
jli.search();
}
}
Listing 2-12 A class that invokes the method search

If you run the application with the previous block of code, you will see something like Listing 2-13.

12:23:40.978 [main] INFO com.apress.book.ldap.dao.impl.JndiLdapDaoImpl -


Chie> [+1 622 858 9026]
12:23:40.978 [main] INFO com.apress.book.ldap.dao.impl.JndiLdapDaoImpl -
Chin> [+1 191 452 7983]
12:23:40.978 [main] INFO com.apress.book.ldap.dao.impl.JndiLdapDaoImpl -
ChinFui> [+1 439 500 8383]
12:23:40.978 [main] INFO com.apress.book.ldap.dao.impl.JndiLdapDaoImpl -
Ching-Long> [+1 407 407 2419]
12:13:14.186 [main] INFO com.apress.book.ldap.dao.impl.JndiLdapDaoImpl -
Chip> [+1 833 470 1660]
Listing 2-13 The result of obtaining all the employees from LDAP

The next step is to add an employee and obtain all the employees to check whether the operations were
okay. Let’s make some little modifications to the class App, like Listing 2-14.

public class App {


public static void main(String[] args) {
JndiLdapDaoImpl jli = new JndiLdapDaoImpl();

//Add and search


jli.addEmployee(getEmployee());
Random documents with unrelated
content Scribd suggests to you:
beyond the city by the church; and passing first directly southward,
along the Phoenician coast, they next turned inland through
Samaria, everywhere visiting the churches on the route, and making
known to them the joyful story of the conversions among the
Gentiles of Asia Minor, which was news to the Christians of
Palestine, and caused great congratulations among them, at these
unexpected triumphs of their common faith. Arriving at Jerusalem,
they there, for the first time, gave to the twelve apostles, a detailed
account of their long Asian mission; and then brought forward the
grand question under debate. As soon as this point was presented,
all the obstinate Jewish prejudices of that portion of the church who
were of the order of the Pharisees, were instantly aroused,――and
with great earnestness they insisted “that it was necessary to
circumcise them, and to command them to keep the law of Moses.”
This first meeting however, adjourned without coming to any
conclusion; and the apostles and elders were called together again
to consider upon the matter. As soon as they were assembled they
all fell to disputing with great violence, and, of course, with no
decisive or profitable result; but at last the great apostolic chief rising
up, ended the debate with a very clear statement of the results of his
own personal experience of the divine guidance in this matter, and
with brief but decisive eloquence hushed their clamors, that they
might give Barnabas and Paul a chance to declare in what manner
God had sanctioned their similar course. The two apostles of the
Gentiles then narrated what miracles and wonders God had wrought
among the heathen by them. Such was the decisive effect of their
exposition of these matters of fact, that all debate was checked at
once; and James himself, the great leader of the Judaical order, rose
to express his perfect acquiescence in the decision of the apostolic
chief and the Hellenists. His opinion was, that only so much
conformity to the Mosaic institutions should be required of the
Gentile converts, as they might without inconvenience submit to, out
of respect to the old covenant, and such observances as were
necessary for the moral purity of a professing Christian of any nation.
The whole assembly concurred; and it was resolved to dispatch two
select persons out of their own company, to accompany Paul and
Barnabas to Antioch, and thus by their special commission, enforce
the decision of the apostolic and presbyterial council. The decision of
the council was therefore committed to writing, in a letter which bore
high testimony to the zeal and courage of Barnabas and Paul, as
“men who had hazarded their lives for the sake of the
gospel,”――and it was announced as the inspired decision of the
apostles, elders and brethren, that the Gentile converts should not
be troubled with any greater burden than these necessary
things:――“That you abstain from things offered to idols, and from
blood, and from things strangled, and from fornication;” and if they
should only keep themselves from these, they would do well. Jude
and Silas were the envoys commissioned with the charge of this
epistle, and accordingly accompanied Paul and Barnabas back to
Antioch.

♦ “acccording” replaced with “according”

“Those who maintained this position were Jews, of the sect of the Pharisees, Acts, xv. 5,
converted to Christianity, but still too zealous for the observance of the law; and their
coming immediately from Judea might make it rather believed, that the necessity of
circumcision, in order to salvation, was a tenet of the apostles. The Jews themselves indeed
were of different opinions in this matter, even as to the admission of a man into their
religion. For some of them would allow those of other nations who owned the true God, and
practised moral duties, to live quietly among them, and even without circumcision, to be
admitted into their religion; whilst others were decidedly opposed to any such thing. Thus
Josephus tells us that when Izates, the son of Helen, queen of Adiabene, embraced the
Jews’ religion, Ananias, who converted him, declared that he might do it without
circumcision; but Eleazer, another eminent Jew, maintained, that it was a great impiety in
such circumstances, to remain uncircumcised; and this difference of opinion continued
among the Jewish Christian converts, some allowing Gentiles to become converts to
Christianity, without submitting to circumcision and the Jewish law: whilst others contended
that without circumcision, and the observance of the law, their profession of the Christian
faith would not save them.” (Stackhouse from Whitby and Beausobre.)

“It is very evident, that this is the same journey to which the apostle alludes in Galatians
ii. First, from the agreement of the history here and the apostle’s relation in the epistle, as
that ‘he communicated to them the gospel, which he preached among the Gentiles,’
Galatians ii. 2. which he now did, Acts xv. 4. That circumcision was not then judged
necessary to the Gentiles, verse 3, as we find, Acts xv. 24, ‘that, when they saw the gospel
of uncircumcision was committed to him, they gave to him and Barnabas the right hand of
fellowship,’ Galatians ii. 9, as they did here, sending their very decree with one consent to
the Gentiles, ‘by the hands of Paul and Barnabas,’ Acts xv. 22, 25, who were received by
the ‘whole church,’ verse 4. and styled beloved,’ verse 25.
“Secondly, it appears unlikely that the apostle, writing this epistle about nine years after
this council, should make no mention of a thing so advantageous to a cause he is pleading
here, and so proper to confute the pretenses of the adversaries he disputes against. And,

“Thirdly, James, Peter, and John, being all the apostles now present at the council, the
mention of their consent to his doctrine and practice was all that was necessary to his
purpose to be mentioned concerning that council, It is no objection to this opinion, that we
find no mention, in Acts xv. of Titus’s being with him; for he is not mentioned in the whole of
the Acts, during which interval the journey must have happened.” (Whitby.)

“The Council of Jerusalem was assembled in the fourteenth year after St. Paul’s
conversion. For the apostle adverts to this same journey, and determinately specifies the
time in Galatians ii. 1, 2. Grotius is of opinion that four years should be here written instead
of fourteen; who, nevertheless, allows, that the one mentioned in Galatians, is this journey
to the Council. But the reason is evident why the apostle should date these years from the
epoch of his conversion, from the scope of the first and second chapters. He styles himself
an apostle, not of men, neither by man, chap. i. 1: he declared that his gospel was not
according to men, and that he neither received nor learned it from men, but by the
revelation of Jesus Christ, verses 11, 12. And this he proves to the Galatians by his
conversion, which was not unknown to them. He begins with his strict profession of the
Jewish religion, according to the tenets of the Pharisees, which ended in a most violent
persecution of the Christians. Then he goes on to show how God revealed his Son to him,
and that immediately he conferred not with flesh and blood, he neither held communion with
any man, neither did he go up to Jerusalem to them that were apostles before him, by
whom he could have been taught more fully the mind of God, ‘but went into Arabia,’ where
he received the gospel by revelation; and he returned to Damascus, and preached the word
of God to the confounding of the Jews: ‘Then after three years he went up to Jerusalem to
see Peter.’ From all this it appears evident, that the epoch of these three years should
commence at the time of his conversion. The same is to be said of the other epoch of the
fourteen years. ‘Then, after fourteen years, I went up again to Jerusalem,’ chap. ii. 1,
because the scope of both is the same,――and they both date from the same period of
time. The word επειτα does not connect this sentence with that of the three years, as if the
beginning of these should be dated from the close of those, because there is another επειτα
which comes between these two texts, viz. in verse 21, of chap. i. where he begins to relate
his travels in Syria and Cilicia, but does not specify the period of time he remained in those
regions; therefore no chronological connexion can have been intended by him. The apostle
still following up his design, says επειτα and παλιν, but neither does επειτα refer to his stay in
Syria and Cilicia,――nor παλιν to his second coming to Jerusalem: for he had been with a
second collection to Jerusalem, then suffering from famine, accompanied by Barnabas, but
not by Titus; and because he then saw none of the apostles, he omitted mentioning that
journey, considering it quite foreign to his present purpose.” (Pearson, Annales, 49.)

paul’s quarrel with peter.

The whole company of envoys, both Barnabas and Paul, the


original messengers of the Syrian church, and Jude and Silas, the
deputies of the apostolic college, presented the complete results of
the Jerusalem consultation before a fall meeting of the whole
congregation of believers at Antioch, and read the epistle of the
council to them. The sage and happy exhortations which it contained
were not only respectfully but joyfully received; and in addition to the
comfort of these, the first written words of Christian inspiration, the
two envoys, Jude and Silas, also discoursed to the church,
commenting at more length on the apostolic message of which they
were the bearers, and confirmed their hearers in the faith. After
remaining there for some time, Jude bade them farewell, and
returned to his apostolic associates; but Silas was so much pleased
with the opportunities thus afforded him of doing good among the
Gentiles, of whom he himself also was one, as his name
shows,――that he stayed in Antioch after the departure of Jude, and
labored along with Paul and Barnabas, teaching and preaching the
word of the Lord, with many others also. This is commonly
understood to be the time of Paul’s dissension with Peter, as
mentioned in the epistle to the Galatians. The circumstances of this
disagreeable occurrence have already been narrated and
commented on, in the Life of Peter,――nor need anything additional
be presented here in relation to Paul, except the observation, that his
dispute with the chief apostle, and his harsh censure of his conduct,
are very much in accordance with the impressions of his character,
given in other passages of his life. He was evidently a man of violent
and hasty passions; and is uniformly represented, both by his
historian and by himself, as exceedingly bitter and harsh in his
denunciations of all who differed from him on practical or speculative
points, both before and after his calling to the apostleship; and this
trait is manifested on such a variety of occasions, as to be very justly
considered an inseparable peculiarity of his natural disposition and
temperament. Doubtless there are many to whom it seems very
strange, that the Apostle Paul should ever be spoken of as having
been actually and truly angry, or ever having made an error in his
conduct after his conversion; but there are instances enough to show
that it was not a mere modest injustice to himself for him to tell the
Lystran idolaters that he was a man of like passions with
them,――but a plain matter of fact, made evident not only by his
own noble and frank confession, but by many unfortunate instances
throughout his recorded life. Yet there are a great many Protestants,
who have been in the habit of making such a kind of idol or demi-god
out of Paul, that they are as little prepared as the Lystrans to
appreciate the human imperfections of his character; and if Paul
himself could at this moment be made fully sensible of the dumb
idolatrous reverence with which many of his modern and enlightened
adorers regard him, he would be very apt to burst out in the same
earnest and grieved tone, in which he checked the similar folly of the
Lystrans,――“Sirs! why do ye these things? I also am a man of like
passions with yourselves.”――“The spirit of divine truth which
actuated me, and guided me in the way of light, by which I led others
to life eternal, still did not make me anything more than a man,――a
man in moral as in bodily weakness, nor exempt from liabilities to the
accidents of passion, any more than to the pains of mortal disease.
The Spirit that guided my pen in the record of eternal truth, and my
tongue in the preaching of the word of salvation, did not exalt me
above the errors, the failings and distresses of mortality; and I was
still all my lifetime subject to the bondage of sin, groaning under that
body of death, and longing for the day when I should pass away from
the frailties and distresses of earth, to that state of being which alone
is wholly sinless and pure.”

“From the opposition to St. Peter, which they suppose to be before the Council at
Jerusalem, some would have it, that this Epistle to the Galatians was written before that
Council; as if what was done before the Council could not be mentioned in a letter written
after the Council. They also contend, that this journey, mentioned here by St. Paul, was not
that wherein he and Barnabas went up to that Council to Jerusalem, but that mentioned
Acts xi. 30; but this with as little ground as the former. The strongest reason they bring, is,
that if this journey had been to the Council, and this letter after that Council, St. Paul would
not certainly have omitted to have mentioned to the Galatians that decree. To which it is
answered, 1. The mention of it was superfluous; for they had it already, see Acts xvi. 4. 2.
The mention of it was impertinent to the design of St. Paul’s narrative here. For it is plain,
that his aim, in what he relates here of himself, and his past actions, is to shew, that having
received the gospel from Christ by immediate revelation, he had all along preached that,
and nothing but that, everywhere; so that he could not be supposed to have preached
circumcision, or by his carriage, to have shewn any subjection to the law; all the whole
narrative following being to make good what he says, ♦chap. i. 11, ‘that the gospel which he
preached was not accommodated to the humoring of men; nor did he seek to please the
Jews (who were the men here meant) in what he taught.’ Taking this to be his aim, we shall
find the whole account he gives of himself, from that verse 11 of chap. i., to the end of the
second chapter, to be very ♠clear and easy, and very proper to invalidate the report of his
preaching circumcision.” (Locke’s Paraphrase.)
♦ “ehap.” replaced with “chap.” ♠ “ctear” replaced with “clear”

“I conceive that this happened at the time here stated, because Paul intimates in
Galatians ii. 11, that he was in Antioch when Peter came there; and Peter had never been
to Antioch before Paul was in that city after the Council of Jerusalem; and besides the
dissension between Paul and Barnabas, who was the intimate friend of Peter, appears to
have originated here.” Pearson’s Annales Paul. (A. D. 50.)

A fine exhibition of a quibbling, wire-drawn argument, may be found in Baronius,


(Annales, 51,) who is here put to his wits’ end to reconcile the blunt, “round, unvarnished
tale,” in Paul’s own account, (in Galatians ii. 11‒14,) with the papistical absurdity of the
moral infallibility of the apostles. He lays out an argument of five heavy folio pages to prove
that, though Paul quarreled thus with Peter, yet neither of them was in the slightest degree
to blame, &c. But the folly of explaining away the Scriptures in this manner, is not confined
wholly to the bigoted, hireling historian of papal Rome; some of the boldest of protestants
have, in the same manner, attempted to reconcile the statement of Paul with the vulgar
notions of apostolic infallibility. Witsius (Vita Pauli, iv. 12,) expends a paragraph to show that
neither of them was to blame; but following the usual course of anti-papist writers, he
represents the great protestant idol, Paul, in altogether the most advantageous light,
according to the perfectly proverbial peculiarity of the opponents of the church of Rome,
who, in their apostolic distinctions, uniformly “rob Peter to pay Paul.”

paul’s quarrel with barnabas.

The church of Antioch having thus made great advances under


these very abundant and extraordinary instructions, the apostles
began to turn their eyes again to a foreign field, and longed for a
renewal of those adventurous labors from which they had now had
so long a repose. Paul therefore proposed to Barnabas that they
should go over their old ground again:――“Let us go again and visit
our brethren in every city, where we have preached the word of the
Lord, and see how they do.” To this frank and reasonable
proposition, Barnabas readily agreed, and as it was desirable that
they should have an assistant with them on this journey, he
proposed that his nephew Mark should accompany them in this
capacity as he had done on their former voyage. But Paul,
remembering the manner in which he had forsaken them just as they
were entering upon the arduous missionary fields of Asia Minor,
refused to try again one who had once failed to do them the desired
service, at a time when he was most needed. Yet Barnabas, being
led, no doubt by his near relationship to the delinquent evangelist, to
overlook this single deficiency, and perhaps, having good reason to
think that he had now made up his mind to stick to them through
thick and thin, through good and bad fortune, was disposed to give
him another trial in the apostolic service, and therefore strongly
urged Paul to accept of him as their common assistant in this new
tour for which he was well fitted by his knowledge of the routes. Paul,
however, no doubt irritated against Mark, for the wavering spirit
already manifested by him at Perga, utterly refused to have anything
to do with him after such a display of character, and wished to take
some other person who had been tried in the good work with more
satisfactory results as to his resolution and ability. Barnabas of
course, was not at all pleased to have his sister’s son treated so
slightingly, and refused to have any substitute whatever, insisting
that Mark should go, while Paul was equally resolved that he should
not. The conclusion of the whole matter was, that these two great
apostles, the authorized messengers of God to the Gentiles,
quarreled downright; and after a great deal of furious contention,
they parted entirely from one another; and so bitter seems to have
been the division between them that they are not known to have ever
after been associated in apostolic labors, although they had been the
most intimate friends and fellow-travelers for many years, standing
by one another through evil and good report, through trials, perils,
distresses and almost to death. A most lamentable exhibition of
human ♦ weakness marring the harmonious progress of the great
scheme of evangelization! Yet it must be esteemed one of the most
valuable facts relating to the apostles, that are recorded in the
honest, simple, clear, and truly impartial narrative of Luke; because it
reminds the Christian reader of a circumstance, that he might
otherwise forget, in an undue reverence for the character of the
apostles,――and that is, the circumstance that these consecrated
ministers of the word of truth were, really and practically, in spite of
their holiness, “men of like passions with ourselves,” and even in the
arrangement of their apostolic duties, were liable to be governed by
the impulses of human passion, which on a few occasions like this,
acting in opposite directions in different persons at the same time,
brought them into open collisions and disputes,――which, if men of
their pure martyr-spirit, mostly too, under the guidance of a divine
influence, could not avoid, nor could satisfactorily settle, neither may
the unconsecrated historian of a later age presume to decide. Who
was right and who was wrong in this difficulty, it is impossible to say;
and each reader may judge for himself. It may be remarked,
however, that Paul was no more likely to be right than Barnabas; he
was a younger man, as it would appear from the circumstance that
he is named after him in the apostolic epistle;――he was no more an
apostle than Barnabas was; for both are thus named by Luke in his
account of their first journey, and both were expressly called by a
distinct revelation from the Holy Spirit to undertake the apostleship of
the Gentiles together. Paul also is known to have quarreled with
other persons, and especially with Peter himself, and that too without
very just cause; and although Barnabas may have been influenced
to partiality by his relationship to Mark, yet much also may be justly
chargeable to Paul’s natural violence and bitterness of temper, which
often led him into hasty acts, of which he afterwards repented, as he
certainly did in this very case, after some time; for he repeatedly
mentions Mark in his epistles in terms of regard, and what is most in
point, declares him to be “profitable to him in the ministry.”

♦ “weaknes” replaced with “weakness”

Witsius remarks, (Vita Pauli, iv. 16,) that the ancient Christian writers ascribe the
greatest part of the blame of this quarrel to Barnabas, whom they consider as having been
unduly influenced by natural affection for his kindred according to the flesh. “But”, as Witsius
rather too cautiously remarks, “it may well be doubted whether Paul’s natural violence of
temper did not carry him somewhat beyond the bounds of right. The Greeks have not
unwisely remarked――Ὁ Παυλος ἐζητει το δικαιον, ὁ Βαρναβας το Πιλανθροπον ‘Paul
demanded what was just――Barnabas, what was charitable.’ It might have been well
enough if Barnabas had yielded to the zeal of Paul; but it would not have been bad if Paul
had persuaded himself to allow something to the feelings of that most mild and amiable
man. Meanwhile, it deserves notice, that God so ordered this, that it turned out as much for
the individual benefit of Mark, as for the general benefit of the church. For the kind partiality
of Barnabas was of advantage to Mark, in preventing him from being utterly cast off from
apostolic companionship, and forsaken as unworthy; while to the church, this separation
was useful, since it was the means of confirming the faith of more of the churches in the
same time.” (Witsius.)

“From hence we may learn, not only that these great lights in the Christian church were
men of the like passions with us, but that God, upon this occasion, did most eminently
illustrate the wisdom of his providence, by rendering the frailties of two such eminent
servants instrumental to the benefit of his church, since both of them thenceforward
employed their extraordinary industry and zeal singly and apart, which till then had been
united, and confined to the same place.” (Stanhope on the Epistles and Gospels, vol. 4.)

his second apostolic mission.

After this unhappy dispute, the two great apostles of the Gentiles
separated; and while Barnabas, accompanied by his favorite
nephew, pursued the former route to Cyprus, his native island, Paul
took a different direction, by land, north and west. In selecting a
companion for a journey which he had considered as urgently
requiring such blameless rectitude and firmness of resolution, he had
set his heart upon Silas, the efficient Hellenist deputy from
Jerusalem, whose character had been fully tested and developed
during his stay in Antioch, where he had been so active in the
exercise of those talents, as a preacher, which had gained for him
the title of “prophet” before his departure from Jerusalem. Paul,
during his apostolic association with him, had laid the foundation of a
very intimate friendship; and being thus attached to him by motives
of affection and respect, he now selected him as the companion of
his missionary toils. Bidding the church of Antioch farewell, and
being commended by them to the favor of God, he departed,――not
by water, but through the cities of Syria, by land,――whence turning
westward, he passed through the Syrian gates into Cilicia; in all
these places strengthening the churches already planted, by making
large additions to them from the Gentiles around them. Journeying
northwest from Cilicia, he came by the Cilician gates of Taurus, to his
old scenes of labor and suffering, in Lycaonia, at Derbe and Lystra,
where he proceeded in the task of renewing and completing the
good work which he had himself begun on his former tour with
Barnabas; with whom he might now doubtless have effected vastly
more good, and whose absence must have been deeply regretted by
those who owed their hopes of salvation to the united prayers and
labors of him and Paul. Among those who had been converted here
by the apostles on their first mission, was a half-bred Jew, by name
Timotheus, his father having been a Greek who married Eunice, a
Jewess, and had maintained a high character among his countrymen
in that region, both in Lystra and Iconium. Under the early and
careful instructions of his pious mother, who had herself received a
superior religious education under her own mother Lois, Timothy had
acquired a most uncommon familiarity with the Scriptures, which
were able to make him wise unto salvation; and that he had learned
them and appreciated their meaning in a much more spiritual and
exalted sense than most Jews, appears from the fact, that
notwithstanding his early regard for the law as well as the prophets,
he had never complied with the Mosaic rite of
circumcision,――perhaps because his father may have been
prejudiced against the infliction of such a sign upon his child. Paul
becoming acquainted with Timothy, and seeing in the young man the
germ of those talents which were afterwards so eminent in the
gospel cause, determined to train him to be an assistant and
associate with him in the apostolic ministry,――and in order to make
him so far conform to all the rites of the ancient covenant, as would
fit him for an acceptable ministry among the Jews as well as the
Gentiles, he had him circumcised; and he was induced still farther to
this step of conformity, by the consideration of the effect it would
have on the Jews in that immediate neighborhood, who were already
very suspicious that Paul was in reality aiming at the utter overthrow
and extinction of all the Mosaic usages, and was secretly doing all
that he could to bring them into contempt and disuse. Having made
this sacrifice to the prejudices of his countrymen, he now considered
Timothy as completely fitted for usefulness in the apostolic ministry,
and henceforth made him his constant companion for years.

his westward journey.

With this accession to his company, Paul proceeded through the


cities of that region which he had before visited, and communicated
to them the decrees passed by the apostles and elders at
Jerusalem, for the regulation of the deportment of professing
Christians, in regard to the observance of Mosaic usages. They all,
moreover, labored for the extension of the churches already
founded, and thus caused them to be built up, so that they received
fresh additions daily. Nor did Paul limit his apostolic labors to the
mere confirmation of the work begun on his tour with Barnabas; but
after traversing all his old fields of exertion, he extended his journey
far north of his former route, through all Phrygia, and Galatia, a
province which had never before been blessed with the presence of
a Christian missionary,――and after laboring in his high vocation
there, he was disposed to move west, to the Ionian or true Asian
shore of the Aegean, but was checked by a direction which he could
not resist; and passing northward of the true Asian cities, he came
out of Phrygia into Mysia, the province that occupies the
northwestern corner of all Asia Minor, bounded north by the
Propontis and Hellespont, and west by the northern part of the
Aegean,――the true Asia lying south of it, within the geographical
division commonly named Lydia. Having entered Mysia, they were
expecting to turn northeast into Bithynia, when again their own
preferences and counsels were overruled by the same mysterious
impulse as before, and they therefore continued their westward
journey to the shore of the Hellespont and Aegean, arriving within
the classic region of the Troad, at the modern city of Alexandria
Troas, some miles south of that most glorious of all the scenes of
Grecian poetical antiquity, where, thirteen hundred years before,
“Troy was.” Here they rested for a brief space, and while they were
undecided as to the course which they ought next to pursue, Paul
had a remarkable vision, which gave a summons too distinct to be
mistaken or doubted, to a field in which the most noble triumphs of
the cross were destined to be won under his own personal
ministration, and where through thousands of years the name of
Christ should consecrate and re-exalt the land, over all whose hills,
mountains, streams, valleys, and seas, then as now, clustered the
rich associations of the most splendid antiquity that is marked in the
records of the past, with the beautiful and the excellent in poetry, art,
taste, literature, philosophy and moral exaltation. In the night, as
Paul was slumbering at his stopping-place, in the Troad, there
appeared to him a vision of a Macedonian, who seemed to cry out
beseechingly to him――“Come over into Macedonia, and help us!”
This voice of earnest prayer for the help of Christ, rolling over the
wide Aegean, was enough to move the ardent spirit of Paul, and on
waking he therefore summoned his companions to attend him in his
voyage to this new field. He had been joined here by a new
companion, as appears from the fact, that the historian of the Acts of
the apostles now begins to speak in the first person, of the apostolic
company, and it thence appears that besides Silas and Timotheus,
Paul was now attended by Luke. Setting sail from Troas, as soon as
they could get ready for this unexpected extension of their travels,
the whole four were wafted by a fresh south-eastern breeze from the
Asian coast, first to the large island of Samothrace; and on the
second day, they came to Neapolis, a town on the coast of
Macedonia, which is the seaport of the great city of Philippi.

his mission in macedonia.

They without delay proceeded to Philippi, the chief city of that part
of Macedonia, taking its name from that sage monarch who laid the
foundation of the Macedonian dominion over the Grecian world, and
gave this city its importance and splendor, re-building it, and granting
it the honors of his peculiar favor. Under the Roman conquest it had
lost no part of its ancient importance, but had been endowed by
Julius Caesar, in a special decree, with the high privileges of a
Roman colony, and was in the apostolic age one of the greatest
cities in that part of Europe. Here Paul and his companions staid for
several days; and seeking on the sabbath, for some place where
they could, in that heathen land, observe the worship, and celebrate
the praises of the God of their fathers, they wandered forth from the
great pagan city, and sat down, away from the unholy din of mirth
and business, in a retired place on the banks of the little stream
which ran by the town, being made up of numerous springs that rise
at the foot of the hills north of it,――which gave it the name of
Crenides, or “the city of springs;”――the common name of the town
before its conquest by Philip. In such places, by the side of streams
and other waters, the Jews were always accustomed to construct
their places for social worship; and here, in this quiet place, a few
Jewish residents of the city resorted for prayer, remembering the
God of their fathers, though so far from his sanctuary. Those who
thus kept up the worship of God in this place, are mentioned as
being women only; for it may always be observed that it is among
the softer sex that religion takes its deepest root, and among them a
regard to its observances is always found, long after the indifference
generated by a change of circumstances, or by the engrossing cares
of business, has turned away the devotions of men. So was it in
Philippi; while the sons of Judah had grown indifferent to those
observances of their religion, which were inconvenient, by interfering
with the daily arrangements of business intercourse with their
heathen fellow-citizens, the daughters of Zion came still regularly
together, to the place where prayer was wont to be made. Here the
apostolic company met them, and preached to them the new word of
grace, now revealed for all the scattered race of Israel, far and
near,――and not for them only, but also for the Gentiles. Among
these gentle auditors of the word of grace, now first proclaimed in
Greece, was a Jewess, named Lydia, who had emigrated from
Thyatira, in Lydian Asia, and now carried on in Philippi, a trade in the
purple dye, for which the region from which she came was so
famous, even from the time of Homer. While listening to the words of
Paul, her heart was opened to the comprehension of the truth of the
gospel, and she professed her faith in Jesus. Having been baptized
with all her household, she was so moved with regard for those who
had thus taught her the way of salvation, that she earnestly invited
them to make her house their home. Complying with her benevolent
and hospitable invitation, Paul, Silas, Timothy and Luke, took up their
abode in her house, and remained there throughout their whole stay
in Philippi.

Such was the beginning of the propagation of the gospel in


Greece,――such was the foundation of the first church ever planted
east of the Hellespont; and thus did Europe first receive the
doctrines of that faith, which now holds in all that mighty division of
the world, a triumphant seat, and constitutes the universal religion of
the nations that hold within themselves the sources of art,
learning,――all the refinements of civilization,――and of the
dominion of half the globe. Four pilgrims entered the city of Philippi,
unknown, friendless, and scorned for their foreign, half-barbarian
aspect. Strolling about from day to day, to find the means of
executing their strange errand, they at last found a few Jewish
women, sitting in a little retired place, on the banks of a nameless
stream. To them they made known the message of
salvation;――one of the women with her household believed the
gospel, and professed the faith of Jesus;――and from this beginning
did those glorious results advance, which in their progress have
changed the face of Europe, revolutionized the course of empires,
and modified the destiny of the world!

An incident soon occurred, however, which brought them into


more public notice, though not in a very desirable manner. As they
went out to the usual place of prayer on the bank of the stream, they
at last were noticed by a poor bedeviled crazy girl, who, being
deprived of reason, had been made a source of profit to a set of
mercenary villains, who taking advantage of the common
superstition of their countrymen about the supernatural endowments
of such unfortunate persons, pretended that she was a Pythoness,
indued by the Pythian Apollo with the spirit of prophecy; for not only
at Delphi, on his famous tripod, but also throughout Greece, he was
believed to inspire certain females to utter his oracles, concerning
future events. The owners and managers of this poor girl therefore
made a trade of her supposed soothsaying faculty, and found it a
very profitable business, through the folly of the wise Greeks of
Philippi. This poor girl had her crazy fancy struck by the appearance
of the apostolic company, as they passed along the streets to their
place of prayer, and following them, perceived, under the impulse of
the strange influence that possessed her, the real character of Paul
and his companions; and cried out after them, “These men are the
servants of the most high God, who show us the way of salvation.”
This she did daily for a long time, till at last, Paul, annoyed by this
kind of proclamation thus made at his heels, turned about, and by a
single command subdued the demoniac influence that possessed
her, and restored her to the freedom of sense and thought. Of course
she was now no longer the submissive instrument of the will of her
mercenary managers, and it was with no small vexation that they
found all chance of these easy gains was forever gone. In their rage
against the authors of what they deemed their calamity, they caught
Paul and Silas, as the foremost of the apostolic company, and
dragging them into the forum or courthouse, where the magistrates
were in session, they presented their prisoners as a downright
nuisance: “These men, who are Jews, do exceedingly trouble our
city; and teach customs which are not lawful for us to adopt nor
observe, if we are to maintain the privileges of Roman citizens.”
What the latter part of the accusation referred to, in particular, it is
not easy to say, and probably there was no very definite specification
made by the accusers; for the general prejudice against the Jews
was such, that the mob raised a clamor against them at once; and
the magistrates seeing in the apostles only some nameless foreign
vagabonds, who having come into the city without any reasonable
object in view were disturbing the peace of the inhabitants, had no
hesitation whatever in ordering them to be punished in the most
ignominious manner, and without any question or defense,
conforming to the dictation of that universally divine and immaculate
source of justice,――the voice of the people,――instantly had them
stripped and flogged at the discretion of their persecutors. After
having thus shamefully abused them, they did not dismiss them, but
cast them into prison, and set their feet in the stocks.

“Philippi was a city of Macedonia, of moderate extent, and not far from the borders of
Thrace. It was formerly called Crenides, from its ♦numerous springs, from which arises a
small stream, mentioned Acts xvi. 13, though it is commonly omitted in the maps. The name
of Philippi it received from Philip, father of Alexander, who enlarged it, and fortified it as a
barrier town against the Thracians. Julius Caesar sent hither a Roman colony, as appears
from the following inscription on a medal of this city, COL. IUL. AUG. PHIL. quoted in
Vaillant Num. æn. imp. T. I. p. 160, and from Spon Misc. p. 173. See also Pliny, L. IV. c. ii.
and the authors in Wolfii Curae, πρωτη της μεριδος της Μακεδονιας πολις, ‘the first city of that
district of Macedonia:’ but in what sense the word πρωτη, or ‘first,’ is here to be taken,
admits of some doubt. Paulus Æmilius had divided Macedonia into four districts, and that in
which Philippi was situated, was called πρωτη, or the first district. But of this district, Philippi
does not appear to be entitled, in any sense, to the name of πρωτη πολις. For if πρωτη be
taken in the sense of ‘first in respect to place,’ this title belonged rather to Neapolis, which
was the frontier town of Macedonia, towards Thrace, as appears from Acts xvii. 1. And, if
taken in the sense of ‘first in respect to rank,’ it belonged rather to Amphipolis, which was
the capital of this district of Macedonia, as appears from the following passage Livii History
Lib. XLV. 29. Capita regionum, ubi concilia fierent, primae regionis Amphipolin, secundae
Thessalonicen, &c. But the difficulty is not so great as it appears to be. For, though
Amphipolis was made the capital of the first district of ♠ Macedonia in the time of Paulus
Æmilius, and therefore entitled to the name of πρωτη, it is not impossible that in a
subsequent age, the preference was given to Philippi. Or even if Amphipolis still continued
to be the capital of the district, or the seat of the Roman provincial government, yet the title
πρωτη may have been claimed by the city of Philippi, though it were not the very first in point
of rank. We meet with many instances of this kind, on the medals of the Greek cities, on
which we find that more than one city of the same province, assumed the title of πρωτη. St.
Luke, therefore, who spent a long time at Philippi, and was well acquainted with the
customs of the place, gave this city the title which it claimed, and which, according to the
custom of the Greek cities, was inscribed probably on its coins. Hence it appears that the
proposal made by Pierce to alter πρωτη της μεριδος to πρωτη μεριδος, is unnecessary.”
(Michaelis’s Introduction, Vol. IV. pp. 152‒154. Marsh’s translation.)

♦ “numerons” replaced with “numerous”

♠ “Macodonia” replaced with “Macedonia”

“‘Where prayer was wont to be made.’ xvi. 13. This proseuchae signifies an oratory, a
place appointed for prayer; in heathen countries, they were erected in sequestered retreats,
commonly on the banks of rivers (as here) or on the sea-shore. Josephus has preserved
the decree of the city of Halicarnassus, permitting the Jews to erect oratories, part of which
is in the following terms:――‘We ordain that the Jews, who are willing, both men and
women, do observe the Sabbaths and perform sacred rites according to the Jewish law, and
build proseuchae by the seaside, according to the custom of their country; and if any man,
whether magistrate or private person, give them any hinderance or disturbance, he shall
pay a fine to the city.’ (Josephus, Antiquities, lib. xiv, cap. 10.) (Al. 24.)

“Many commentators, viz. Grotius, Drs. Whitby, Doddridge, and Lardner, agree with
Josephus, Philo, and Juvenal, that these places of worship were synonymous with
synagogues. But Calmet, Prideaux, and Hammond, contend that they were nearly the
same, yet there was a real difference between them; the synagogues were within the cities,
while the proseuchae were without, in retired spots, particularly in heathen countries, by the
river-side, with galleries or the shades of trees for their only shelter. Prideaux considers
them to be of greater antiquity than the synagogues, and that they were formed by the Jews
in open courts, that those who lived at a distance from Jerusalem might offer their private
worship as in the open courts of the Temple or Tabernacle. In the synagogues, Prideaux
observes, public worship was performed, and in the proseuchae private prayer was used to
be made. It is highly probable that these proseuchae were the same which are called in the
Old Testament ‘high places.’ (Hammond on Luke vi. 12, and Acts xvi. 13‒16. Calmet’s
Dictionary voce proseucha. Prideaux’s Connec, part i. book iv. sub anno 444. vol. I. pp.
387‒390. edition 1720.) (Horne’s Introduction.)

“‘And a certain woman named Lydia, a seller of purple, of the city of Thyatira.’ verse 14.
It is a remarkable fact, that among the ruins of Thyatira, there is an inscription extant with
the words ΟΙ ΒΑΦΕΙΣ, the dyers. Wheler’s Journey into Greece, vol. iii. p. 233. Spon,
Miscellanea Eruditae Antiquitates, p. 113; from whence we learn that the art and trade of
dyeing purple were carried on in that city.” (Horne’s Introduction.)

Here was fine business for the apostle and his companion! “Come
over into Macedonia and help us!” Such were the words of deep
agonizing entreaty, in which the beseeching Macedonian had, in the
night-vision, summoned the great apostle of the Gentiles to this new
field of evangelizing labor. Taking that summons for a divine
command, he had obeyed it――had crossed the wide Aegean, and
sought in this great city of Macedonia, the occasions and the means
of “helping” the idolatrous citizens to a knowledge of the truth as it
was in Jesus. Week after week they had been inoffensively toiling in
the faithful effort to answer this Macedonian cry for help; and what
was the result and the reward of all these exertions? For no crime
whatever, and for no reason except that they had rescued a gentle
and unfortunate spirit from a most degrading thraldom to demoniac
agencies, and to men more vile and wicked than demons, they had
been mobbed,――abused by a parcel of mercenary
scoundrels,――stripped naked in the forum, and whipped there like
thieves,――and at last thrown into the common jail among felons,
with every additional injury that could be inflicted by their determined
persecutors, being fettered so that they could not repose their sore
and exhausted bodies. Was not here enough to try the patience of
even an apostle? What man would not have burst out in furious
vexation against the beguiling vision which had led them away into a
foreign land, among those who were disposed to repay their
assiduous “help,” by such treatment? Thus might Paul and Silas
have expressed their vexation, if they had indeed been misled by a
mere human enthusiasm; but they knew Him in whom they had
trusted, and were well assured that He would not deceive them. So
far from giving way to despondency and silence, they uplifted their
voices in praise! Yes, praise to the God and Father of Jesus Christ,
that he had accounted them worthy to suffer thus for the glory of his
name. “At midnight Paul and Silas prayed and sang praises to God,
and the prisoners heard them.” In the dreary darkness,――inclosed
between massive walls, and bound in weighty fetters, their spirits
rose in prayer,――doubtless for those persecutors whom they came
over to “help,” and not for themselves,――since their souls were
already so surely stayed on God. To him they raised their voices in
praise, for their own peace and joy in believing. Not yielding like
those inspired by the mere impulses of human ambition or wild
enthusiasm,――they passed the dreary night, not

“In silence or in fear.――

They shook the depths of the prison gloom,

With their hymns of lofty cheer.――

Amid the storm they sang,”

for He whom they thus invoked did not leave them in their heroic
endurance, without a most convincing testimony that their prayers
and their songs had come up in remembrance before him. In the
midst of their joyous celebration of this persecution, while their
wondering fellow-prisoners, waked from their sleep by this very
unparalleled noise, were listening in amazement to this manifestation
of the manner of spirit with which their new companions were
disposed to meet their distresses,――a mighty earthquake shook
the city, and heaved the whole prison-walls on their foundations, so
that all the firmly barred doors were burst open, and, what was more
remarkable, all the chains fell from the prisoners. The jailer waking
up amidst this horrible crash, and seeing all the prison-doors open,
supposed that the prisoners had all escaped; and knowing how
utterly certain would be his ruin if his charge should thus be
broken,――in a fit of vexation and despair, he drew his sword, and
would have instantly killed himself, had not Paul, seeing through the
darkness the frenzied actions of the wretched man, called out to him
in a loud voice, clear and distinct amid the dreadful din, “Do thyself
no harm, for we are all here.”
Hearing these consolatory words, the jailer called for a light, and
sprang in, and came trembling, and fell down before Paul and Silas,
saying,――“Sirs! What must I do to be saved?” They
replied――“Believe on the Lord Jesus Christ, and thou shalt be
saved, with all thy house.” The jailer of course spoke of being saved
merely from present danger,――and appalled by the shock of the
earthquake, concluded at once that it had some connection with the
prayers and songs of the two Jewish prisoners, whom he knew to
have been unjustly punished and imprisoned. He supposed
therefore, that from those who were the occasion of the awful
occurrence, he might best learn the means of escaping its
destructive consequences. But his alarmed inquiries were made
instrumental in teaching him the way of escape from a peril of far
greater magnitude, threatening his spirit with the eternal ruin that
would fall at last on all the sinful opposers of the truth. The two
imprisoned preachers then proclaimed to him the word of the Lord,
and not only to him, but to all that were in his house. No sooner had
the jailer thus learned, by their eloquent words, the real character
and objects of his prisoners, than he immediately determined to
make them all the atonement in his power, for the shameful
treatment which they had received from his fellow-citizens. He took
them that same hour of the night, and washed their stripes, and was
baptized with all his house. Of course he could no longer suffer
those who were the authors of his hopes of salvation, to lie any
longer among felons; and he immediately brought them out of the jail
into his own house, and gave them food, making it a sort of festal
♦ occasion for himself and his whole family, who were all rejoicing
with him in the knowledge of the gospel. When it was day the
magistrates sent the officers of justice with a verbal order for the
release of the two prisoners, of whose abominable usage they were
now quite ashamed, after a night’s reflection, without the clamors of
a mob to incite them; and perhaps also their repentance may have
been promoted by the great earthquake during the night, for which
the Greeks and Romans would, as usual, seek some moral
occasion, looking on it of course, as a prodigy, expressive of the
anger of the gods, who might be supposed perhaps, to be indignant
at the flagrant injustice committed against these two friendless
strangers. But however satisfactory this atonement might seem to
the magistrates, Paul was by no means disposed to let them off so
quietly, after using him and Silas in this outrageous manner, in
absolute defiance of all forms of law and justice. To this permission
thus given him to sneak off quietly, he therefore returned the
indignant answer――“They have openly beaten us uncondemned,
though we are Roman citizens, and they have cast us into prison;
and now do they thrust us out so slily? No, indeed; but let them
come themselves and fetch us out.” This was alarming news indeed,
to the magistrates. Here they were found guilty of having violated
“the sacred privilege of Roman citizenship!”――a privilege which
always shielded its possessor from irregular tyranny, and required,
throughout the Roman world, that he should never be subjected to
punishment without the most open and formal investigation of the
charge; a privilege too, whose violation would bring down on them
the most remorseless vengeance of the imperial fountain of Roman
power. So nothing would do, but they must submit to the
uncomfortable necessity of bringing down their magisterial dignity, to
the low business of visiting their poor, abused prisoners in the jail,
and humbly apologizing for their own cruelty.

♦ “accasion” replaced with “occasion”

The magistrates of the great city of Philippi therefore came to the


prison, and brought out their abused victims, respectfully requesting
them to depart out of the city. The two prisoners accordingly
consented to retire quietly from the city, without making any more
trouble for their persecutors. Going first to the house of their kind
hostess, Lydia, they saw the brethren who had believed the gospel
there, during their apostolic ministrations, and having exhorted them,
bade them farewell, and in company with their two companions,
Timothy and Luke, left the city.
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.

Let us accompany you on the journey of exploring knowledge and


personal growth!

ebookmass.com

You might also like