blob: fa879432038e91b32aa37f58da2830eba1eb1a66 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>org.apache.hadoop.hbase.constraint (Apache HBase 3.0.0-alpha-2-SNAPSHOT API)</title>
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
<script type="text/javascript" src="../../../../../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="org.apache.hadoop.hbase.constraint (Apache HBase 3.0.0-alpha-2-SNAPSHOT API)";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../../../../../overview-summary.html">Overview</a></li>
<li class="navBarCell1Rev">Package</li>
<li>Class</li>
<li><a href="package-use.html">Use</a></li>
<li><a href="package-tree.html">Tree</a></li>
<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
<li><a href="../../../../../index-all.html">Index</a></li>
<li><a href="../../../../../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="../../../../../org/apache/hadoop/hbase/conf/package-summary.html">Prev&nbsp;Package</a></li>
<li><a href="../../../../../org/apache/hadoop/hbase/coordination/package-summary.html">Next&nbsp;Package</a></li>
</ul>
<ul class="navList">
<li><a href="../../../../../index.html?org/apache/hadoop/hbase/constraint/package-summary.html" target="_top">Frames</a></li>
<li><a href="package-summary.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="header">
<h1 title="Package" class="title">Package&nbsp;org.apache.hadoop.hbase.constraint</h1>
<div class="docSummary">
<div class="block">Restrict the domain of a data attribute, often times to fulfill business rules/requirements.</div>
</div>
<p>See:&nbsp;<a href="#package.description">Description</a></p>
</div>
<div class="contentContainer">
<ul class="blockList">
<li class="blockList">
<table class="typeSummary" border="0" cellpadding="3" cellspacing="0" summary="Interface Summary table, listing interfaces, and an explanation">
<caption><span>Interface Summary</span><span class="tabEnd">&nbsp;</span></caption>
<tr>
<th class="colFirst" scope="col">Interface</th>
<th class="colLast" scope="col">Description</th>
</tr>
<tbody>
<tr class="altColor">
<td class="colFirst"><a href="../../../../../org/apache/hadoop/hbase/constraint/Constraint.html" title="interface in org.apache.hadoop.hbase.constraint">Constraint</a></td>
<td class="colLast">
<div class="block">Apply a <a href="../../../../../org/apache/hadoop/hbase/constraint/Constraint.html" title="interface in org.apache.hadoop.hbase.constraint"><code>Constraint</code></a> (in traditional database terminology) to a Table.</div>
</td>
</tr>
</tbody>
</table>
</li>
<li class="blockList">
<table class="typeSummary" border="0" cellpadding="3" cellspacing="0" summary="Class Summary table, listing classes, and an explanation">
<caption><span>Class Summary</span><span class="tabEnd">&nbsp;</span></caption>
<tr>
<th class="colFirst" scope="col">Class</th>
<th class="colLast" scope="col">Description</th>
</tr>
<tbody>
<tr class="altColor">
<td class="colFirst"><a href="../../../../../org/apache/hadoop/hbase/constraint/BaseConstraint.html" title="class in org.apache.hadoop.hbase.constraint">BaseConstraint</a></td>
<td class="colLast">
<div class="block">Base class to use when actually implementing a <a href="../../../../../org/apache/hadoop/hbase/constraint/Constraint.html" title="interface in org.apache.hadoop.hbase.constraint"><code>Constraint</code></a>.</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="../../../../../org/apache/hadoop/hbase/constraint/ConstraintProcessor.html" title="class in org.apache.hadoop.hbase.constraint">ConstraintProcessor</a></td>
<td class="colLast">
<div class="block">Processes multiple <a href="../../../../../org/apache/hadoop/hbase/constraint/Constraint.html" title="interface in org.apache.hadoop.hbase.constraint"><code>Constraints</code></a> on a given table.</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="../../../../../org/apache/hadoop/hbase/constraint/Constraints.html" title="class in org.apache.hadoop.hbase.constraint">Constraints</a></td>
<td class="colLast">
<div class="block">Utilities for adding/removing constraints from a table.</div>
</td>
</tr>
</tbody>
</table>
</li>
<li class="blockList">
<table class="typeSummary" border="0" cellpadding="3" cellspacing="0" summary="Exception Summary table, listing exceptions, and an explanation">
<caption><span>Exception Summary</span><span class="tabEnd">&nbsp;</span></caption>
<tr>
<th class="colFirst" scope="col">Exception</th>
<th class="colLast" scope="col">Description</th>
</tr>
<tbody>
<tr class="altColor">
<td class="colFirst"><a href="../../../../../org/apache/hadoop/hbase/constraint/ConstraintException.html" title="class in org.apache.hadoop.hbase.constraint">ConstraintException</a></td>
<td class="colLast">
<div class="block">Exception that a user defined constraint throws on failure of a
<a href="../../../../../org/apache/hadoop/hbase/client/Put.html" title="class in org.apache.hadoop.hbase.client"><code>Put</code></a>.</div>
</td>
</tr>
</tbody>
</table>
</li>
</ul>
<a name="package.description">
<!-- -->
</a>
<h2 title="Package org.apache.hadoop.hbase.constraint Description">Package org.apache.hadoop.hbase.constraint Description</h2>
<div class="block">Restrict the domain of a data attribute, often times to fulfill business rules/requirements.
<h2>Table of Contents</h2>
<ul>
<li><a href="#overview">Overview</a></li>
<li><a href="#concurrency">Concurrency and Atomicity</a></li>
<li><a href="#caveats">Caveats</a></li>
<li><a href="#usage">Example Usage</a></li>
</ul>
<h2><a name="overview">Overview</a></h2> Constraints are used to enforce business rules in a
database. By checking all <a href="../../../../../org/apache/hadoop/hbase/client/Put.html" title="class in org.apache.hadoop.hbase.client"><code>Puts</code></a> on a given table, you
can enforce very specific data policies. For instance, you can ensure that a certain column
family-column qualifier pair always has a value between 1 and 10. Otherwise, the
<a href="../../../../../org/apache/hadoop/hbase/client/Put.html" title="class in org.apache.hadoop.hbase.client"><code>Put</code></a> is rejected and the data integrity is maintained.
<p/>
Constraints are designed to be configurable, so a constraint can be used across different tables,
but implement different behavior depending on the specific configuration given to that
constraint.
<p/>
By adding a constraint to a table (see <a href="#usage">Example Usage</a>), constraints will
automatically be enabled. You also then have the option of to disable (just 'turn off') or remove
(delete all associated information) all constraints on a table. If you remove all constraints
(see
<a href="../../../../../org/apache/hadoop/hbase/constraint/Constraints.html#remove-org.apache.hadoop.hbase.client.TableDescriptorBuilder-"><code>Constraints.remove(org.apache.hadoop.hbase.client.TableDescriptorBuilder)</code></a>,
you must re-add any <a href="../../../../../org/apache/hadoop/hbase/constraint/Constraint.html" title="interface in org.apache.hadoop.hbase.constraint"><code>Constraint</code></a> you want on that table.
However, if they are just disabled (see
<a href="../../../../../org/apache/hadoop/hbase/constraint/Constraints.html#disable-org.apache.hadoop.hbase.client.TableDescriptorBuilder-"><code>Constraints.disable(org.apache.hadoop.hbase.client.TableDescriptorBuilder)</code></a>,
all you need to do is enable constraints again, and everything will be turned back on as it was
configured. Individual constraints can also be individually enabled, disabled or removed without
affecting other constraints.
<p/>
By default, constraints are disabled on a table. This means you will not see <i>any</i> slow down
on a table if constraints are not enabled.
<p/>
<h2><a name="concurrency">Concurrency and Atomicity</a></h2> Currently, no attempts at enforcing
correctness in a multi-threaded scenario when modifying a constraint, via
<a href="../../../../../org/apache/hadoop/hbase/constraint/Constraints.html" title="class in org.apache.hadoop.hbase.constraint"><code>Constraints</code></a>, to the the
<a href="../../../../../org/apache/hadoop/hbase/client/TableDescriptorBuilder.html" title="class in org.apache.hadoop.hbase.client"><code>TableDescriptorBuilder</code></a>. This is particularly important
when adding a constraint(s) to the <a href="../../../../../org/apache/hadoop/hbase/client/TableDescriptorBuilder.html" title="class in org.apache.hadoop.hbase.client"><code>TableDescriptorBuilder</code></a>
as it first retrieves the next priority from a custom value set in the descriptor, adds each
constraint (with increasing priority) to the descriptor, and then the next available priority is
re-stored back in the <a href="../../../../../org/apache/hadoop/hbase/client/TableDescriptorBuilder.html" title="class in org.apache.hadoop.hbase.client"><code>TableDescriptorBuilder</code></a>.
<p/>
Locking is recommended around each of Constraints add methods:
<a href="../../../../../org/apache/hadoop/hbase/constraint/Constraints.html#add-org.apache.hadoop.hbase.client.TableDescriptorBuilder-java.lang.Class...-"><code>Constraints.add(org.apache.hadoop.hbase.client.TableDescriptorBuilder, Class...)</code></a>,
<a href="../../../../../org/apache/hadoop/hbase/constraint/Constraints.html#add-org.apache.hadoop.hbase.client.TableDescriptorBuilder-org.apache.hadoop.hbase.util.Pair...-"><code>Constraints.add(org.apache.hadoop.hbase.client.TableDescriptorBuilder, org.apache.hadoop.hbase.util.Pair...)</code></a>,
and
<a href="../../../../../org/apache/hadoop/hbase/constraint/Constraints.html#add-org.apache.hadoop.hbase.client.TableDescriptorBuilder-java.lang.Class-org.apache.hadoop.conf.Configuration-"><code>Constraints.add(org.apache.hadoop.hbase.client.TableDescriptorBuilder, Class, org.apache.hadoop.conf.Configuration)</code></a>.
Any changes on <i>a single TableDescriptor</i> should be serialized, either within a single
thread or via external mechanisms.
<p/>
Note that having a higher priority means that a constraint will run later; e.g. a constraint with
priority 1 will run before a constraint with priority 2.
<p/>
Since Constraints currently are designed to just implement simple checks (e.g. is the value in
the right range), there will be no atomicity conflicts. Even if one of the puts finishes the
constraint first, the single row will not be corrupted and the 'fastest' write will win; the
underlying region takes care of breaking the tie and ensuring that writes get serialized to the
table. So yes, this doesn't ensure that we are going to get specific ordering or even a fully
consistent view of the underlying data.
<p/>
Each constraint should only use local/instance variables, unless doing more advanced usage.
Static variables could cause difficulties when checking concurrent writes to the same region,
leading to either highly locked situations (decreasing through-put) or higher probability of
errors. However, as long as each constraint just uses local variables, each thread interacting
with the constraint will execute correctly and efficiently.
<h2><a name="caveats">Caveats</a></h2> In traditional (SQL) databases, Constraints are often used
to enforce <a href="http://en.wikipedia.org/wiki/Relational_database#Constraints">referential
integrity</a>. However, in HBase, this will likely cause significant overhead and dramatically
decrease the number of <a href="../../../../../org/apache/hadoop/hbase/client/Put.html" title="class in org.apache.hadoop.hbase.client"><code>Puts</code></a>/second possible on a
table. This is because to check the referential integrity when making a
<a href="../../../../../org/apache/hadoop/hbase/client/Put.html" title="class in org.apache.hadoop.hbase.client"><code>Put</code></a>, one must block on a scan for the 'remote' table,
checking for the valid reference. For millions of <a href="../../../../../org/apache/hadoop/hbase/client/Put.html" title="class in org.apache.hadoop.hbase.client"><code>Puts</code></a>
a second, this will breakdown very quickly. There are several options around the blocking
behavior including, but not limited to:
<ul>
<li>Create a 'pre-join' table where the keys are already denormalized</li>
<li>Designing for 'incorrect' references</li>
<li>Using an external enforcement mechanism</li>
</ul>
There are also several general considerations that must be taken into account, when using
Constraints:
<ol>
<li>All changes made via <a href="../../../../../org/apache/hadoop/hbase/constraint/Constraints.html" title="class in org.apache.hadoop.hbase.constraint"><code>Constraints</code></a> will make
modifications to the <a href="../../../../../org/apache/hadoop/hbase/client/TableDescriptor.html" title="interface in org.apache.hadoop.hbase.client"><code>TableDescriptor</code></a> for a given table. As
such, the usual renabling of tables should be used for propagating changes to the table. When at
all possible, Constraints should be added to the table before the table is created.</li>
<li>Constraints are run in the order that they are added to a table. This has implications for
what order constraints should be added to a table.</li>
<li>Whenever new Constraint jars are added to a region server, those region servers need to go
through a rolling restart to make sure that they pick up the new jars and can enable the new
constraints.</li>
<li>There are certain keys that are reserved for the Configuration namespace:
<ul>
<li>_ENABLED - used server-side to determine if a constraint should be run</li>
<li>_PRIORITY - used server-side to determine what order a constraint should be run</li>
</ul>
If these items are set, they will be respected in the constraint configuration, but they are
taken care of by default in when adding constraints to an
<a href="../../../../../org/apache/hadoop/hbase/client/TableDescriptorBuilder.html" title="class in org.apache.hadoop.hbase.client"><code>TableDescriptorBuilder</code></a> via the usual method.</li>
</ol>
<p/>
Under the hood, constraints are implemented as a Coprocessor (see
<a href="../../../../../org/apache/hadoop/hbase/constraint/ConstraintProcessor.html" title="class in org.apache.hadoop.hbase.constraint"><code>ConstraintProcessor</code></a> if you are interested).
<h2><a name="usage">Example usage</a></h2> First, you must define a
<a href="../../../../../org/apache/hadoop/hbase/constraint/Constraint.html" title="interface in org.apache.hadoop.hbase.constraint"><code>Constraint</code></a>. The best way to do this is to extend
<a href="../../../../../org/apache/hadoop/hbase/constraint/BaseConstraint.html" title="class in org.apache.hadoop.hbase.constraint"><code>BaseConstraint</code></a>, which takes care of some of the more
mundane details of using a <a href="../../../../../org/apache/hadoop/hbase/constraint/Constraint.html" title="interface in org.apache.hadoop.hbase.constraint"><code>Constraint</code></a>.
<p/>
Let's look at one possible implementation of a constraint - an IntegerConstraint(there are also
several simple examples in the tests). The IntegerConstraint checks to make sure that the value
is a String-encoded <code>int</code>. It is really simple to implement this kind of constraint,
the only method needs to be implemented is
<a href="../../../../../org/apache/hadoop/hbase/constraint/Constraint.html#check-org.apache.hadoop.hbase.client.Put-"><code>Constraint.check(org.apache.hadoop.hbase.client.Put)</code></a>:
<div style="background-color: #cccccc; padding: 2px"> <blockquote>
<pre>
public class IntegerConstraint extends BaseConstraint {
public void check(Put p) throws ConstraintException {
Map&lt;byte[], List&lt;KeyValue&gt;&gt; familyMap = p.getFamilyMap();
for (List &lt;KeyValue&gt; kvs : familyMap.values()) {
for (KeyValue kv : kvs) {
// just make sure that we can actually pull out an int
// this will automatically throw a NumberFormatException if we try to
// store something that isn't an Integer.
try {
Integer.parseInt(new String(kv.getValue()));
} catch (NumberFormatException e) {
throw new ConstraintException("Value in Put (" + p
+ ") was not a String-encoded integer", e);
} } }
</pre>
</blockquote> </div>
<p/>
Note that all exceptions that you expect to be thrown must be caught and then rethrown as a
<a href="../../../../../org/apache/hadoop/hbase/constraint/ConstraintException.html" title="class in org.apache.hadoop.hbase.constraint"><code>ConstraintException</code></a>. This way, you can be sure that a
<a href="../../../../../org/apache/hadoop/hbase/client/Put.html" title="class in org.apache.hadoop.hbase.client"><code>Put</code></a> fails for an expected reason, rather than for any
reason. For example, an <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/OutOfMemoryError.html?is-external=true" title="class or interface in java.lang"><code>OutOfMemoryError</code></a> is probably indicative of an inherent
problem in the <a href="../../../../../org/apache/hadoop/hbase/constraint/Constraint.html" title="interface in org.apache.hadoop.hbase.constraint"><code>Constraint</code></a>, rather than a failed
<a href="../../../../../org/apache/hadoop/hbase/client/Put.html" title="class in org.apache.hadoop.hbase.client"><code>Put</code></a>.
<p/>
If an unexpected exception is thrown (for example, any kind of uncaught
<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/RuntimeException.html?is-external=true" title="class or interface in java.lang"><code>RuntimeException</code></a>), constraint-checking will be 'unloaded' from the regionserver
where that error occurred. This means no further
<a href="../../../../../org/apache/hadoop/hbase/constraint/Constraint.html" title="interface in org.apache.hadoop.hbase.constraint"><code>Constraints</code></a> will be checked on that server
until it is reloaded. This is done to ensure the system remains as available as possible.
Therefore, be careful when writing your own Constraint.
<p/>
So now that we have a Constraint, we want to add it to a table. It's as easy as:
<div style="background-color: #cccccc; padding: 2px"> <blockquote>
<pre>
TableDescriptor builder = TableDescriptorBuilder.newBuilder(TABLE_NAME);
...
Constraints.add(builder, IntegerConstraint.class);
</pre>
</blockquote></div>
<p/>
Once we added the IntegerConstraint, constraints will be enabled on the table (once it is
created) and we will always check to make sure that the value is an String-encoded integer.
<p/>
However, suppose we also write our own constraint, <code>MyConstraint.java</code>. First, you
need to make sure this class-files are in the classpath (in a jar) on the regionserver where that
constraint will be run (this could require a rolling restart on the region server - see
<a href="#caveats">Caveats</a> above)
<p/>
Suppose that MyConstraint also uses a Configuration (see
<code>Configurable.getConf()</code>). Then adding MyConstraint looks
like this: <div style="background-color: #cccccc; padding: 2px"> <blockquote>
<pre>
TableDescriptor builder = TableDescriptorBuilder.newBuilder(TABLE_NAME);
Configuration conf = new Configuration(false);
...
(add values to the conf)
(modify the table descriptor)
...
Constraints.add(builder, new Pair(MyConstraint.class, conf));
</pre>
</blockquote></div>
<p/>
At this point we added both the IntegerConstraint and MyConstraint to the table, the
IntegerConstraint <i>will be run first</i>, followed by MyConstraint.
<p/>
Suppose we realize that the <code>Configuration</code> for MyConstraint is
actually wrong when it was added to the table. Note, when it is added to the table, it is
<i>not</i> added by reference, but is instead copied into the
<a href="../../../../../org/apache/hadoop/hbase/client/TableDescriptor.html" title="interface in org.apache.hadoop.hbase.client"><code>TableDescriptor</code></a>. Thus, to change the
<code>Configuration</code> we are using for MyConstraint, we need to do this:
<div style="background-color: #cccccc; padding: 2px"> <blockquote>
<pre>
(add/modify the conf)
...
Constraints.setConfiguration(desc, MyConstraint.class, conf);
</pre>
</blockquote></div>
<p/>
This will overwrite the previous configuration for MyConstraint, but <i>not</i> change the order
of the constraint nor if it is enabled/disabled.
<p/>
Note that the same constraint class can be added multiple times to a table without repercussion.
A use case for this is the same constraint working differently based on its configuration.
<p/>
Suppose then we want to disable <i>just</i> MyConstraint. Its as easy as:
<div style="background-color: #cccccc"> <blockquote>
<pre>
Constraints.disable(desc, MyConstraint.class);
</pre>
</blockquote></div>
<p/>
This just turns off MyConstraint, but retains the position and the configuration associated with
MyConstraint. Now, if we want to re-enable the constraint, its just another one-liner:
<div style="background-color: #cccccc"> <blockquote>
<pre>
Constraints.enable(desc, MyConstraint.class);
</pre>
</blockquote></div>
<p/>
Similarly, constraints on the entire table are disabled via:
<div style="background-color: #cccccc"> <blockquote>
<pre>
Constraints.disable(desc);
</pre>
</blockquote></div>
<p/>
Or enabled via: <div style="background-color: #cccccc"> <blockquote>
<pre>
Constraints.enable(desc);
</pre>
</blockquote></div>
<p/>
Lastly, suppose you want to remove MyConstraint from the table, including with position it should
be run at and its configuration. This is similarly simple:
<div style="background-color: #cccccc"> <blockquote>
<pre>
Constraints.remove(desc, MyConstraint.class);
</pre>
</blockquote></div>
<p/>
Also, removing <i>all</i> constraints from a table is similarly simple:
<div style="background-color: #cccccc"> <blockquote>
<pre>
Constraints.remove(desc);
</pre>
</blockquote></div> This will remove all constraints (and associated information) from the table
and turn off the constraint processing.
<p/>
<b>NOTE</b>
<p/>
It is important to note the use above of <div style="background-color: #cccccc"> <blockquote>
<pre>
Configuration conf = new Configuration(false);
</pre>
</blockquote></div> If you just use <code> new Configuration()</code>, then the Configuration
will be loaded with the default properties. While in the simple case, this is not going to be an
issue, it will cause pain down the road. First, these extra properties are going to cause serious
bloat in your <a href="../../../../../org/apache/hadoop/hbase/client/TableDescriptor.html" title="interface in org.apache.hadoop.hbase.client"><code>TableDescriptor</code></a>, meaning you are keeping
around a ton of redundant information. Second, it is going to make examining your table in the
shell, via <code>describe 'table'</code>, a huge pain as you will have to dig through a ton of
irrelevant config values to find the ones you set. In short, just do it the right way.</div>
</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../../../../../overview-summary.html">Overview</a></li>
<li class="navBarCell1Rev">Package</li>
<li>Class</li>
<li><a href="package-use.html">Use</a></li>
<li><a href="package-tree.html">Tree</a></li>
<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
<li><a href="../../../../../index-all.html">Index</a></li>
<li><a href="../../../../../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="../../../../../org/apache/hadoop/hbase/conf/package-summary.html">Prev&nbsp;Package</a></li>
<li><a href="../../../../../org/apache/hadoop/hbase/coordination/package-summary.html">Next&nbsp;Package</a></li>
</ul>
<ul class="navList">
<li><a href="../../../../../index.html?org/apache/hadoop/hbase/constraint/package-summary.html" target="_top">Frames</a></li>
<li><a href="package-summary.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
<p class="legalCopy"><small>Copyright &#169; 2007&#x2013;2021 <a href="https://www.apache.org/">The Apache Software Foundation</a>. All rights reserved.</small></p>
</body>
</html>