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

Reply via email to