This guide covers the use of the OdbResource components with
Tomcat.
Download and Install
- Download the latest binary release from the OdbResource release page on Github. Or download
the source and build the package phase with Maven.
- Unzip the file odbresource-[version number]-bin.zip
in the lib directory of Apache Tomcat.
Configuration
There are three components that must be configured at either the
context or server level. (context.xml or server.xml) They are OServerObjectFactory,
OPDPFObjectFactory and OdbRealm.
OServerObjectFactory
This resource is only declared when are running OrientDB embedded.
It is never referenced directly from your application but must
referenced by the server attribute in the resource
declaration for OPDPFObjectFactory. OPDPFObjectFactory will then
look up the OServerObjectFactory resource which will start the
embedded OrientDB server.
OServerObjectFactory resource declaration:
<Resource
auth="Container"
closeMethod="shutdown"
configFile="/mnt/share/orientdb-community-2.1.9/config/orientdb-server-config.xml"
factory="com.ashtonit.odb.jndi.OServerObjectFactory"
name="oserver"
singleton="true"
type="com.orientechnologies.orient.server.OServer"
/>
The only attribute in the above element that is not described in
the Tomcat configuration guide is configFile. The
value of this attribute is the name of the configuration file for
the OrientDB server. Refer to the OrientDB manual when editing
this.
OPDPFObjectFactory
The OPDPFObjectFactory class must be configured as a JNDI
Resource in Tomcat. This must be done in either server.xml or the
context.xml file for the web application.
Putting the configuration in server.xml is generally more
appropriate. When running the embedded server, the OServer instance
runs as a singleton anyway so the configuration is effectively
global wherever you put it. Two different configurations in
different context.xml files would result in undefined behaviour.
Most likely the first application to be loaded would override any
others.
The Tomcat guide on resource configuration is here.
Important things to note for OdbResource configuration are:
- The auth attribute must have a value of "Container"
- The capacity attribute sets the maximum number of
connections available
- The closeMethod attribute must have a value of "close"
- The factory attribute must have a value of
"com.ashtonit.odb.jndi.OPDPFObjectFactory"
- The type attribute must have a value of
"com.orientechnologies.orient.core.db.OPartitionedDatabasePoolFactory"
- The server attribute must be present only if you are
running OrientDB embedded, in which case the value must match the
value of the name attribute for the OServer resource declaration
- The singleton attribute must have a value of true, to
ensure that the close method is run (In fact the factory remains a
singleton regardless of this attribute.)
OPDPFObjectFactory resource declaration:
<Resource
auth="Container"
capacity="100"
closeMethod="close"
factory="com.ashtonit.odb.jndi.OPDPFObjectFactory"
name="opdpfactory"
server="oserver"
singleton="true"
type="com.orientechnologies.orient.core.db.OPartitionedDatabasePoolFactory"
/>
The only attributes in the above element that are not described in
the Tomcat configuration guide are capacity and server.
The server attribute must be present only if you
want to run an embedded OrientDB server. The value must match the
value of the name attribute for the OServer
resource declaration.
Finally, to make the resource available to a given web application
you also must add it as a Resource Link in the web
app's context.xml:.
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<ResourceLink global="opdpfactory" name="opdpfactory"
type="com.orientechnologies.orient.core.db.OPartitionedDatabasePoolFactory">
</ResourceLink>
</Context>
The Tomcat guide on JNDI resource configuration is
here.
OdbRealm
This is a fairly simple and restricted authentication Realm for
Tomcat. It only supports one form of authentication, the basic
username/password method. Attempting to use any other method will
result in an UnsupportedOperationException.
The Tomcat guide on realm configuration is here.
See the API documentation for OdbRealm for more
information on this specific implementation. Important things to
note for OdbRealm configuration are:
- The className attribute must have a value of
"com.ashtonit.odb.realm.OdbRealm"
- The value of the dbUser attribute must be the name of a
user with read access to the OUser class in the OrientDB database.
The "admin" user can be used for this for development and testing
purposes
- The dbResource attribute is optional:
- If present, the OdbRealm pool will be obtained from the
OPartitionedDatabasePoolFactory resource. The value must match
the value of the "name" attribute in the OdbResource
configuration
- If not present, a new pool with the default capacity
will be instantiated by the realm
- The value of the dbUrl attribute must be a valid OrientDB
URI
- The value of the query attribute must be an OSQL query
string that takes one parameter (a user identifier) and returns
the password hash and roles
<Realm
className="com.ashtonit.odb.realm.OdbRealm"
dbPass="admin"
dbResource="opdpfactory"
dbUrl="plocal:/opt/odb/mygraphdb"
dbUser="admin"
query="SELECT password, roles.name AS roles FROM OUser WHERE status = 'ACTIVE' AND name = ?"
/>
OdbRealm was originally written to authenticate only against the
built-in
OUser
and
ORole
classes but the authentication is now configurable by a query.
It takes an OSQL query string as a attribute named
query
which must return the password hash and the roles for a user.
The query must:
- Take one parameter (the user name or identifier)
- Return the password hash as a String for the user with a
parameter name of, "password"
- Return the role names for the user as a List of Strings
with a parameter name of, "roles"
The password is checked using the method OSecurityManager.checkPassword(String,
String). It checks for three different types of password hashes by
looking at the prefix of the string. They are:
- SHA-256 (A string prefix of
{SHA-256}-
)
- PBKDF2WithHmacSHA1 (A string prefix of
{PBKDF2WithHmacSHA1}-
)
- PBKDF2WithHmacSHA256 (A string prefix of
{PBKDF2WithHmacSHA256}-
)
The simplest way to create a password hash in the correct format is
to use the method OUser.encryptPassword(String).
The Principal implementation used by OdbRealm is OdbPrincipal. If you want to look up an
OrientDB pool factory directly from a JNDI context in your web
application you can cast the principal to OdbPrincipal and then
obtain the OrientDB URL as well as the username and password. See
the servlet example just below.
Declare Dependency
OdbResource is available as
a dependency from the Maven Central Repository.
Declare it with a scope of provided in your web application. The
library itself must be available to the container at start up. An example is given for Maven:
<dependency>
<groupId>com.ashtonit</groupId>
<artifactId>odbresource</artifactId>
<version>[2.2,2.3)</version>
<scope>provided</scope>
</dependency>
Here we have a simple example showing how to look up the
database pool factory in the JNDI context, obtain and use an
OrientGraph instance and release it again.
A Servlet Example
Here we have a simple example showing how to look up the
database pool factory in the JNDI context, obtain and use an
OrientGraph instance and release it again.
NOTE: The example given below pulls the username and password
from the principal. This only makes sense when you are
authenticating agains the built-in OUser and ORole classes. For any
other data model you will need the username and password of a
database user configured statically.
public class MyServlet extends HttpServlet {
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
OPartitionedDatabasePoolFactory factory = (OPartitionedDatabasePoolFactory) envCtx.lookup("opdpfactory");
OdbPrincipal principal = (OdbPrincipal) httpRequest.getUserPrincipal();
// Get the username and the password from the principal only if
// you are authenticating an actual database user, i.e. against
// the OUser and ORole classes. If you are authenticating against
// your own classes you will need a username and password for an
// actual database user. Add these using some kind of static
// configuration - i.e. Spring, from your web.xml, etc.
OPartitionedDatabasePool pool = factory.get(principal.getDbUrl(),
principal.getName(),
principal.getPassword());
OrientGraph graph = null;
try {
graph = new OrientGraph(pool.acquire());
OrientVertex vertex = graph.getVertex("myVertexKey");
out.println("<html>");
out.println("<body>");
out.println("<h1>");
out.println(vertex.toString());
out.println("</h1>");
out.println("</body>");
out.println("</html>");
} finally {
if (graph != null && !graph.isClosed()) {
graph.shutdown();
}
}
}
}
You may notice that the database URI is obtained from the
principal. This allows multiple databases, each managed by a
different realm. The OdbResource configuration defines the server,
not the database.