Hi,
with great thanks to Chuck I were able to solve my problem.
I ported my application from webware 0.8 to 0.9rc1 and get the above
error message only when I add new records. So changing and deleting
records works fine. It looks like that the model can be read. But why do
I get this error, if the rest is working?
using webware 0.9rc1, python 2.3, mysql 4, apache 2, cheetahtemplates
under Debian Sarge (uptodate).
store = MySQLObjectStore(user='db', passwd='geheim')
store.readModelFileNamed('app/Middle/app')
#
# create transfer object
#
transfer = Transfers()
...
transfer.setChangedOn(self.getSite())
#
# calculate the rest
#
#
# store transfer in database
#
store.addObject(transfer)
^^^^^^^^^^^^^^^^^^^^^^^^^^
The MiddleKit package creates internally a "Klass" object, which
contains an internal model and will be assoziated with each MiddleKit
object. If the store have read the model can be tested the following way:
# can we make a store with a model?
from MiddleKit.Run.MySQLObjectStore import MySQLObjectStore
store = MySQLObjectStore(user=user, passwd=password)
store.readModelFileNamed('Middle/app')
assert store.model() is not None
assert len(store.model().allKlassesByName())==11 # number of classes in
the app model
assert store.model().allKlassesByName().has_key('Transfers') # check
for a MiddleKit class
pprint(store.model().allKlassesByName())
To check the model assoziated with a concrete class from the MiddleKit
model you can use the following example code:
# does the Transfers class look right?
from Middle.Transfers import Transfers
assert hasattr(Transfers, 'Datum')
t = Transfers()
assert t.klass() is not None
store.addObject(t)
In my case the last assertion failed inside my webware application but
nor when I used this test code standalone. The reason was that my class
Transfer was registered inside python 2.3 TWO TIMES under different
relative paths :-( This we could see by inserting the following code in
my app:
import os, sys, time, types
assert store is not None
assert store.model() is not None
t = Transfers()
assert t
print '\n'*4
from pprint import pprint
pprint(sys.modules)
print '>> t class = %r' % t.__class__
print '>> t class module = %r' % t.__class__.__module__
keys = sorted(sys.modules.keys())
for key in keys:
if key.lower().find('transfers')!=-1:
print '>> found module: %r' % key
The problem is that python don't use the absolute path to identify a
module/class. So two mistakes I have made. I extended the path
entvironment in "__init__.py" of my app to include the app path and the
MiddleKit path. Both are NOT required! But the most important mistake
was my folder structure:
workDir
app
Middle
Transfers
This structure is ugly for several reasons I understood, now, and
learned how to improve:
- the "app" folder should include ONLY servlet classes, which should be
callable via web server, so no utilities and no database classes!!!
- the Middlekit classes should be not directly callable by the
web/application server only internal. So you should move it in the
workDir and import the required classes using "from Middle.Transfers
import Transfers".
- all utilities, like my singleton (see below) to access the store
should be moved into the "Libs" folder as suggested by webware 0.9.
--- class GlobalState.py
from MiddleKit.Run.MySQLObjectStore import MySQLObjectStore
#
# read configuration file
#
f = open('app/product.config','r')
config = eval(f.read())
f.close()
#
# and select required configuration information
#
dbUser = config['dbUser']
dbPassword = config['dbPassword']
class Store:
def __init__(self):
# Do something
self.store = MySQLObjectStore(user=dbUser, passwd=dbPassword)
self.store.readModelFileNamed('Middle/app')
def __call__(self):
return self
def store(self):
return self.store
Store = Store()
---
So you should create the following folder structure:
workDir
app -> name of the context
Main.py -> only servlets, which can be directly call via URL
Middle -> all MiddleKit / database classes
Transfers
Libs -> all utility classes
GlobalState.py
so use the command: "MakeAppWorkDir -l Libs -c app workDir"
If you port your application from an older webware version don't forget
to recreate the MiddleKit classes and include a setting file
"Middle/app.mkmodel/Settings.config" like the following:
{
'Package': 'Middle',
'SQLSerialColumnName': '%(className)sId',
#'SQLLog': { 'File': 'mk-sql.log' },
'DoNotSortSQLCreateStatementsByDependency': 1,
'UseBigIntObjRefColumns': 1,
'AllowRefreshOfChangedObjects': 1,
'UseHashForClassIds': 1,
}
I hope that these comments could help others, too.
Jan
-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP. Click here to play: http://sourceforge.net/geronimo.php
_______________________________________________
Webware-discuss mailing list
Webware-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/webware-discuss