292 lines
11 KiB
XML
292 lines
11 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
|
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
|
<chapter id="odm">
|
|
<title>Object-Directory Mapping (ODM)</title>
|
|
|
|
<sect1 id="odm-intro">
|
|
<title>Introduction</title>
|
|
|
|
<para>Relational mapping frameworks like Hibernate and JPA have offered
|
|
developers the ability to use annotations to map database tables to Java
|
|
objects for some time. The Spring Framework LDAP project now offers the
|
|
same ability with respect to directories through the use of the
|
|
<code>org.springframework.ldap.odm</code> package.</para>
|
|
</sect1>
|
|
|
|
<sect1 id="odm-odmmanager">
|
|
<title>OdmManager</title>
|
|
|
|
<para>The
|
|
<code>org.springframework.ldap.odm.OdmManager</code>
|
|
interface, and its implementation, is the central class in the ODM
|
|
package. The <code>OdmManager</code> orchestrates the
|
|
process of reading objects from the directory and mapping the data to
|
|
annotated Java object classes. This interface provides access to the
|
|
underlying directory instance through the following methods:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><code><T> T read(Class<T> clazz, Name
|
|
dn)</code></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><code>void create(Object entry)</code></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><code>void update(Object entry)</code></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><code>void delete(Object entry)</code></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><code><T> List<T> findAll(Class<T> clazz, Name
|
|
base, SearchControls searchControls)</code></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><code><T> List<T> search(Class<T> clazz, Name
|
|
base, String filter, SearchControls searchControls)</code></para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>A reference to an implementation of this interface can be obtained
|
|
through the
|
|
<code>org.springframework.ldap.odm.core.impl.OdmManagerImplFactoryBean</code>.
|
|
A basic configuration of this factory would be as follows:</para>
|
|
|
|
<example>
|
|
<title>Configuring the OdmManager Factory</title>
|
|
<programlisting><![CDATA[
|
|
<beans>
|
|
...
|
|
<bean id="odmManager" class="org.springframework.ldap.odm.core.impl.OdmManagerImplFactoryBean">
|
|
<property name="converterManager" ref="converterManager" />
|
|
<property name="contextSource" ref="contextSource" />
|
|
<property name="managedClasses">
|
|
<set>
|
|
<value>com.example.dao.SimplePerson</value>
|
|
</set>
|
|
</property>
|
|
</bean>
|
|
...
|
|
</beans>
|
|
]]></programlisting>
|
|
</example>
|
|
|
|
<para>The factory requires the list of entity classes to be managed by the
|
|
<code>OdmManager</code> to be explicitly declared. These
|
|
classes should be properly annotated as defined in the next section. The
|
|
<code>converterManager</code> referenced in the above definition
|
|
is described in <xref
|
|
linkend="odm-typeconversion" />.</para>
|
|
</sect1>
|
|
|
|
<sect1 id="odm-annotations">
|
|
<title>Annotations</title>
|
|
|
|
<para>Entity classes managed by the
|
|
<code>OdmManager</code> are required to be annotated
|
|
with the annotations in the
|
|
<code>org.springframework.ldap.odm.annotations</code> package. The
|
|
available annotations are:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><code>@Entry</code> - Class level annotation indicating the
|
|
<code>objectClass</code> definitions to which the entity
|
|
maps.<emphasis> (required)</emphasis></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><code>@Id</code> - Indicates the entity DN; the field declaring
|
|
this attribute must be a derivative of the
|
|
<code>javax.naming.Name</code> class.
|
|
<emphasis>(required)</emphasis></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><code>@Attribute</code> - Indicates the mapping of a directory
|
|
attribute to the object class field.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><code>@Transient</code> - Indicates the field is not persistent
|
|
and should be ignored by the
|
|
<code>OdmManager</code>.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<simpara>The <code>@Entry</code> and <code>@Id</code> attributes are
|
|
required to be declared on managed classes. <code>@Entry</code> is used to
|
|
specify which object classes the entity maps too. All object classes for
|
|
which fields are mapped are required to be declared. Also, in order for a
|
|
directory entry to be considered a match to the managed entity, all object
|
|
classes declared by the directory entry must match be declared by in the
|
|
<code>@Entry</code> annotation. </simpara>
|
|
|
|
<simpara>The <code>@Id</code> annotation is used to map the distinguished
|
|
name of the entry to a field. The field must be an instance of
|
|
<code>javax.naming.Name</code> or a subclass of it.</simpara>
|
|
|
|
<simpara>The <code>@Attribute</code> annotation is used to map object
|
|
class fields to entity fields. <code>@Attribute</code> is required to
|
|
declare the name of the object class property to which the field maps and
|
|
may optionally declare the syntax OID of the LDAP attribute, to guarantee
|
|
exact matching. <code>@Attribute</code> also provides the type declaration
|
|
which allows you to indicate whether the attribute is regarded as binary
|
|
based or string based by the LDAP JNDI provider.</simpara>
|
|
|
|
<simpara>The <code>@Transient</code> annotation is used to indicate the
|
|
field should be ignored by the <code>OdmManager</code>
|
|
and not mapped to an underlying LDAP property.</simpara>
|
|
</sect1>
|
|
|
|
<sect1 id="odm-typeconversion">
|
|
<title>Type Conversion</title>
|
|
|
|
<para>The <code>OdmManager</code> relies on the
|
|
<code>org.springframework.ldap.odm.typeconversion</code> package to
|
|
convert LDAP attributes to Java fields. The main interface in this class
|
|
is the
|
|
<code>org.springframework.ldap.odm.typeconversion.ConverterManager</code>.
|
|
The default <code>ConverterManager</code> implementation
|
|
uses the following algorithm when parsing objects to convert
|
|
fields:<orderedlist>
|
|
<listitem>
|
|
<para>Try to find and use a <code>Converter</code>
|
|
registered for the <code>fromClass</code>,
|
|
<code>syntax</code> and <code>toClass</code> and use
|
|
it.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>If this fails, then if the <code>toClass</code>
|
|
<code><methodname>isAssignableFrom</methodname></code> the
|
|
<code>fromClass</code> then just assign it.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>If this fails try to find and use a
|
|
<code><code>Converter</code></code> registered for
|
|
the <code>fromClass</code> and the
|
|
<code>toClass</code> ignoring the syntax.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>If this fails then throw a
|
|
<exceptionname>ConverterException</exceptionname>.</para>
|
|
</listitem>
|
|
</orderedlist></para>
|
|
|
|
<para>Implementations of the <code>ConverterManager</code>
|
|
interface can be obtained from the
|
|
<code>org.springframework.ldap.odm.typeconversion.impl.ConvertManagerFactoryBean</code>.
|
|
The factory bean requires converter configurations to be declared in the
|
|
bean configuration. </para>
|
|
|
|
<para>The converterConfig property accepts a set of
|
|
<code>ConverterConfig</code> classes, each one defining some
|
|
conversion logic. A converter config is an instance of
|
|
<code>org.springframework.ldap.odm.typeconversion.impl.ConverterManagerFactoryBean.ConverterConfig</code>.
|
|
The config defines a set of source classes, the set of target classes, and
|
|
an implementation of the
|
|
<code>com.springframework.ldap.odm.typeconversion.impl.Converter</code>
|
|
interface which provides the logic to convert from the
|
|
<code>fromClass</code> to the <code>toClass</code>. A
|
|
sample configuration is provided in the following example:</para>
|
|
|
|
<example>
|
|
<title>Configuring the Converter Manager Factory</title>
|
|
<programlisting><![CDATA[
|
|
<bean id="fromStringConverter"
|
|
class="org.springframework.ldap.odm.typeconversion.impl.converters.FromStringConverter" />
|
|
<bean id="toStringConverter"
|
|
class="org.springframework.ldap.odm.typeconversion.impl.converters.ToStringConverter" />
|
|
<bean id="converterManager"
|
|
class="org.springframework.ldap.odm.typeconversion.impl.ConverterManagerFactoryBean">
|
|
<property name="converterConfig">
|
|
<set>
|
|
<bean class="org.springframework.ldap.odm.typeconversion.impl.ConverterManagerFactoryBean$ConverterConfig">
|
|
<property name="fromClasses">
|
|
<set>
|
|
<value>java.lang.String</value>
|
|
</set>
|
|
</property>
|
|
<property name="toClasses">
|
|
<set>
|
|
<value>java.lang.Byte</value>
|
|
<value>java.lang.Short</value>
|
|
<value>java.lang.Integer</value>
|
|
<value>java.lang.Long</value>
|
|
<value>java.lang.Float</value>
|
|
<value>java.lang.Double</value>
|
|
<value>java.lang.Boolean</value>
|
|
</set>
|
|
</property>
|
|
<property name="converter" ref="fromStringConverter" />
|
|
</bean>
|
|
<bean class="org.springframework.ldap.odm.typeconversion.impl.ConverterManagerFactoryBean$ConverterConfig">
|
|
<property name="fromClasses">
|
|
<set>
|
|
<value>java.lang.Byte</value>
|
|
<value>java.lang.Short</value>
|
|
<value>java.lang.Integer</value>
|
|
<value>java.lang.Long</value>
|
|
<value>java.lang.Float</value>
|
|
<value>java.lang.Double</value>
|
|
<value>java.lang.Boolean</value>
|
|
</set>
|
|
</property>
|
|
<property name="toClasses">
|
|
<set>
|
|
<value>java.lang.String</value>
|
|
</set>
|
|
</property>
|
|
<property name="converter" ref="toStringConverter" />
|
|
</bean>
|
|
</set>
|
|
</property>
|
|
</bean>
|
|
]]></programlisting>
|
|
</example>
|
|
</sect1>
|
|
|
|
<sect1 id="odm-execution">
|
|
<title>Execution</title>
|
|
|
|
<para>After all components are configured, directory interaction can be
|
|
acheived through a reference to the
|
|
<code>OdmManager</code> as shown in this example:</para>
|
|
|
|
<example>
|
|
<title>Execution</title>
|
|
<programlisting><![CDATA[
|
|
public class App {
|
|
private static Log log = LogFactory.getLog(App.class);
|
|
private static final SearchControls searchControls =
|
|
new SearchControls(SearchControls.SUBTREE_SCOPE, 100, 10000, null, true, false);
|
|
public static void main( String[] args ) {
|
|
try {
|
|
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
|
|
OdmManager manager = (OdmManager) context.getBean("odmManager");
|
|
List<SimplePerson> people = manager.search(
|
|
SimplePerson.class, new DistinguishedName("dc=example,dc=com"), "uid=*", searchControls);
|
|
log.info("People found: " + people.size());
|
|
for (SimplePerson person : people) {
|
|
log.info( person );
|
|
}
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
]]></programlisting>
|
|
</example>
|
|
</sect1>
|
|
</chapter>
|