3160 |
05 Mar 07 |
martin |
1 |
<?xml version="1.0" encoding="UTF-8"?> |
3160 |
05 Mar 07 |
martin |
2 |
<!DOCTYPE chapter PUBLIC |
3160 |
05 Mar 07 |
martin |
3 |
"-//Dawid Weiss//DTD DocBook V3.1-Based Extension for XML and graphics inclusion//EN" |
3192 |
13 Mar 07 |
martin |
4 |
"../../../../lib/docbook/preprocess/dweiss-docbook-extensions.dtd"> |
3160 |
05 Mar 07 |
martin |
5 |
<!-- |
3192 |
13 Mar 07 |
martin |
$Id$ |
3160 |
05 Mar 07 |
martin |
7 |
|
3675 |
16 Aug 07 |
jari |
Copyright (C) 2007 Nicklas Nordborg, Martin Svensson |
3160 |
05 Mar 07 |
martin |
9 |
|
3160 |
05 Mar 07 |
martin |
This file is part of BASE - BioArray Software Environment. |
3160 |
05 Mar 07 |
martin |
Available at http://base.thep.lu.se/ |
3160 |
05 Mar 07 |
martin |
12 |
|
3160 |
05 Mar 07 |
martin |
BASE is free software; you can redistribute it and/or |
3160 |
05 Mar 07 |
martin |
modify it under the terms of the GNU General Public License |
4477 |
05 Sep 08 |
jari |
as published by the Free Software Foundation; either version 3 |
3160 |
05 Mar 07 |
martin |
of the License, or (at your option) any later version. |
3160 |
05 Mar 07 |
martin |
17 |
|
3160 |
05 Mar 07 |
martin |
BASE is distributed in the hope that it will be useful, |
3160 |
05 Mar 07 |
martin |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
3160 |
05 Mar 07 |
martin |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3160 |
05 Mar 07 |
martin |
GNU General Public License for more details. |
3160 |
05 Mar 07 |
martin |
22 |
|
3160 |
05 Mar 07 |
martin |
You should have received a copy of the GNU General Public License |
4509 |
11 Sep 08 |
jari |
along with BASE. If not, see <http://www.gnu.org/licenses/>. |
3160 |
05 Mar 07 |
martin |
25 |
--> |
3160 |
05 Mar 07 |
martin |
26 |
|
5781 |
04 Oct 11 |
nicklas |
27 |
<chapter id="developer.overview" chunked="0"> |
5782 |
04 Oct 11 |
nicklas |
28 |
<?dbhtml filename="overview.html" ?> |
4487 |
08 Sep 08 |
jari |
29 |
<title>Developer overview of BASE</title> |
3315 |
09 May 07 |
nicklas |
30 |
|
3315 |
09 May 07 |
nicklas |
31 |
<para> |
4902 |
24 Apr 09 |
nicklas |
32 |
This section gives a brief overview of the architechture used |
4902 |
24 Apr 09 |
nicklas |
33 |
in BASE. This is a good starting point if you need to know how |
4902 |
24 Apr 09 |
nicklas |
34 |
various parts of BASE are glued together. The figure below should |
4902 |
24 Apr 09 |
nicklas |
35 |
display most of the importants parts in BASE. The following |
4902 |
24 Apr 09 |
nicklas |
36 |
sections will briefly describe some parts of the figure |
4902 |
24 Apr 09 |
nicklas |
37 |
and give you pointers for further reading if you are interested in |
4902 |
24 Apr 09 |
nicklas |
38 |
the details. |
3315 |
09 May 07 |
nicklas |
39 |
</para> |
4902 |
24 Apr 09 |
nicklas |
40 |
|
5781 |
04 Oct 11 |
nicklas |
41 |
<figure id="developer.figures.overview"> |
4902 |
24 Apr 09 |
nicklas |
42 |
<title>Overview of the BASE application</title> |
4902 |
24 Apr 09 |
nicklas |
43 |
<screenshot> |
4902 |
24 Apr 09 |
nicklas |
44 |
<mediaobject> |
4902 |
24 Apr 09 |
nicklas |
45 |
<imageobject> |
4902 |
24 Apr 09 |
nicklas |
46 |
<imagedata |
4902 |
24 Apr 09 |
nicklas |
47 |
align="center" |
4902 |
24 Apr 09 |
nicklas |
48 |
scalefit="1" width="100%" |
4902 |
24 Apr 09 |
nicklas |
49 |
fileref="figures/uml/base.overview.png" format="PNG" /> |
4902 |
24 Apr 09 |
nicklas |
50 |
</imageobject> |
4902 |
24 Apr 09 |
nicklas |
51 |
</mediaobject> |
4902 |
24 Apr 09 |
nicklas |
52 |
</screenshot> |
4902 |
24 Apr 09 |
nicklas |
53 |
</figure> |
4902 |
24 Apr 09 |
nicklas |
54 |
|
5781 |
04 Oct 11 |
nicklas |
55 |
<sect1 id="developer.overview.database"> |
4902 |
24 Apr 09 |
nicklas |
56 |
<title>Fixed vs. dynamic database</title> |
4902 |
24 Apr 09 |
nicklas |
57 |
|
4902 |
24 Apr 09 |
nicklas |
58 |
<para> |
4902 |
24 Apr 09 |
nicklas |
59 |
BASE stores most of it's data in a database. The database is divided into |
4902 |
24 Apr 09 |
nicklas |
60 |
two parts, one fixed and one dynamic part. |
4902 |
24 Apr 09 |
nicklas |
61 |
</para> |
4902 |
24 Apr 09 |
nicklas |
62 |
|
4902 |
24 Apr 09 |
nicklas |
63 |
<para> |
4902 |
24 Apr 09 |
nicklas |
64 |
The fixed part contains tables that corresponds |
4902 |
24 Apr 09 |
nicklas |
65 |
to the various items found in BASE. There is, for example, one table |
4902 |
24 Apr 09 |
nicklas |
66 |
for users, one table for groups and one table for reporters. Some items |
5816 |
20 Oct 11 |
nicklas |
67 |
share the same table. Biosources, samples and extracts are |
4902 |
24 Apr 09 |
nicklas |
68 |
all biomaterials and share the <code>BioMaterials</code> table. The access |
4902 |
24 Apr 09 |
nicklas |
69 |
to the fixed part of the database goes through Hibernate in most cases |
4902 |
24 Apr 09 |
nicklas |
70 |
or through the the Batch API in some cases (for example, access to reporters). |
4902 |
24 Apr 09 |
nicklas |
71 |
</para> |
4902 |
24 Apr 09 |
nicklas |
72 |
|
4902 |
24 Apr 09 |
nicklas |
73 |
<para> |
4902 |
24 Apr 09 |
nicklas |
74 |
The dynamic part of the database contains tables for storing analyzed data. |
4902 |
24 Apr 09 |
nicklas |
75 |
Each experiment has it's own set of tables and it is not possible to mix data |
4902 |
24 Apr 09 |
nicklas |
76 |
from two experiments. The dynamic part of the database can only be accessed |
4902 |
24 Apr 09 |
nicklas |
77 |
by the Batch API and the Query API using SQL and JDBC. |
4902 |
24 Apr 09 |
nicklas |
78 |
</para> |
4902 |
24 Apr 09 |
nicklas |
79 |
|
4902 |
24 Apr 09 |
nicklas |
80 |
<note> |
4902 |
24 Apr 09 |
nicklas |
81 |
The actual location of the two parts depends on the database that is used. |
4902 |
24 Apr 09 |
nicklas |
82 |
MySQL uses two separate databases while PostgreSQL uses one database with two schemas. |
4902 |
24 Apr 09 |
nicklas |
83 |
</note> |
4902 |
24 Apr 09 |
nicklas |
84 |
|
4902 |
24 Apr 09 |
nicklas |
85 |
<bridgehead>More information</bridgehead> |
4902 |
24 Apr 09 |
nicklas |
86 |
<itemizedlist> |
4902 |
24 Apr 09 |
nicklas |
87 |
<listitem> |
4902 |
24 Apr 09 |
nicklas |
88 |
<para> |
5781 |
04 Oct 11 |
nicklas |
89 |
<xref linkend="core_api.dynamic" /> |
4902 |
24 Apr 09 |
nicklas |
90 |
</para> |
4902 |
24 Apr 09 |
nicklas |
91 |
</listitem> |
4902 |
24 Apr 09 |
nicklas |
92 |
</itemizedlist> |
4902 |
24 Apr 09 |
nicklas |
93 |
|
4902 |
24 Apr 09 |
nicklas |
94 |
</sect1> |
4902 |
24 Apr 09 |
nicklas |
95 |
|
5781 |
04 Oct 11 |
nicklas |
96 |
<sect1 id="developer.overview.hibernate"> |
4902 |
24 Apr 09 |
nicklas |
97 |
<title>Hibernate and the DbEngine</title> |
4902 |
24 Apr 09 |
nicklas |
98 |
|
4902 |
24 Apr 09 |
nicklas |
99 |
<para> |
4902 |
24 Apr 09 |
nicklas |
100 |
Hibernate (<ulink url="http://www.hibernate.org">www.hibernate.org</ulink>) is an |
4902 |
24 Apr 09 |
nicklas |
101 |
object/relational mapping software package. It takes plain Java objects |
4902 |
24 Apr 09 |
nicklas |
102 |
and stores them in a database. All we have to do is to set the properties |
4902 |
24 Apr 09 |
nicklas |
103 |
on the objects (for example: <code>user.setName("A name")</code>). Hibernate |
4902 |
24 Apr 09 |
nicklas |
104 |
will take care of the SQL generation and database communication for us. |
4902 |
24 Apr 09 |
nicklas |
105 |
This is not a magic or automatic process. We have to provide mapping |
4902 |
24 Apr 09 |
nicklas |
106 |
information about what objects goes into which tables and what properties |
4902 |
24 Apr 09 |
nicklas |
107 |
goes into which columns, and other stuff like caching and proxy settings, etc. |
4902 |
24 Apr 09 |
nicklas |
108 |
This is done by annotating the code with Javadoc comments. The classes |
4902 |
24 Apr 09 |
nicklas |
109 |
that are mapped to the database are found in the <code>net.sf.basedb.core.data</code> |
4902 |
24 Apr 09 |
nicklas |
110 |
package, which is shown as the <guilabel>Data classes</guilabel> box in the image above. |
4902 |
24 Apr 09 |
nicklas |
111 |
The <classname docapi="net.sf.basedb.core">HibernateUtil</classname> class contains a |
4902 |
24 Apr 09 |
nicklas |
112 |
lot of functionality for interacting with Hibernate. |
4902 |
24 Apr 09 |
nicklas |
113 |
</para> |
4902 |
24 Apr 09 |
nicklas |
114 |
|
4902 |
24 Apr 09 |
nicklas |
115 |
<para> |
4902 |
24 Apr 09 |
nicklas |
116 |
Hibernate supports many different database systems. In theory, this means |
4902 |
24 Apr 09 |
nicklas |
117 |
that BASE should work with all those databases. However, in practice we have |
4902 |
24 Apr 09 |
nicklas |
118 |
found that this is not the case. For example, Oracle converts empty strings |
4902 |
24 Apr 09 |
nicklas |
119 |
to <code>null</code> values, which breaks some parts of our code that |
4902 |
24 Apr 09 |
nicklas |
120 |
expects non-null values. Another difficulty is that our Batch API and some parts of |
4902 |
24 Apr 09 |
nicklas |
121 |
the Query API:s generates native SQL as well. We try to use database dialect information |
4902 |
24 Apr 09 |
nicklas |
122 |
from Hibernate, but it is not always possible. The <interfacename |
4902 |
24 Apr 09 |
nicklas |
123 |
docapi="net.sf.basedb.core.dbengine">DbEngine</interfacename> contains code |
4902 |
24 Apr 09 |
nicklas |
124 |
for generating the SQL that Hibernate can't help us with. We have implemented |
4902 |
24 Apr 09 |
nicklas |
125 |
a generic <classname docapi="net.sf.basedb.core.dbengine">DefaultDbEngine</classname> |
4902 |
24 Apr 09 |
nicklas |
126 |
which follows ANSI specifications and special drivers for MySQL |
4902 |
24 Apr 09 |
nicklas |
127 |
(<classname docapi="net.sf.basedb.core.dbengine">MySQLEngine</classname>) and |
4902 |
24 Apr 09 |
nicklas |
128 |
PostgreSQL (<classname docapi="net.sf.basedb.core.dbengine">PostgresDbEngine</classname>). |
4902 |
24 Apr 09 |
nicklas |
129 |
We don't expect BASE to work with other databases without modifications. |
4902 |
24 Apr 09 |
nicklas |
130 |
</para> |
4902 |
24 Apr 09 |
nicklas |
131 |
|
4902 |
24 Apr 09 |
nicklas |
132 |
<bridgehead>More information</bridgehead> |
4902 |
24 Apr 09 |
nicklas |
133 |
<itemizedlist> |
4902 |
24 Apr 09 |
nicklas |
134 |
<listitem> |
4902 |
24 Apr 09 |
nicklas |
135 |
<para> |
4902 |
24 Apr 09 |
nicklas |
136 |
<xref linkend="core_ref.rules.datalayer" /> |
4902 |
24 Apr 09 |
nicklas |
137 |
</para> |
4902 |
24 Apr 09 |
nicklas |
138 |
</listitem> |
4902 |
24 Apr 09 |
nicklas |
139 |
<listitem> |
4902 |
24 Apr 09 |
nicklas |
140 |
<para> |
4902 |
24 Apr 09 |
nicklas |
141 |
<ulink url="http://www.hibernate.org">www.hibernate.org</ulink> |
4902 |
24 Apr 09 |
nicklas |
142 |
</para> |
4902 |
24 Apr 09 |
nicklas |
143 |
</listitem> |
4902 |
24 Apr 09 |
nicklas |
144 |
</itemizedlist> |
4902 |
24 Apr 09 |
nicklas |
145 |
|
4902 |
24 Apr 09 |
nicklas |
146 |
</sect1> |
4902 |
24 Apr 09 |
nicklas |
147 |
|
5781 |
04 Oct 11 |
nicklas |
148 |
<sect1 id="developer.overview.batchapi"> |
4902 |
24 Apr 09 |
nicklas |
149 |
<title>The Batch API</title> |
4902 |
24 Apr 09 |
nicklas |
150 |
|
4902 |
24 Apr 09 |
nicklas |
151 |
<para> |
4902 |
24 Apr 09 |
nicklas |
152 |
Hibernate comes with a price. It affects performance and uses a lot |
4902 |
24 Apr 09 |
nicklas |
153 |
of memory. This means that those parts of BASE that often handles |
4902 |
24 Apr 09 |
nicklas |
154 |
lots of items at the same time doesn't work well with Hibernate. This |
4902 |
24 Apr 09 |
nicklas |
155 |
is for example reporters, array design features and raw data. We |
4902 |
24 Apr 09 |
nicklas |
156 |
have created the Batch API to solve these problems. |
4902 |
24 Apr 09 |
nicklas |
157 |
</para> |
4902 |
24 Apr 09 |
nicklas |
158 |
|
4902 |
24 Apr 09 |
nicklas |
159 |
<para> |
4902 |
24 Apr 09 |
nicklas |
160 |
The Batch API uses JDBC and SQL directly against the database. However, we |
4902 |
24 Apr 09 |
nicklas |
161 |
still use metadata and database dialect information available from Hibernate |
4902 |
24 Apr 09 |
nicklas |
162 |
to generate most of the SQL we need. In theory, this should make the Batch API |
4902 |
24 Apr 09 |
nicklas |
163 |
just as database-independent as Hibernate is. In practice there is some information |
4902 |
24 Apr 09 |
nicklas |
164 |
that we can't extract from Hibernate so we have implemented a simple |
4902 |
24 Apr 09 |
nicklas |
165 |
<interfacename docapi="net.sf.basedb.core.dbengine">DbEngine</interfacename> |
4902 |
24 Apr 09 |
nicklas |
166 |
to account for missing pieces. The Batch API can be used for any |
4902 |
24 Apr 09 |
nicklas |
167 |
<classname docapi="net.sf.basedb.core.data">BatchableData</classname> class in the |
4902 |
24 Apr 09 |
nicklas |
168 |
fixed part of the database and is the only way for adding data to the dynamic part. |
4902 |
24 Apr 09 |
nicklas |
169 |
</para> |
4902 |
24 Apr 09 |
nicklas |
170 |
|
4902 |
24 Apr 09 |
nicklas |
171 |
<note> |
4902 |
24 Apr 09 |
nicklas |
172 |
The main reason for the Batch API is to avoid the internal caching |
4902 |
24 Apr 09 |
nicklas |
173 |
of Hibernate which eats lots of memory when handling thousands of items. |
4902 |
24 Apr 09 |
nicklas |
174 |
Hibernate 3.1 introduced a new stateless API which among other things doesn't |
4902 |
24 Apr 09 |
nicklas |
175 |
do any caching. This version was released after we had created the Batch API. |
4902 |
24 Apr 09 |
nicklas |
176 |
We made a few tests to check if it would be better for us to switch back to Hibernate |
4902 |
24 Apr 09 |
nicklas |
177 |
but found that it didn't perform as well as our own Batch API (it was about 2 times slower). |
4902 |
24 Apr 09 |
nicklas |
178 |
In any case, we can never get Hibernate to work with the dynamic database, |
4902 |
24 Apr 09 |
nicklas |
179 |
so the Batch API is needed. |
4902 |
24 Apr 09 |
nicklas |
180 |
</note> |
4902 |
24 Apr 09 |
nicklas |
181 |
|
4902 |
24 Apr 09 |
nicklas |
182 |
<bridgehead>More information</bridgehead> |
4902 |
24 Apr 09 |
nicklas |
183 |
<itemizedlist> |
4902 |
24 Apr 09 |
nicklas |
184 |
<listitem> |
4902 |
24 Apr 09 |
nicklas |
185 |
<para> |
5781 |
04 Oct 11 |
nicklas |
186 |
<xref linkend="core_api.batch" /> |
4902 |
24 Apr 09 |
nicklas |
187 |
</para> |
4902 |
24 Apr 09 |
nicklas |
188 |
</listitem> |
4902 |
24 Apr 09 |
nicklas |
189 |
<listitem> |
4902 |
24 Apr 09 |
nicklas |
190 |
<para> |
5781 |
04 Oct 11 |
nicklas |
191 |
<xref linkend="core_api.dynamic" /> |
4902 |
24 Apr 09 |
nicklas |
192 |
</para> |
4902 |
24 Apr 09 |
nicklas |
193 |
</listitem> |
4902 |
24 Apr 09 |
nicklas |
194 |
<listitem> |
4902 |
24 Apr 09 |
nicklas |
195 |
<para> |
5781 |
04 Oct 11 |
nicklas |
196 |
<xref linkend="core_ref.rules.batchclass" /> |
4902 |
24 Apr 09 |
nicklas |
197 |
</para> |
4902 |
24 Apr 09 |
nicklas |
198 |
</listitem> |
4902 |
24 Apr 09 |
nicklas |
199 |
</itemizedlist> |
4902 |
24 Apr 09 |
nicklas |
200 |
</sect1> |
4902 |
24 Apr 09 |
nicklas |
201 |
|
5781 |
04 Oct 11 |
nicklas |
202 |
<sect1 id="developer.overview.classes"> |
4902 |
24 Apr 09 |
nicklas |
203 |
<title>Data classes vs. item classes</title> |
4902 |
24 Apr 09 |
nicklas |
204 |
|
4902 |
24 Apr 09 |
nicklas |
205 |
<para> |
4902 |
24 Apr 09 |
nicklas |
206 |
The data classes are, with few exceptions, for internal use. These are the classes |
4902 |
24 Apr 09 |
nicklas |
207 |
that are mapped to the database with Hibernate mapping files. They are very simple |
4902 |
24 Apr 09 |
nicklas |
208 |
and contains no logic at all. They don't do any permission checks or any data |
4902 |
24 Apr 09 |
nicklas |
209 |
validation. |
4902 |
24 Apr 09 |
nicklas |
210 |
</para> |
4902 |
24 Apr 09 |
nicklas |
211 |
|
4902 |
24 Apr 09 |
nicklas |
212 |
<para> |
4902 |
24 Apr 09 |
nicklas |
213 |
Most of the data classes has a corresponding item class. For example: |
4902 |
24 Apr 09 |
nicklas |
214 |
<classname docapi="net.sf.basedb.core.data">UserData</classname> |
4902 |
24 Apr 09 |
nicklas |
215 |
and <classname docapi="net.sf.basedb.core">User</classname>, |
4902 |
24 Apr 09 |
nicklas |
216 |
<classname docapi="net.sf.basedb.core.data">GroupData</classname> and |
4902 |
24 Apr 09 |
nicklas |
217 |
<classname docapi="net.sf.basedb.core">Group</classname>. |
4902 |
24 Apr 09 |
nicklas |
218 |
The item classes are what the client applications can see and use. They contain |
4902 |
24 Apr 09 |
nicklas |
219 |
logic for permission checking (for example if the logged in user has WRITE permission) |
4902 |
24 Apr 09 |
nicklas |
220 |
and data validation (for example setting a required property to null). |
4902 |
24 Apr 09 |
nicklas |
221 |
</para> |
4902 |
24 Apr 09 |
nicklas |
222 |
|
4902 |
24 Apr 09 |
nicklas |
223 |
<para> |
4902 |
24 Apr 09 |
nicklas |
224 |
The exception to the above scheme are the batchable classes, which are |
4902 |
24 Apr 09 |
nicklas |
225 |
all subclasses of the <classname docapi="net.sf.basedb.core.data">BatchableData</classname> |
4902 |
24 Apr 09 |
nicklas |
226 |
class. For example, there is a <classname docapi="net.sf.basedb.core.data">ReporterData</classname> |
4902 |
24 Apr 09 |
nicklas |
227 |
class but no corresponding item class. Instead there is a |
4902 |
24 Apr 09 |
nicklas |
228 |
batcher implementation, <classname docapi="net.sf.basedb.core">ReporterBatcher</classname>, |
4902 |
24 Apr 09 |
nicklas |
229 |
which takes care of the more or less the same things that an item class does, |
4902 |
24 Apr 09 |
nicklas |
230 |
but it also takes care of it's own SQL generation and JDBC calls that |
4902 |
24 Apr 09 |
nicklas |
231 |
bypasses Hibernate and the caching system. |
4902 |
24 Apr 09 |
nicklas |
232 |
</para> |
4902 |
24 Apr 09 |
nicklas |
233 |
|
4902 |
24 Apr 09 |
nicklas |
234 |
<bridgehead>More information</bridgehead> |
4902 |
24 Apr 09 |
nicklas |
235 |
<itemizedlist> |
4902 |
24 Apr 09 |
nicklas |
236 |
<listitem> |
4902 |
24 Apr 09 |
nicklas |
237 |
<para> |
4902 |
24 Apr 09 |
nicklas |
238 |
<xref linkend="core_ref.rules.datalayer" /> |
4902 |
24 Apr 09 |
nicklas |
239 |
</para> |
4902 |
24 Apr 09 |
nicklas |
240 |
</listitem> |
4902 |
24 Apr 09 |
nicklas |
241 |
<listitem> |
4902 |
24 Apr 09 |
nicklas |
242 |
<para> |
4902 |
24 Apr 09 |
nicklas |
243 |
<xref linkend="core_ref.rules.itemclass" /> |
4902 |
24 Apr 09 |
nicklas |
244 |
</para> |
4902 |
24 Apr 09 |
nicklas |
245 |
</listitem> |
4902 |
24 Apr 09 |
nicklas |
246 |
<listitem> |
4902 |
24 Apr 09 |
nicklas |
247 |
<para> |
4902 |
24 Apr 09 |
nicklas |
248 |
<xref linkend="core_ref.rules.batchclass" /> |
4902 |
24 Apr 09 |
nicklas |
249 |
</para> |
4902 |
24 Apr 09 |
nicklas |
250 |
</listitem> |
4902 |
24 Apr 09 |
nicklas |
251 |
<listitem> |
4902 |
24 Apr 09 |
nicklas |
252 |
<para> |
5781 |
04 Oct 11 |
nicklas |
253 |
<xref linkend="core_api.accesspermissions" /> |
4902 |
24 Apr 09 |
nicklas |
254 |
</para> |
4902 |
24 Apr 09 |
nicklas |
255 |
</listitem> |
4902 |
24 Apr 09 |
nicklas |
256 |
<listitem> |
4902 |
24 Apr 09 |
nicklas |
257 |
<para> |
5781 |
04 Oct 11 |
nicklas |
258 |
<xref linkend="core_api.datavalidation" /> |
4902 |
24 Apr 09 |
nicklas |
259 |
</para> |
4902 |
24 Apr 09 |
nicklas |
260 |
</listitem> |
4902 |
24 Apr 09 |
nicklas |
261 |
<listitem> |
4902 |
24 Apr 09 |
nicklas |
262 |
<para> |
5781 |
04 Oct 11 |
nicklas |
263 |
<xref linkend="core_api.batch" /> |
4902 |
24 Apr 09 |
nicklas |
264 |
</para> |
4902 |
24 Apr 09 |
nicklas |
265 |
</listitem> |
4902 |
24 Apr 09 |
nicklas |
266 |
</itemizedlist> |
4902 |
24 Apr 09 |
nicklas |
267 |
</sect1> |
4902 |
24 Apr 09 |
nicklas |
268 |
|
5781 |
04 Oct 11 |
nicklas |
269 |
<sect1 id="developer.overview.queryapi"> |
4902 |
24 Apr 09 |
nicklas |
270 |
<title>The Query API</title> |
4902 |
24 Apr 09 |
nicklas |
271 |
<para> |
4902 |
24 Apr 09 |
nicklas |
272 |
The Query API is used to build and execute queries against the data in the |
4902 |
24 Apr 09 |
nicklas |
273 |
database. It builds a query by using objects that represents certain |
4902 |
24 Apr 09 |
nicklas |
274 |
operations. For example, there is an <classname |
4902 |
24 Apr 09 |
nicklas |
275 |
docapi="net.sf.basedb.core.query">EqRestriction</classname> object |
4902 |
24 Apr 09 |
nicklas |
276 |
which tests if two expressions are equal and there is an <classname |
4902 |
24 Apr 09 |
nicklas |
277 |
docapi="net.sf.basedb.core.query">AddExpression</classname> |
4902 |
24 Apr 09 |
nicklas |
278 |
object which adds two expressions. In this way it is possible to build |
4902 |
24 Apr 09 |
nicklas |
279 |
very complex queries without using SQL or HQL. |
4902 |
24 Apr 09 |
nicklas |
280 |
</para> |
4902 |
24 Apr 09 |
nicklas |
281 |
|
4902 |
24 Apr 09 |
nicklas |
282 |
<para> |
4902 |
24 Apr 09 |
nicklas |
283 |
The Query API knows how to work both via Hibernate and via SQL. In the first case it |
4902 |
24 Apr 09 |
nicklas |
284 |
generates HQL (Hibernate Query Language) statements which Hibernate then |
4902 |
24 Apr 09 |
nicklas |
285 |
translates into SQL. In the second case SQL is generated directly. |
4902 |
24 Apr 09 |
nicklas |
286 |
In most cases HQL and SQL are identical, but not |
4902 |
24 Apr 09 |
nicklas |
287 |
always. Some situations are solved by having the Query API generate |
4902 |
24 Apr 09 |
nicklas |
288 |
slightly different query strings (with the help of information from |
4902 |
24 Apr 09 |
nicklas |
289 |
Hibernate and the DbEngine). Some query elements can only be used |
4902 |
24 Apr 09 |
nicklas |
290 |
with one of the query types. |
4902 |
24 Apr 09 |
nicklas |
291 |
</para> |
4902 |
24 Apr 09 |
nicklas |
292 |
|
4902 |
24 Apr 09 |
nicklas |
293 |
<note> |
4902 |
24 Apr 09 |
nicklas |
294 |
The object-based approach makes it a bit difficult to store |
4902 |
24 Apr 09 |
nicklas |
295 |
a query for later reuse. The <code>net.sf.basedb.util.jep</code> |
4902 |
24 Apr 09 |
nicklas |
296 |
package contains an expression parser that can be used to convert |
4902 |
24 Apr 09 |
nicklas |
297 |
a string to <interfacename |
4902 |
24 Apr 09 |
nicklas |
298 |
docapi="net.sf.basedb.core.query">Restriction</interfacename>:s and |
4902 |
24 Apr 09 |
nicklas |
299 |
<interfacename |
4902 |
24 Apr 09 |
nicklas |
300 |
docapi="net.sf.basedb.core.query">Expression</interfacename>:s for |
4902 |
24 Apr 09 |
nicklas |
301 |
the Query API. While it doesn't cover 100% of the cases it should be |
4902 |
24 Apr 09 |
nicklas |
302 |
useful for the <code>WHERE</code> part of a query. |
4902 |
24 Apr 09 |
nicklas |
303 |
</note> |
4902 |
24 Apr 09 |
nicklas |
304 |
|
4902 |
24 Apr 09 |
nicklas |
305 |
<bridgehead>More information</bridgehead> |
4902 |
24 Apr 09 |
nicklas |
306 |
<itemizedlist> |
4902 |
24 Apr 09 |
nicklas |
307 |
<listitem> |
4902 |
24 Apr 09 |
nicklas |
308 |
<para> |
5781 |
04 Oct 11 |
nicklas |
309 |
<xref linkend="core_api.query" /> |
4902 |
24 Apr 09 |
nicklas |
310 |
</para> |
4902 |
24 Apr 09 |
nicklas |
311 |
</listitem> |
4902 |
24 Apr 09 |
nicklas |
312 |
</itemizedlist> |
4902 |
24 Apr 09 |
nicklas |
313 |
</sect1> |
5816 |
20 Oct 11 |
nicklas |
314 |
|
5781 |
04 Oct 11 |
nicklas |
315 |
<sect1 id="developer.overview.controllerapi"> |
4902 |
24 Apr 09 |
nicklas |
316 |
<title>The Controller API</title> |
4902 |
24 Apr 09 |
nicklas |
317 |
<para> |
5633 |
18 May 11 |
nicklas |
318 |
The Controller API is the very heart of the BASE system. This part |
4902 |
24 Apr 09 |
nicklas |
319 |
of the core is used for boring but essential details, such as |
4902 |
24 Apr 09 |
nicklas |
320 |
user authentication, database connection management, transaction |
4902 |
24 Apr 09 |
nicklas |
321 |
management, data validation, and more. We don't write more about this |
4902 |
24 Apr 09 |
nicklas |
322 |
part here, but recommends reading the documents below. |
4902 |
24 Apr 09 |
nicklas |
323 |
</para> |
4902 |
24 Apr 09 |
nicklas |
324 |
|
4902 |
24 Apr 09 |
nicklas |
325 |
<bridgehead>More information</bridgehead> |
4902 |
24 Apr 09 |
nicklas |
326 |
<itemizedlist> |
4902 |
24 Apr 09 |
nicklas |
327 |
<listitem> |
4902 |
24 Apr 09 |
nicklas |
328 |
<para> |
5781 |
04 Oct 11 |
nicklas |
329 |
<xref linkend="base_api.core" /> |
4902 |
24 Apr 09 |
nicklas |
330 |
</para> |
4902 |
24 Apr 09 |
nicklas |
331 |
</listitem> |
4902 |
24 Apr 09 |
nicklas |
332 |
</itemizedlist> |
4902 |
24 Apr 09 |
nicklas |
333 |
</sect1> |
5816 |
20 Oct 11 |
nicklas |
334 |
|
5816 |
20 Oct 11 |
nicklas |
335 |
<sect1 id="developer.overview.extensionsapi"> |
5816 |
20 Oct 11 |
nicklas |
336 |
<title>The Extensions API</title> |
5816 |
20 Oct 11 |
nicklas |
337 |
<para> |
5816 |
20 Oct 11 |
nicklas |
338 |
An extensions mechanism makes it possible to add functionality |
5816 |
20 Oct 11 |
nicklas |
339 |
to BASE by external parties without having to modify the BASE code. |
5816 |
20 Oct 11 |
nicklas |
340 |
This is not something that can be done at random, but BASE define |
5816 |
20 Oct 11 |
nicklas |
341 |
a number of <emphasis>extension points</emphasis> which can been as |
5816 |
20 Oct 11 |
nicklas |
342 |
a contract that must be fulfilled by the external code. Extension |
5816 |
20 Oct 11 |
nicklas |
343 |
points are defined both by the BASE core (for example, file validators) |
5816 |
20 Oct 11 |
nicklas |
344 |
and by the BASE web client (for example, menu and toolbar entries). |
5816 |
20 Oct 11 |
nicklas |
345 |
In many cases, the distinction between an extension and a plug-in is |
5816 |
20 Oct 11 |
nicklas |
346 |
fine. One major difference is that extensions are invoked and used |
5816 |
20 Oct 11 |
nicklas |
347 |
immediately and are never queued for later execution. The installation |
5816 |
20 Oct 11 |
nicklas |
348 |
mechanism is the same for both extensions and plug-ins and many packages |
5816 |
20 Oct 11 |
nicklas |
349 |
use both types to provide a better user experience. |
5816 |
20 Oct 11 |
nicklas |
350 |
</para> |
5816 |
20 Oct 11 |
nicklas |
351 |
|
5816 |
20 Oct 11 |
nicklas |
352 |
<bridgehead>More information</bridgehead> |
5816 |
20 Oct 11 |
nicklas |
353 |
<itemizedlist> |
5816 |
20 Oct 11 |
nicklas |
354 |
<listitem> |
5816 |
20 Oct 11 |
nicklas |
355 |
<para> |
5816 |
20 Oct 11 |
nicklas |
356 |
<xref linkend="extensions_developer" /> |
5816 |
20 Oct 11 |
nicklas |
357 |
</para> |
5816 |
20 Oct 11 |
nicklas |
358 |
</listitem> |
5816 |
20 Oct 11 |
nicklas |
359 |
</itemizedlist> |
5816 |
20 Oct 11 |
nicklas |
360 |
<itemizedlist> |
5816 |
20 Oct 11 |
nicklas |
361 |
<listitem> |
5816 |
20 Oct 11 |
nicklas |
362 |
<para> |
5816 |
20 Oct 11 |
nicklas |
363 |
<xref linkend="core_api.extensions" /> |
5816 |
20 Oct 11 |
nicklas |
364 |
</para> |
5816 |
20 Oct 11 |
nicklas |
365 |
</listitem> |
5816 |
20 Oct 11 |
nicklas |
366 |
</itemizedlist> |
5816 |
20 Oct 11 |
nicklas |
367 |
</sect1> |
4902 |
24 Apr 09 |
nicklas |
368 |
|
5781 |
04 Oct 11 |
nicklas |
369 |
<sect1 id="developer.overview.plugins"> |
4902 |
24 Apr 09 |
nicklas |
370 |
<title>Plug-ins</title> |
4902 |
24 Apr 09 |
nicklas |
371 |
|
4902 |
24 Apr 09 |
nicklas |
372 |
<para> |
4902 |
24 Apr 09 |
nicklas |
373 |
From the core code's point of view a plug-in is just another client |
4902 |
24 Apr 09 |
nicklas |
374 |
application. A plug-in doesn't have more powers and doesn't have |
4902 |
24 Apr 09 |
nicklas |
375 |
access to some special API that allows it to do cool stuff that other |
4902 |
24 Apr 09 |
nicklas |
376 |
clients can't. |
4902 |
24 Apr 09 |
nicklas |
377 |
</para> |
4902 |
24 Apr 09 |
nicklas |
378 |
|
4902 |
24 Apr 09 |
nicklas |
379 |
<para> |
4902 |
24 Apr 09 |
nicklas |
380 |
However, the core must be able to control when and where a plug-in is |
4902 |
24 Apr 09 |
nicklas |
381 |
executed. Some plug-ins may take a long time doing their calculations |
4902 |
24 Apr 09 |
nicklas |
382 |
and may use a lot of memory. It would be bad if a several users started |
4902 |
24 Apr 09 |
nicklas |
383 |
to execute a resource-demanding plug-in at the same time. This problem is |
4902 |
24 Apr 09 |
nicklas |
384 |
solved by adding a job queue. Each plug-in that should be executed is |
4902 |
24 Apr 09 |
nicklas |
385 |
registered as <classname |
4902 |
24 Apr 09 |
nicklas |
386 |
docapi="net.sf.basedb.core">Job</classname> in the database. A job controller is |
4902 |
24 Apr 09 |
nicklas |
387 |
checking the job queue at regular intervals. The job controller can then |
4902 |
24 Apr 09 |
nicklas |
388 |
choose if it should execute the plug-in or wait depending on the current |
4902 |
24 Apr 09 |
nicklas |
389 |
load on the server. |
4902 |
24 Apr 09 |
nicklas |
390 |
</para> |
4902 |
24 Apr 09 |
nicklas |
391 |
|
4902 |
24 Apr 09 |
nicklas |
392 |
<note> |
4902 |
24 Apr 09 |
nicklas |
393 |
BASE ships with two types of job controllers. One internal that runs |
4902 |
24 Apr 09 |
nicklas |
394 |
inside the web application, and one external that is designed to run |
4902 |
24 Apr 09 |
nicklas |
395 |
on separate servers, so called job agents. The internal job controller |
4902 |
24 Apr 09 |
nicklas |
396 |
should work fine in most cases. The drawback with this controller is |
4902 |
24 Apr 09 |
nicklas |
397 |
that a badly written plug-in may crash the entire web server. For example, |
4902 |
24 Apr 09 |
nicklas |
398 |
a call to <code>System.exit()</code> in the plug-in code shuts down Tomcat |
4902 |
24 Apr 09 |
nicklas |
399 |
as well. |
4902 |
24 Apr 09 |
nicklas |
400 |
</note> |
4902 |
24 Apr 09 |
nicklas |
401 |
|
4902 |
24 Apr 09 |
nicklas |
402 |
<bridgehead>More information</bridgehead> |
4902 |
24 Apr 09 |
nicklas |
403 |
<itemizedlist> |
4902 |
24 Apr 09 |
nicklas |
404 |
<listitem> |
4902 |
24 Apr 09 |
nicklas |
405 |
<para> |
4902 |
24 Apr 09 |
nicklas |
406 |
<xref linkend="plugin_developer" /> |
4902 |
24 Apr 09 |
nicklas |
407 |
</para> |
4902 |
24 Apr 09 |
nicklas |
408 |
</listitem> |
4902 |
24 Apr 09 |
nicklas |
409 |
<listitem> |
4902 |
24 Apr 09 |
nicklas |
410 |
<para> |
5781 |
04 Oct 11 |
nicklas |
411 |
<xref linkend="core_api.pluginexecution" /> |
4902 |
24 Apr 09 |
nicklas |
412 |
</para> |
4902 |
24 Apr 09 |
nicklas |
413 |
</listitem> |
4902 |
24 Apr 09 |
nicklas |
414 |
</itemizedlist> |
4902 |
24 Apr 09 |
nicklas |
415 |
</sect1> |
4902 |
24 Apr 09 |
nicklas |
416 |
|
5781 |
04 Oct 11 |
nicklas |
417 |
<sect1 id="developer.overview.clients"> |
4902 |
24 Apr 09 |
nicklas |
418 |
<title>Client applications</title> |
4902 |
24 Apr 09 |
nicklas |
419 |
<para> |
4902 |
24 Apr 09 |
nicklas |
420 |
Client applications are application that use the BASE Core API. The current web |
5633 |
18 May 11 |
nicklas |
421 |
application is built with Java Server Pages (JSP). JSP is supported by several |
5633 |
18 May 11 |
nicklas |
422 |
application servers but we have only tested it with Tomcat. Another client |
5633 |
18 May 11 |
nicklas |
423 |
application is the external job agents that executes plug-ins on separate |
5633 |
18 May 11 |
nicklas |
424 |
servers. |
4902 |
24 Apr 09 |
nicklas |
425 |
</para> |
4902 |
24 Apr 09 |
nicklas |
426 |
|
4902 |
24 Apr 09 |
nicklas |
427 |
<para> |
4902 |
24 Apr 09 |
nicklas |
428 |
Although it is possible to develop a completely new client appliction from |
4902 |
24 Apr 09 |
nicklas |
429 |
scratch we don't see this as a likely thing to happen. Instead, there are |
4902 |
24 Apr 09 |
nicklas |
430 |
some other possibilites to access data in BASE and to extend the functionality |
4902 |
24 Apr 09 |
nicklas |
431 |
in BASE. |
4902 |
24 Apr 09 |
nicklas |
432 |
</para> |
4902 |
24 Apr 09 |
nicklas |
433 |
|
4902 |
24 Apr 09 |
nicklas |
434 |
<para> |
4902 |
24 Apr 09 |
nicklas |
435 |
The first possibility is to use the Web Service API. This allows you to access |
4902 |
24 Apr 09 |
nicklas |
436 |
some of the data in the BASE database and download it for further use. The |
4902 |
24 Apr 09 |
nicklas |
437 |
Web Service API is currently very limited but it is not hard to extend it |
4902 |
24 Apr 09 |
nicklas |
438 |
to cover more use cases. |
4902 |
24 Apr 09 |
nicklas |
439 |
</para> |
4902 |
24 Apr 09 |
nicklas |
440 |
|
4902 |
24 Apr 09 |
nicklas |
441 |
<para> |
4902 |
24 Apr 09 |
nicklas |
442 |
A second possibility is to use the Extension API. This allows a developer to |
4902 |
24 Apr 09 |
nicklas |
443 |
add functionality that appears directly in the web interface. For example, |
4902 |
24 Apr 09 |
nicklas |
444 |
additional menu items and toolbar buttons. This API is also easy to extend to |
4902 |
24 Apr 09 |
nicklas |
445 |
cover more use cases. |
4902 |
24 Apr 09 |
nicklas |
446 |
</para> |
4902 |
24 Apr 09 |
nicklas |
447 |
|
4902 |
24 Apr 09 |
nicklas |
448 |
<bridgehead>More information</bridgehead> |
4902 |
24 Apr 09 |
nicklas |
449 |
<itemizedlist> |
4902 |
24 Apr 09 |
nicklas |
450 |
<listitem> |
4902 |
24 Apr 09 |
nicklas |
451 |
<para> |
4902 |
24 Apr 09 |
nicklas |
452 |
<xref linkend="extensions_developer" /> |
4902 |
24 Apr 09 |
nicklas |
453 |
</para> |
4902 |
24 Apr 09 |
nicklas |
454 |
</listitem> |
4902 |
24 Apr 09 |
nicklas |
455 |
<listitem> |
4902 |
24 Apr 09 |
nicklas |
456 |
<para> |
7982 |
14 Jun 21 |
nicklas |
457 |
The <ulink url="https://baseplugins.thep.lu.se">BASE plug-ins site</ulink> also |
6465 |
04 Jun 14 |
nicklas |
458 |
has examples of extensions. |
4902 |
24 Apr 09 |
nicklas |
459 |
</para> |
4902 |
24 Apr 09 |
nicklas |
460 |
</listitem> |
4902 |
24 Apr 09 |
nicklas |
461 |
</itemizedlist> |
4902 |
24 Apr 09 |
nicklas |
462 |
</sect1> |
4902 |
24 Apr 09 |
nicklas |
463 |
|
3675 |
16 Aug 07 |
jari |
464 |
</chapter> |