So you’ve just installed Oracle Documaker Enterprise Edition (ODEE) into a green-field, and now you’re poking around the directory structure that’s been created for you. Or maybe you haven’t done this yet, in which case you can review previous posts on the subject here, here, and here. Maybe you’re just reading the documentation, and you came across various references to the bindings file, but nothing that really explains the why and where and what of the file. In this post, I’ll explain a little bit about JNDI and the bindings file, and what it means to ODEE.

Names, Context, and Bindings

This heading might sound like some arcane spell, but it’s more technical jargon that we need to understand before we get too deep into ODEE configuration files.  First, let’s define names and naming services. A name is a human-readable identifier for an object in a computing system. A naming service is a facility that provides the mapping of names to objects, like an address book. You’ve used a naming service perhaps without realizing it when you sent an email since the recipient has a name. Or, if you accessed a file in a computer, you located that file by its name. In a computing system, a naming service is used to identify and locate objects that might be used by an application, such as your internet browser, which uses the domain name system (DNS) to map host names to IP addresses.

To look up an object in a naming system, you must know the name of the object. But how do you know the appropriate name to use? What’s the format? This is the naming convention, which is a standard devised for each naming system that specifies the components of the name and any particular details such as component separators. DNS uses periods (“.”) to separate the components of domain names, e.g. www.oracle.com. File systems use slashes to separate components of file names, e.g. “/usr/bin” or “C:\system\”). A binding is necessary in the naming system, as it what associates a name to the object. Finally, a context is a set of bindings that follows a naming convention. A context provides the lookup (a/k/a name resolution) capability. For more details on naming and directory concepts, Oracle has a handy tutorial available here.

Wait, Just A Few More Acronyms…

Before we can get to the meat of the bindings file, we need to define a few more things… we’re getting close, I promise! Now that we understand names, context, and bindings, we need to put it into.. umm.. context — pardon the pun. Decades ago, when the gurus at Sun Microsystems were building and enhancing the Java framework, they became aware of a need for programs to talk to naming and directory services. Rather than building custom interfaces to each service provider, they came up with the Java Naming and Directory Interface (JNDI), which became one of the core components of the Java Platform. The JNDI, like many things in Java, is an application programming interface (API) that simplifies application development by providing a level of abstraction between a service implementation and the consumer of those services. The Java Development Kit (JDK) includes interfaces for common naming and directory service providers such as LDAP, DNS, RMI, and CORBA, to name a few. Using the JNDI, an application can easily consume services offered by providers that implement the JNDI service provider interface (SPI).

Now Can We Talk About the Bindings File?

Yes! We’re here now! You probably already know that ODEE requires a database, but you might not know how the workers interact with the database. If you review the ODEE Administrator Guide, there are numerous references to the bindings file. In fact, each worker’s documentation discusses the bindings file. In the Using the Supervisor section, the documentation states: The Supervisor then gets a JNDI data source to the configuration tables by reading the config/context/.bindings file. Next, it retrieves its configuration information from the ALCONFIGCONTEXT and APPCONFIGCONTEXT tables in the assembly line using the APP_ID column value of 1. Further on, the Supervisor documentation states that “the .bindings file contains the Java Naming and Directory Interface (JNDI) data sources used by the Supervisor and any process the Supervisor starts. It is located in the config/context subdirectory of Document Factory. “.

 

Right there, in just four sentences, the documentation tells us that the Supervisor (and in fact, each worker) reads the bindings file to create a JNDI data source, which is then used to connect to the database and retrieve configuration information. As you probably can surmise, or can read about further in the documentation, workers will also connect to the database to process their work. In short, the bindings file contains the database connection information (as well as some other related properties) — all in a JNDI context format, which is a representation of a Java object and its properties. As you might recall from the review above, a naming service defines its conventions, so the format of the bindings file is a JNDI standard. You may recall that binding associates a name to an object, and that a context is a collection of bindings that follow a convention. So, the bindings file, is the collection of name/object associations for a context, and the context is the configuration of ODEE’s Document Factory (hint: the directory name gives this away as it’s located in docfactory/config/context). If you look at a sample bindings file, you’ll see that name/object associations are similar to name/value pairings with some minor differences.

DMKRConfig/ClassName=javax.sql.DataSource

If you’re familiar with Java programming, you might recognize the class name javax.sql.DataSource — that’s because the bindings file represents an instantiation of this class and its properties, persisted to a file. The next entry in the file is part of the Java Factory programming pattern, in that connections to data sources are managed by a Factory, so the DataSource class expects a Factory to be defined. The bindings file provides this definition:

DMKRConfig/FactoryName=org.apache.commons.dbcp.BasicDataSourceFactory

The remainder of the bindings file content that is prefixed with DMKRConfig contains triplets of information, each identified by a prefix RefAddr and a unique integer. Each component of the triplet has one each of the properties Content, Type, and Encoding. Each of these triplets defines a property for the DataSource class. An example is shown below:

DMKRConfig/RefAddr/0/Content=oracle.jdbc.driver.OracleDriver

DMKRConfig/RefAddr/0/Encoding=String

DMKRConfig/RefAddr/0/Type=driverClassName

The object in this case is DMKRConfig, a representation of a database connection object.  The DataSource object expects to have a number of properties, each expressed as a triplet of Content, Encoding and Type. Each individual property has a numeric identifier (0 in the example above). The Type defines the object property, the Content is the object value, and the Encoding states how the object value is store (e.g. String).  Below are the properties expected to be contained in the bindings file for DataSource objects that represent the DMKRFactory and DMKRConfig datasources. Remember that each of these properties (except ClassName and FactoryName) will have three entries for Type, Content, and Encoding per the naming convention shown above.

Option

Description

ClassName

The data source fully-qualified class name. Use the javax.sql.DataSource value.

FactoryName

The data source factory fully-qualified class name. Use the org.apache.commons.dbcp.BasicDataSourceFactory value. The BasicDataSourceFactory class supports connection pooling.

driverClassName

The Java Database Connectivity (JDBC) driver class name.

url

The JDBC URL.

maxOpenPreparedStatements

The maximum number of prepared statements to cache in the connection pool. Use the value -1 to indicate there is no limit.

timeBetweenEvictionRunsM illis

How often the idle object evictor thread should run and clean up the stale connection handles. Use the value -1 to disable the idle object evictor thread.

validationQuery

A validation query that should be run when borrowing objects from the connection pool.

username

The JDBC user name.

password

The JDBC password.

testOnBorrow

Set this option to Yes if validationQuery should be used when borrowing an object from the connection pool. The default is No.

initialSize

The initial connection pool size.

maxActive

The maximum number of active connections in the pool.

maxIdle

The maximum number of idle connections in the pool.

minIdle

The minimum number of idle connections in the pool.

maxWait

The maximum time (in milliseconds) to wait for a connection object to be retrieved from the pool before issuing an error.

In most implementations it will only be necessary to change the bindings file if you need to change the credential information or connection string for the database. You can modify the bindings file to adjust these settings accordingly, but don’t forget that you’ll also need to change the data sources in WebLogic, since the services hosted therein do not use the bindings file. Also note that the example bindings file in the documentation shows unencrypted passwords, however when the DocFactory starts, it will encrypt any unencrypted passwords and rewrite the bindings file. If you look at your current bindings file you should see that it passwords are not stored in cleartext.

Wrap Up

If you need a one-sentence explanation of a bindings file, here it is: When an ODEE DocFactory worker starts, it creates a DataSource connections to the administrative and assembly line schemas by using JNDI APIs to read the bindings file and create the necessary objects. Hopefully, this short, succinct statement brings clarity to your understanding of the bindings file and how ODEE uses it in the context of DocFactory. If you need more clarification, I invite you to comment below, or join us over in the Documaker community.