You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@turbine.apache.org by Scott Eade <se...@backstagetech.com.au> on 2001/08/30 03:31:56 UTC

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="jon@latchkey.com">Jon S. Stevens</author>
    <author email="dan@chowda.net">Dan A. Bachelder</author>
    <author email="seade@backstagetech.com.au">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.TurbineMapBuilderAdapter
 services.SecurityService.user.class=org.mycompany.newapp.om.NewappUser
 services.SecurityService.userPeer.class=org.mycompany.newapp.om.NewappUserPeer
    ]]></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: turbine-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-user-help@jakarta.apache.org


Re: User Peers and Preparedstatements

Posted by Matthew Inger <ma...@sedonacorp.com>.
Prepared statements do not go very well with connection
pooling, unless you're going to a bulk insert (a whole
lot of records in the same transaction).  The reason is
that the statement is linked to the connection, so if you
insert 1 record, put the connection back, and then insert
another record, there's no guarantee that you will have the
same connection, thus, you cannot use that same prepared
statement.

However, if you know you're going to insert a bunch all
at once (which is where you get your real performance boost),
you can prepare the statement, do all of your inserts, and
then close the statement.

The real performance increase is not going to occur by
preparing a statement that is not executed very often
(such as inserting users, or updating login time), but
when you want to insert hundreds or thousands of records
at once.  I've done some timing of this stuff for work,
using a relatively slow oracle server.  To insert 10000
records which each have 2 varchar(255) fields, and a date
field, i came up with the following:

	inserting one at a time with it's own non-prepared
	statement took approximately 57 seconds

	inserting in blocks of 1000 with a non-prepared statement
	for each block took approximately 52 seconds

	inserting in blocks of 1000 with a prepared statement
	for each block took approximately 42 seconds.


so you can see you get around a 20% performance boost.
I have seen it as high as 75% - 80% depending on the
record structure.


I would extend the Peer class, and make bulkInsert method
which would take in an array of that object, get a connection,
prepare the statement, insert, and then close the statement.
The drawback is that you have to make sure that you
	a) put the right types of objects in the parameters
		(String, Integer, java.sql.Date, java.sql.Timestamp, etc..)
	b) if you change your object model, you'll have to adjust
	   your bulk insert code, since torque won't generate it
	   for you (hm..... an interesting suggestion for future
           torque releases)


On Mon, 2001-09-10 at 10:05, Gareth Coltman wrote:
> Hi,
> 
> I'm trying to performance tune my application, and am finding database performace my biggest problem. I am using Turbine to handle
> all my security, and I notice that the sql produced by the UserPeer (and I assume all SQL generated by Peers) doesn't use and kind
> prepared statement. I understand that the SQL in Peers is being generated on the fly, but requests like SELECT * WHERE USER_ID = ?
> could easily be anticipated!??
> 
> Comments?
> 
> Gareth
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: turbine-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: turbine-user-help@jakarta.apache.org
> 
-- 
Matt Inger (matt.inger@sedonacorp.com)
Sedona Corporation
455 S. Gulph Road, Suite 300
King of Prussia, PA 19406
(484) 679-2213
"Self-respect - the secure feeling that no one,
 as yet, is suspicious." -H.L. Mencken 


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-user-help@jakarta.apache.org


RE: User Peers and Preparedstatements

Posted by Gareth Coltman <ga...@majorband.co.uk>.
Hi,

The problem I am getting is that because the populateUser calls SQL without bind variables, almost half my shared pool (in oracle)
is filling up with these statements.

Can you think of any way around this.

Gareth

>
> Hi,
>
> I'm trying to performance tune my application, and am finding
> database performace my biggest problem. I am using Turbine to handle
> all my security, and I notice that the sql produced by the
> UserPeer (and I assume all SQL generated by Peers) doesn't
> use and kind
> prepared statement. I understand that the SQL in Peers is
> being generated on the fly, but requests like SELECT * WHERE
> USER_ID = ?
> could easily be anticipated!??
>
> Comments?
>
> Gareth
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: turbine-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: turbine-user-help@jakarta.apache.org
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-user-help@jakarta.apache.org


User Peers and Preparedstatements

Posted by Gareth Coltman <ga...@majorband.co.uk>.
Hi,

I'm trying to performance tune my application, and am finding database performace my biggest problem. I am using Turbine to handle
all my security, and I notice that the sql produced by the UserPeer (and I assume all SQL generated by Peers) doesn't use and kind
prepared statement. I understand that the SQL in Peers is being generated on the fly, but requests like SELECT * WHERE USER_ID = ?
could easily be anticipated!??

Comments?

Gareth


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-user-help@jakarta.apache.org


Re: [PATCH] - Re: [HOWTO] Extend TurbineUser with your own class... - New Version for review

Posted by Scott Eade <se...@backstagetech.com.au>.
From: "Dan Bachelder" <ch...@chowda.net>
> I can't commit...

That's Daniel, not Dan :-)



---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-user-help@jakarta.apache.org


Re: [PATCH] - Re: [HOWTO] Extend TurbineUser with your own class... - New Version for review

Posted by Dan Bachelder <ch...@chowda.net>.
I can't commit...

> From: "Daniel Rall" <dl...@finemaltcoding.com>
> > > Are you able to commit the extend-user-howto.xml patch that Dan
> > > posted based on the updates I made?  The patch was attached to the 
> > > previous post in this thread.
> > 
> > Yeah, I'll get to it tomorrow.
> 
> Thanks Daniel.  To complete the full cycle, is it possible for you to
> update the turbine site to use the new doc.
> 
> Thanks,
> 
> Scott
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: turbine-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: turbine-user-help@jakarta.apache.org
> 
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-user-help@jakarta.apache.org


Re: [PATCH] - Re: [HOWTO] Extend TurbineUser with your own class... - New Version for review

Posted by Daniel Rall <dl...@finemaltcoding.com>.
"Scott Eade" <se...@backstagetech.com.au> writes:

> From: "Daniel Rall" <dl...@finemaltcoding.com>
> > > Are you able to commit the extend-user-howto.xml patch that Dan
> > > posted based on the updates I made?  The patch was attached to the 
> > > previous post in this thread.
> > 
> > Yeah, I'll get to it tomorrow.
> 
> Thanks Daniel.  To complete the full cycle, is it possible for you to
> update the turbine site to use the new doc.

I gave that a wack when I checked in, but it was a no go.  For some
reason the build.xml file in jakarta-turbine-site is not producing the
latest output for me.  Someone who is more familiar with the
documentation system will have to step up for that.

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-user-help@jakarta.apache.org


Re: [PATCH] - Re: [HOWTO] Extend TurbineUser with your own class... - New Version for review

Posted by Scott Eade <se...@backstagetech.com.au>.
From: "Daniel Rall" <dl...@finemaltcoding.com>
> > Are you able to commit the extend-user-howto.xml patch that Dan
> > posted based on the updates I made?  The patch was attached to the 
> > previous post in this thread.
> 
> Yeah, I'll get to it tomorrow.

Thanks Daniel.  To complete the full cycle, is it possible for you to
update the turbine site to use the new doc.

Thanks,

Scott


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-user-help@jakarta.apache.org


Re: [PATCH] - Re: [HOWTO] Extend TurbineUser with your own class... - New Version for review

Posted by Daniel Rall <dl...@finemaltcoding.com>.
"Scott Eade" <se...@backstagetech.com.au> writes:

> Are you able to commit the extend-user-howto.xml patch that Dan
> posted based on the updates I made?  The patch was attached to the 
> previous post in this thread.

Yeah, I'll get to it tomorrow.

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-user-help@jakarta.apache.org


Re: [PATCH] - Re: [HOWTO] Extend TurbineUser with your own class... - New Version for review

Posted by Scott Eade <se...@backstagetech.com.au>.
Daniel,

Are you able to commit the extend-user-howto.xml patch that Dan
posted based on the updates I made?  The patch was attached to the 
previous post in this thread.

Thanks,

Scott

----- Original Message ----- 
From: "Dan Bachelder" <ch...@chowda.net>
To: <tu...@jakarta.apache.org>
Sent: Sunday, September 02, 2001 10:51 AM
Subject: [PATCH] - Re: [HOWTO] Extend TurbineUser with your own class... - New Version for review


> Sure thing... this is my first patch ever... so someone might want to be
> extra careful with it :)
> 
> I got the howto i wrote from web CVS and cut the new from the email and then
> did this:
> 
> diff -u extend-user-howto.xml extend_user_howto_new.xml >>
> extend-user-howto-patchfile.txt
> 
> look right to everyone?
> 
> ----- Original Message -----
> From: "Daniel Rall" <dl...@finemaltcoding.com>
> To: <tu...@jakarta.apache.org>
> Sent: Thursday, August 30, 2001 6:16 PM
> Subject: Re: [HOWTO] Extend TurbineUser with your own class... - New Version
> for review
> 
> 
> > "Scott Eade" <se...@backstagetech.com.au> writes:
> >
> > > 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.
> >
> > Please send a unidiff.
> >
> > http://jakarta.apache.org/site/source.html
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: turbine-user-unsubscribe@jakarta.apache.org
> > For additional commands, e-mail: turbine-user-help@jakarta.apache.org
> >
> >
> 


--------------------------------------------------------------------------------


> ---------------------------------------------------------------------
> To unsubscribe, e-mail: turbine-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: turbine-user-help@jakarta.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-user-help@jakarta.apache.org


[PATCH] - Re: [HOWTO] Extend TurbineUser with your own class... - New Version for review

Posted by Dan Bachelder <ch...@chowda.net>.
Sure thing... this is my first patch ever... so someone might want to be
extra careful with it :)

I got the howto i wrote from web CVS and cut the new from the email and then
did this:

diff -u extend-user-howto.xml extend_user_howto_new.xml >>
extend-user-howto-patchfile.txt

look right to everyone?

----- Original Message -----
From: "Daniel Rall" <dl...@finemaltcoding.com>
To: <tu...@jakarta.apache.org>
Sent: Thursday, August 30, 2001 6:16 PM
Subject: Re: [HOWTO] Extend TurbineUser with your own class... - New Version
for review


> "Scott Eade" <se...@backstagetech.com.au> writes:
>
> > 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.
>
> Please send a unidiff.
>
> http://jakarta.apache.org/site/source.html
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: turbine-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: turbine-user-help@jakarta.apache.org
>
>

Re: [HOWTO] Extend TurbineUser with your own class... - New Version for review

Posted by Daniel Rall <dl...@finemaltcoding.com>.
"Scott Eade" <se...@backstagetech.com.au> writes:

> 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.

Please send a unidiff.

http://jakarta.apache.org/site/source.html

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-user-help@jakarta.apache.org


Re: [HOWTO] Extend TurbineUser with your own class... - New Version for review

Posted by Scott Eade <se...@backstagetech.com.au>.
Dan,

Can you do me a big favour and create a patch from my message?

I need to figure out a few things here before I will be able to do this 
myself and I have a project deadline looming.  Don't worry if you 
can't - I will hopefully get some time in about a week to figure things
out.

Thanks in advance.

Scott

----- Original Message ----- 
From: "Dan Bachelder" <ch...@chowda.net>
To: <tu...@jakarta.apache.org>
Sent: Sunday, September 02, 2001 6:06 AM
Subject: Re: [HOWTO] Extend TurbineUser with your own class... - New Version for review


> Much more clear than what I had put together! thanks!
> 



---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-user-help@jakarta.apache.org


Re: [HOWTO] Extend TurbineUser with your own class... - New Version for review

Posted by Dan Bachelder <ch...@chowda.net>.
Much more clear than what I had put together! thanks!

----- Original Message -----
From: "Scott Eade" <se...@backstagetech.com.au>
To: <tu...@jakarta.apache.org>
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="jon@latchkey.com">Jon S. Stevens</author>
>     <author email="dan@chowda.net">Dan A. Bachelder</author>
>     <author email="seade@backstagetech.com.au">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: turbine-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: turbine-user-help@jakarta.apache.org
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-user-help@jakarta.apache.org