I attempted to write some documentation of the Peers model in my frustration. It is still not the greatest. But, if you like it you can take it. I attempted to put a diff in the message here. Dan Diephouse 5c5 < <meta name="GENERATOR" content="Mozilla/4.7 [en] (X11; I; FreeBSD 3.4-STABLE i386) [Netscape]"> --- > <meta name="GENERATOR" content="Mozilla/4.7 [en] (Win98; I) [Netscape]"> 14,15c14,15 < < <p><b><font size=+2>Getting Started with Turbine</font></b> --- > <b><font face="Arial,Helvetica"></font></b> > <p><b><font size=+2>Getting Started with Turbine</font></b><b><font size=+2></font></b> 17,18c17 < <br><font size=-1>$Id: getting_started.html,v 1.11 2000/05/29 20:10:37 < mbryson Exp $</font> --- > <br><font size=-1>$Id: getting_started.html,v 1.11 2000/05/29 20:10:37 mbryson Exp $</font><b></b> 22,26c21,24 < please refer to the <a href="/usr/Project/Turbine/docs/fsd.html">Functional < Specification Document (FSD)</a> as well as the other <a href="/usr/Project/Turbine/docs/index.html">documentation</a> < that is available.The composition of this document will be written from < the perspective of what I would do in order to start a newly functional < system. --- > please refer to the <a href="fsd.html">Functional Specification Document > (FSD)</a> as well as the other <a href="index.html">documentation</a> that > is available.The composition of this document will be written from the > perspective of what I would do in order to start a newly functional system. 28c26 < into my servlet engine. This step is documented in the <a href="/usr/Project/Turbine/docs/install.txt">INSTALL</a> --- > into my servlet engine. This step is documented in the <a href="install.txt">INSTALL</a> 35,37c33,35 < the Module Loaders (<a href="/usr/Project/Turbine/docs/fsd.html">please < refer to the FSD</a>) that load your Turbine classes into the classloader < and make them available to the system to reference. --- > the Module Loaders (<a href="fsd.html">please refer to the FSD</a>) that > load your Turbine classes into the classloader and make them available > to the system to reference. 44,46c42,44 < Again, please refer to the <a href="/usr/Project/Turbine/docs/fsd.html">FSD</a> < for more information about what each module is used for. You can then tell < Turbine to recognize this directory structure by modifying the <i>TurbineResources.properties</i> --- > Again, please refer to the <a href="fsd.html">FSD</a> for more information > about what each module is used for. You can then tell Turbine to recognize > this directory structure by modifying the <i>TurbineResources.properties</i> 70,73c68,70 < <i>/servlets/com/mycompany/modules/screens</i> < directory called "HelloWorld". The code for that file would look something < like this: < <blockquote><tt><font size=+1>package com.mycompany.modules.screens;</font></tt> --- > <i>/servlets/com/mycompany/modules/screens</i> directory called "HelloWorld". > The code for that file would look something like this: > <blockquote><tt><font size=+1>package com.mycompany.modules.screens;</font></tt><tt><font size=+1></font></tt> 79c76 < <br><tt><font size=+1>import org.apache.ecs.html.*;</font></tt> --- > <br><tt><font size=+1>import org.apache.ecs.html.*;</font></tt><tt><font size=+1></font></tt> 88c85 < ("Hello World");</font></tt> --- > ("Hello World");</font></tt><tt><font size=+1></font></tt> 123,126c120,122 < you should employ a <a href="/usr/Project/Turbine/docs/webmacrosite.html">MVC < (Model View Controller)</a> approach that allows you to seperate the content < from the presentation. This is done through integration with a tool such < as <a href="http://sourceforge.net/project/?group_id=794">FreeMarker</a> --- > you should employ a <a href="webmacrosite.html">MVC (Model View Controller)</a> > approach that allows you to seperate the content from the presentation. > This is done through integration with a tool such as <a href="http://sourceforge.net/project/?group_id=794">FreeMarker</a> 129c125 < the Turbine distribution and, for WebMacro, is documented in the <a href="/usr/Project/Turbine/docs/webmacrosite.html">WebMacroSite</a > --- > the Turbine distribution and, for WebMacro, is documented in the <a href="webmacrosite.html">WebMacroSite</a> 213,214c209,210 < <a href="http://java.apache.org/jyve/">Jyve</a> < implements this for more information. --- > <a href="http://java.apache.org/jyve/">Jyve</a> implements this for more > information. 375c371 < <br><tt><font size=+1> Connection connection = db.getConnection();</font></tt> --- > <br><tt><font size=+1> Connection connection = db.getConnection();</font></tt><tt><font size=+1></font></tt> 461,488c457,475 < <p><b><font size=+1>Peers</font></b> < <p>The Peer model allows a set of classes to map the database to objects. < It is made of of three fundamental classes: MapBuilder, BaseObject, and < BasePeer. MapBuilder provides an object representation of your database. < The BaseObject class provides an object representation of the a table in < that database. Finally, the BasePeer class provides an easy method < to access your database through an object oriented view, rather than stmt.executeQuery("SELECT < * FROM DB WHERE COL1 = SOMEVALUE"). It can be said that you use the < BasePeer to get a BaseObject which is an object representation of your < table. The MapBuilder class is a utility class used by these two < classes. < <p><b>The MapBuilder Class</b> < <br>A MapBuilder class can be thought of as two seperate sub-entities. < The first is called a DatabaseMap, and the second part of a MapBuilder < class are the methods used to retrieve the name of the Tables, Columns < and the DatabaseMap. The DatabaseMap is a way to map Tables and Columns < to the MapBuilder Class. You build these relationships by adding < <i>TableMap</i>'s and <i>ColumnMap</i>'s together. Turbine comes < with a MapBuilder that it uses called < <i>TurbineMapBuilder</i>. It < is located in the <i>org.apache.turbine.db.map package</i>. You should < refer to it often as we walkthrough this for more information on how to < build your own classes. Below is a walkthrough of the creation < of a MapBuilder class. < <p>The first method to be added is a <i>doBuild()</i> method. < In that method the first thing you must do is create a DatabaseMap. < Since you are creating your own custom map, you should define it by name. < For example: --- > <p><b>Peers</b> > <p>The Peer model is an interesting beast because it uses a set of classes > to map the database to objects. There is a <i>DatabaseMap</i> class that > is used to build those relationships by adding <i>TableMap</i>'s and <i>ColumnMap</i>'s > together. For instance, a Database has many Table's and the Tables each > have many Columns. To build a <i>DatabaseMap</i> and populate it, you would > write a class that implements the <i>MapBuilder</i> interface. For example, > Turbine comes with a default MapBuilder called <i>TurbineMapBuilder</i>. > It is located in the <i>org.apache.turbine.db.map package</i>. You should > refer to it for more information on how to build your own classes. Here > is a break down of what you need to do to implement it though: > <p>Add a <i>doBuild()</i> method. Within that method, you will need to > create a new <i>DatabaseMap</i> and populate it. That <i>DatabaseMap</i> > must be made available via a <i>getDatabaseMap()</i> method. Within the > <i>doBuild()</i> method, you will create <i>TableMap</i>'s and <i>ColumnMap</i>'s > to build the relationships in your database together. Again, please refer > to the <i>TurbineMapBuilder</i> as an example class. > <p>Here is the code for creating the DatabaseMap. Since you are creating > your own custom map, you should define it by name. For example: 494,501c481,482 < <p>In the <i>doBuild()</i> method you will also need to create a new < <i>DatabaseMap</i> < and populate it. You will create <i>TableMap</i>'s and < <i>ColumnMap</i>'s < to build the relationships in your database together. Again, please refer < to the <i>TurbineMapBuilder</i> as an example class. Here is an example < from <i>TurbineMapBuilder</i> that shows how to create a <i>TableMap</i>, < called <i>RolePermission</i> that is a join table: --- > <p>Here is an example from <i>TurbineMapBuilder</i> that shows how to create > a <i>TableMap</i>, called <i>RolePermission</i> that is a join table: 508,519c489,494 < The second part of the mapbuilder class are methods used for accessing < the names of the tables and columns. At the top of your <i>MapBuilder</i> < class, you should create methods for the various names of tables and columns < that you would like to reference as static variables. Currently, in <i>TurbineMapBuilder</i> < we are using methods for these names, but it is also ok to simply just < use public static final String's instead. Please see the <i>TurbineMapBuilder</i> < class for example. < <p>The last thing that must be done is create a getDatabaseMap() method. < This method will return the DatabaseMap that was created in the <i>doBuild()</i> < method. < <p><b>The BaseObject Class</b> < <br>Once you have created your <i>MapBuilder</i> created, you can start --- > At the top of your <i>MapBuilder</i> class, you should create methods for > the various names of tables and columns that you would like to reference > as static variables. Currently, in <i>TurbineMapBuilder</i> we are using > methods for these names, but it is also ok to simply just use public static > final String's instead. > <p>Once you have created your <i>MapBuilder</i> created, you can start 522,527c497,499 < Within these classes, you should define methods to access what the table < represents. In most cases, you should create these classes with a < 1 to 1 relationship with the name of the Table that you are mapping. This < will help avoid confusion in the future. For examples of these objects, < you should look at the files in the <i>org.apache.turbine.om.user</i> and < <i>org.apache.turbine.om.security</i>. --- > Within these classes, you should define the specifics of what that Table > represents. For examples of these objects, you can look at the files in > the <i>org.apache.turbine.om.user</i> and <i>org.apache.turbine.om.security</i>. 529,532c501,504 < classes are excellent examples. Please look at these examples < to understand this class. < <p><b>The BasePeer Class</b> < <br>Next, you should create your Peer objects. These are the core classes --- > classes are excellent examples. In most cases, you should create these > classes with a 1 to 1 relationship with the name of the Table that you > are mapping. This will help avoid confusion in the future. > <p>Next, you should create your Peer objects. This is the core classes 555c527 < = (MyMapBuilder) getMapBuilder("com.mycompany.db.util.map.CustomMap");</font></tt></blockquote> --- > = (MyMapBuilder) getMapBuilder("CustomMap");</font></tt></blockquote> 573,599c545,546 < In the next section the beauty of this will be revealed! < <p><b>Making sense of the above</b> < <br>Now that everyone knows about the different classes we can put them < together! Lets pretend we have a Turbine screen where we wish to < retrieve an object from the database. First you must create < a MapBuilder, a BaseObject, and a BasePeer class for your database. < <p>Once we have all of these together we can make our database into < an object like so: Then in our turbine screen we would do the following < to retrieve the data: < <p><tt><font size=+1> Criteria crit = new Criteria("DBNameHere");</font></tt> < <br><tt><font size=+1> //If you don't do this it defaults < to TurbineMapBuilder:</font></tt> < <br><tt><font size=+1> Criteria.setMapName ("CustomMap");</font></tt> < <br><tt><font size=+1> Criteria.add (PermissionPeer.PERMISSION_ID, < 1);</font></tt> < <br><tt><font size=+1> Vector cat = new PermissionPeer().doSelect(crit);</font></tt> < <br><tt><font size=+1> Permission c = (Permission) cat.firstElement();</font></tt> < <br><tt><font size=+1> body.addElement(c.getName());</font></tt> < <p>The effect of this code would be to create and execute an SQL statement < that looked like this: < <blockquote><tt><font size=+1>select * from table where PERMISSIONID = < 1;</font></tt></blockquote> < Now we have a Permission object from the database! We can modify < it with Permission.setName() and then throw it back into the database with < a different method from Permission peer. < <p>For a another example we could write the code like this: < <blockquote><tt><font size=+1>Criteria crit = new Criteria("DBNameHere");</font></tt> --- > This would allow you to easily write code that looks something like this: > <blockquote><tt><font size=+1>Criteria crit = new Criteria();</font></tt> 606,621c553,567 < Hopefully you can appreciate the power of this abstraction. Once again, < it is ABSOLUTELY VITAL you refer to to the turbine source code.<b></b> < <p><b>IDBroker</b> < <br>One other neat feature that has been recently added to Turbine is the < <i>IDBroker</i> < class. This class implements a large part of the OID model that is described < in <a href="http://www.ambysoft.com/onlineWritings.html">Scott Ambler's < white papers</a>. Essentially, the purpose of this class is to abstract < out the fact that different database implementations do not support a standard < method of retrieving the next ID number when doing an INSERT. For example, < in MySQL you would use the AUTOINSERT addition to the column definition. < In Oracle, you would use a sequence. With this class, you simply define < a primary key to be an integer (or number) and then use this class to get < a set of ID numbers that you can use for inserts. The best part is that < if you use the Peer model, the BasePeer class will know to use this methodology < for you without you having to worry about a thing. --- > Hopefully you can appreciate the power of this abstraction. Again, please > refer to the example classes that come with Turbine for more examples of > how to use this code. > <p>One other neat feature that has been recently added to Turbine is the > <i>IDBroker</i> class. This class implements a large part of the OID model > that is described in <a href="http://www.ambysoft.com/onlineWritings.html">Scott > Ambler's white papers</a>. Essentially, the purpose of this class is to > abstract out the fact that different database implementations do not support > a standard method of retrieving the next ID number when doing an INSERT. > For example, in MySQL you would use the AUTOINSERT addition to the column > definition. In Oracle, you would use a sequence. With this class, you simply > define a primary key to be an integer (or number) and then use this class > to get a set of ID numbers that you can use for inserts. The best part > is that if you use the Peer model, the BasePeer class will know to use > this methodology for you without you having to worry about a thing. 714,731c660,677 < <blockquote><tt>GlobalCacheService gs = null;</tt> < <br><tt>try</tt> < <br><tt>{</tt> < <br><tt> // Look for the item in the cache.</tt> < <br><tt> // If it doesn't exist or the item is stale, < the cache will throw an exception.</tt> < <br><tt> gs = (GlobalCacheService)TurbineServices.getInstance().getService(GlobalCacheService.GLOBALCACHE);</tt> < <br><tt> CachedObject obj = gs.getObject("cached_object");</tt> < <br><tt> data.setMessage( data.getScreen() + " < Got " + obj.getContents().toString() + " from global cache!" );</tt> < <br><tt>}</tt> < <br><tt>catch(ObjectExpiredException gone)</tt> < <br><tt>{</tt> < <br><tt> // Add the item to the cache.</tt> < <br><tt> gs.addObject("cached_object", new CachedObject("in_the_cache",5000));</tt> < <br><tt> data.setMessage( data.getScreen() + " < Refreshed/or added new item to the cache! Expires in 5 seconds" );</tt> < <br><tt>}</tt></blockquote> --- > <blockquote><tt>GlobalCacheService gs = null;<br> > try<br> > {<br> > // Look for the item in the cache.<br> > // If it doesn't exist or the item is stale, the cache > will throw an exception.<br> > gs = (GlobalCacheService)TurbineServices.getInstance().getService(GlobalCacheService.GLOBALCACHE);<br> > CachedObject obj = gs.getObject("cached_object");<br> > data.setMessage( data.getScreen() + " Got " + > obj.getContents().toString() + " from global cache!" );<br> > }<br> > catch(ObjectExpiredException gone)<br> > {<br> > // Add the item to the cache.<br> > gs.addObject("cached_object", new CachedObject("in_the_cache",5000));<br> > data.setMessage( data.getScreen() + " Refreshed/or > added new item to the cache! Expires in 5 seconds" );<br> > }</tt></blockquote> 789,791c735,736 < Configure Turbine to user the WebMacroSite Service. The Scheduler interface < is implemented using WebMacro (see WebMacroSite Service below). You don't < however, need to use WebMacro to use the Scheduler.</li> --- > Configure Turbine to user the WebMacroSite Service. The Scheduler interface is implemented > using WebMacro (see WebMacroSite Service below). You don't however, need to use WebMacro to use the Scheduler. 793,794c738,739 < <li> < Once the Scheduler UI is configured, Go to http://myurl/Turbine and login.</li> --- > <li> > Once the Scheduler UI is configured, Go to http://myurl/Turbine and login. 797,798c742 < Click on Scheduler, then click on Add Job.</li> < --- > Click on Scheduler, then click on Add Job. 800,803c744,747 < Add the Task <i>DefaultScheduledJob</i> via the Scheduled Jobs interface. < Create a couple of entries for this class with different times. For example, < set the minutes to 5 and leave the other time fields set to -1. This means < the Job will execute every 5 minutes.</li> --- > Add the Task <i>DefaultScheduledJob</i> > via the Scheduled Jobs interface. Create a couple of entries for this class > with different times. For example, set the minutes to 5 and leave the other > time fields set to -1. This means the Job will execute every 5 minutes.</li> 828,835c772,777 < <b>WebMacroSite Service</b> < <p>The WebMacroSite service is a Turbine Service that allows you to call < <a href="http://www.webmacro.org">WebMacro</a> < files from within a Turbine screen. It's a great way to separate the presentation < of your information from the business logic. For information on developing < with WebMacro, please see <a href="/usr/Project/Turbine/docs/webmacrosite.html">WebMacroSite < document</a>. If you have specific questions, we are happy to answer them < on the mailing list. --- > <b>WebMacroSite Service</b> > <p>The WebMacroSite service is a Turbine > Service that allows you to call <a href="http://www.webmacro.org">WebMacro</a> files from within a Turbine screen. > It's a great way to separate the presentation of your information from > the business logic. For information on developing with WebMacro, please see <a href="webmacrosite.html">WebMacroSite document</a>. > If you have specific questions, we are happy to answer them on the mailing list. 838,847c780,786 < <li> < First set the following properties in TurbineResources.properties located < in the Turbine/conf directory.</li> < < <br>* default.template=/default.wm < <br>* template.homepage=/index.wm < <br>* screen.login=WebMacroSiteScreen < <br>* screen.homepage=WebMacroSiteScreen < <br>* default.page=WebMacroSitePage < <br>* action.sessionvalidator=sessionvalidator.WebMacroSiteSessionValidator --- > <li>First set the following properties in TurbineResources.properties located in the Turbine/conf directory.<br> > * default.template=/default.wm<br> > * template.homepage=/index.wm<br> > * screen.login=WebMacroSiteScreen<br> ------------------------------------------------------------ To subscribe: [EMAIL PROTECTED] To unsubscribe: [EMAIL PROTECTED] Problems?: [EMAIL PROTECTED]