Much more clear than what I had put together! thanks!
----- Original Message -----
From: "Scott Eade" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Wednesday, August 29, 2001 9:31 PM
Subject: Re: [HOWTO] Extend TurbineUser with your own class... - New Version
for review
> Below is my completely revamped XDOC version of extend-user-howto.xml.
>
> Can those of you that are interested please have a look at this and let me
know
> if you agree with my approach which is a combination of the approaches put
> forward by a number of different people on this list.
>
> The approach documented works, but I am not going to be too surprised if
> there are different opinions as to the best way of doing this. It should
be noted
> however that this is the only way I have been able to get this working
without
> risking the loss of code when regenerating the OM layer code.
>
> I'll try out any suggestions and update the document before requesting a
> commit.
>
> Cheers,
>
> Scott
>
> ------------------- extend-user-howto.xml -----------------------
>
> <?xml version="1.0"?>
> <document>
> <properties>
> <title>Extend User Howto</title>
> <author email="[EMAIL PROTECTED]">Jon S. Stevens</author>
> <author email="[EMAIL PROTECTED]">Dan A. Bachelder</author>
> <author email="[EMAIL PROTECTED]">Scott B. Eade</author>
> </properties>
> <body>
> <section name="Extend User">
> <p>
> This is a not quite quick-and-dirty HOWTO on extending the
TurbineUser and
> its functionality. The motivating factors for extending TurbineUser
are:
> <ol>
> <li>
> to be able to make use of TURBINE_USER.USER_ID as a foreign key
in
> application tables; and
> </li>
> <li>
> to be able to represent additional user attributes by adding
columns
> to TURBINE_USER.
> </li>
> </ol>
> </p>
> <p>
> The example herein uses TDK 2.1 and the TDK sample application
Newapp.
> To illustrate solutions to both of out motivators we will:
> <ol>
> <li>
> Add a CREATE_USER_ID column to the RDF application table.
> </li>
> <li>
> Add a TITLE column to TURBINE_USER.
> </li>
> </ol>
> </p>
> <p>
> First we update the schema for the project (in this case
> newapp-schema.xml) to include an alias definition of TurbineUser
(which
> will NOT create a new table) as well as the desired foreign key
> references. Note how the TurbineUser definition refers to a pair of
> adapter classes (that we will create shortly) and how it is only
> necessary to define the columns we are referring to as foreign keys
> elsewhere in the application database. Note also the addition of
> CREATE_USER_ID as a foreign key in the RDF table.
> </p>
> <source><![CDATA[
> <table name="NEWAPP_USER" javaName="NewappUser" alias="TurbineUser"
> baseClass="org.mycompany.newapp.om.TurbineUserAdapter"
> basePeer="org.mycompany.newapp.om.TurbineUserPeerAdapter">
> <!-- Unique identifier -->
> <column name="USER_ID" primaryKey="true" required="true"
type="integer"/>
> </table>
>
> <table name="RDF" idMethod="autoincrement">
> <column name="RDF_ID" required="true" autoIncrement="true"
> primaryKey="true" type="INTEGER"/>
> <column name="TITLE" size="255" type="VARCHAR"/>
> <column name="BODY" size="255" type="VARCHAR"/>
> <column name="URL" size="255" type="VARCHAR"/>
> <column name="AUTHOR" size="255" type="VARCHAR"/>
> <column name="DEPT" size="255" type="VARCHAR"/>
> <column name="CREATE_USER_ID" required="true" type="INTEGER"/>
> <foreign-key foreignTable="NEWAPP_USER">
> <reference local="CREATE_USER_ID" foreign="USER_ID"/>
> </foreign-key>
> </table>
> ]]></source>
> <p>
> The columns we want to add to TurbineUser must be defined in
> turbine-schema.xml thus:
> </p>
> <source><![CDATA[
> <table name="TURBINE_USER" idMethod="idbroker">
> <column name="USER_ID" required="true" primaryKey="true"
type="INTEGER"/>
> <column name="LOGIN_NAME" required="true" size="32" type="VARCHAR"/>
> <column name="PASSWORD_VALUE" required="true" size="32"
type="VARCHAR"/>
> <column name="FIRST_NAME" required="true" size="99" type="VARCHAR"/>
> <column name="LAST_NAME" required="true" size="99" type="VARCHAR"/>
> <column name="EMAIL" size="99" type="VARCHAR"/>
> <column name="CONFIRM_VALUE" size="99" type="VARCHAR"/>
> <column name="TITLE" size="99" type="VARCHAR"/> <!-- New column -->
> <column name="MODIFIED" type="TIMESTAMP"/>
> <column name="CREATED" type="TIMESTAMP"/>
> <column name="LAST_LOGIN" type="TIMESTAMP"/>
> <column name="OBJECTDATA" type="VARBINARY"/>
> <unique>
> <unique-column name="LOGIN_NAME"/>
> </unique>
> </table>
> ]]></source>
> <p>
> Before we create the adapter classes referred to above we will first
> extend TurbineMapBuilder in order to tell Turbine about the
additional
> columns we are adding to TurbineUser. Note that you can actually
omit
> this step and not even define database columns for the additional
> attributes you want to add if you don't care to have easy external
access
> to the data. If you do this the data for the additional attributes
will
> be written to TURBINE_USER.OBJECTDATA along with any other data
added to
> the the perm hashtable (this is a way cool feature, you should also
look
> into the temp hashtable if you like this).
> </p>
> <source><![CDATA[
> package org.mycompany.newapp.util.db.map;
>
> import java.util.Date;
>
> import org.apache.turbine.services.db.TurbineDB;
> import org.apache.turbine.util.db.map.TableMap;
> import org.apache.turbine.util.db.map.TurbineMapBuilder;
>
> public class TurbineMapBuilderAdapter extends TurbineMapBuilder
> {
> public String getTitle()
> {
> return "TITLE";
> }
>
> public String getUser_Title()
> {
> return getTableUser() + '.' + getTitle();
> }
>
> public void doBuild()
> throws java.lang.Exception
> {
> super.doBuild();
>
> // Make some objects.
> String string = new String("");
> Integer integer = new Integer(0);
> java.util.Date date = new Date();
>
> // Add extra User columns.
> TableMap tMap =
TurbineDB.getDatabaseMap().getTable(getTableUser());
> tMap.addColumn(getTitle(), string);
> }
> }
> ]]></source>
> <p>
> Now we will implement the pair of adapters we referred to in our
schema.
> First we implement TurbineUserAdapter to provide access to the
primary key
> as well as the column we are adding to TurbineUser. If you are
going to
> use OBJECTDATA (and not define new columns in the database) you can
still
> add accessor methods here for convenience if you like, alternatively
you
> can just use setPerm() directly.
> </p>
> <source><![CDATA[
> package org.mycompany.newapp.om;
>
> import org.apache.turbine.om.security.TurbineUser;
> import org.apache.turbine.om.NumberKey;
>
> public class TurbineUserAdapter extends TurbineUser
> {
> public static final String TITLE = "TITLE";
>
> public NumberKey getUserId()
> {
> return (NumberKey) getPrimaryKey();
> }
>
> public void setTitle(String title)
> {
> setPerm(TITLE, title);
> }
>
> public String getTitle()
> {
> String tmp = null;
> try
> {
> tmp = (String) getPerm(TITLE);
> if ( tmp.length() == 0 )
> tmp = null;
> }
> catch ( Exception e )
> {
> }
> return tmp;
> }
> }
> ]]></source>
> <p>
> Next comes TurbineUserPeerAdapter to which we also add details of
the new
> database columns (the body will be empty if you choose to use
> OBJECTDATA).
> </p>
> <source><![CDATA[
> package org.mycompany.newapp.om;
>
> import java.util.Vector;
>
> import org.apache.turbine.om.security.peer.TurbineUserPeer;
> import org.mycompany.newapp.util.db.map.TurbineMapBuilderAdapter;
>
> public class TurbineUserPeerAdapter extends TurbineUserPeer
> {
> private static final TurbineMapBuilderAdapter mapBuilder =
> (TurbineMapBuilderAdapter) getMapBuilder();
>
> public static final String TITLE = mapBuilder.getUser_Title();
> }
> ]]></source>
> <p>
> We can now use "ant project-om" to generate our OM layer using the
adapter
> classes we defined above. Note that "ant init" (WARNING: THE init
TARGET
> WILL DELETE ALL DATA IN YOUR DATABASE), or any other target that
triggers
> a compile of the OM layer will result in a compile error of BaseRdf
due to
> the fact that NewappUserPeer does not implement a retrieveByPK()
method.
> </p>
> <p>
> We can now use "ant project-om" to generate our OM layer using the
adapter
> classes we defined above. Note that "ant init" (WARNING: THE init
TARGET
> WILL DELETE ALL DATA IN YOUR DATABASE), or any other target that
triggers
> a compile of the OM layer will result in a compile error of BaseRdf
due to
> the fact that NewappUserPeer does not implement a retrieveByPK()
method.
> </p>
> <p>
> So lets implement retrieveByPK() so that everything can compile.
This
> needs to be implemented in NewappUserPeer which was generated by
torque
> when we executed project-om above (but it won't be deleted should we
need
> to regenerate the OM layer at some stage in the future - like in
about 2
> minutes).
> </p>
> <source><![CDATA[
> package org.mycompany.newapp.om;
>
> import java.util.*;
>
> import com.workingdogs.village.*;
>
> import org.apache.turbine.om.peer.*;
> import org.apache.turbine.util.*;
> import org.apache.turbine.util.db.*;
> import org.apache.turbine.util.db.map.*;
> import org.apache.turbine.util.db.pool.DBConnection;
> import org.apache.turbine.om.ObjectKey;
> import org.apache.turbine.services.db.TurbineDB;
>
> import org.mycompany.newapp.om.map.*;
>
> public class NewappUserPeer
> extends org.mycompany.newapp.om.BaseNewappUserPeer
> {
> public static NewappUser retrieveByPK(ObjectKey pk)
> throws Exception
> {
> DBConnection db = null;
> NewappUser retVal = null;
>
> try
> {
> db = TurbineDB.getConnection(getMapBuilder()
> .getDatabaseMap().getName());
> retVal = retrieveByPK(pk, db);
> }
> finally
> {
> if (db != null)
> {
> TurbineDB.releaseConnection(db);
> }
> }
> return(retVal);
> }
>
> public static NewappUser retrieveByPK( ObjectKey pk, DBConnection
dbcon )
> throws Exception
> {
> Criteria criteria = new Criteria();
> criteria.add( USER_ID, pk );
> Vector v = doSelect(criteria, dbcon);
> if ( v.size() != 1)
> {
> throw new Exception("Failed to select one and only one row.");
> }
> else
> {
> return (NewappUser)v.firstElement();
> }
> }
> }
> ]]></source>
> <p>
> Now we can now use "ant init" to generate the rest of the things it
> generates - this will include the regenreation of the OM layer, the
> generation of the sql to create the database tables and the actual
> execution of this sql to recreate the database tables to now include
any
> additional columns we have defined (<b>AS A CONSEQUENCE ALL DATA IN
THE
> DATABASE WILL BE DESTROYED).</b>
> </p>
> <p>
> With any luck everything will compile okay and we are only a small
step
> away from being able to use the new OM layer. The last step is to
tell
> Turbine about the new classes we are using for Users and the new
> MapBuilder. To do this we need to update the following entries in
> TurbineResources.properties:
> </p>
> <source><![CDATA[
>
database.maps.builder=org.mycompany.newapp.util.db.map.TurbineMapBuilderAdap
ter
> services.SecurityService.user.class=org.mycompany.newapp.om.NewappUser
>
services.SecurityService.userPeer.class=org.mycompany.newapp.om.NewappUserPe
er
> ]]></source>
> <p>
> That is basically it. We can now modify our application to utilise
the
> new columns via the methods defined in the OM objects we have
modified.
> Note that in order to access the new methods in NewappUser we need
to cast
> from TurbineUser thus:
> </p>
> <source><![CDATA[
> NewappUser user = (NewappUser) data.getUser();
> ]]></source>
> <p>
> Extending TurbineUser should be relatively straightforward with the
help
> of this information.
> </p>
> <p>
> Enjoy.
> </p>
> </section>
> </body>
> </document>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]