We do indeed have a single copy of the entityengine.xml file, but we have added 
"templates" to the file, such that we have an entity in our main "provisioning" 
instance, that lists all the tenants and the coordinates of the database for 
their delegator.

The delegator for the tenants are then instantiated using the template and the 
information from this provisioning database.

This means, that in a VM, all instances share the same "structure" of delegator 
and data sources.  Below is a snippet of our entityengine.xml file that 
illustrates the template delegator and associated datasource.

The FlexibleStringExpander is used to expand the template items.   Our 
delegators have names that are numbers, (ie. party_id of our customer in our 
deployment instance).   Each tenant has a row in the DatabaseDetail entity 
which has columns databaseName, internalHost, externalHost.  In our case, the 
username and password are generated (not stored in the database).

The internalHost is the internal hostname for the database server, while the 
externalHost is the external hostname for the database server.  Since we deploy 
on Amazon EC2, each host has both a local and public IP address. 

If your paying attention to the information below, you can see that the 
sequence numbers for each tenant are prefixed with the party_id and a "-".  
Making all surrogate keys non-colliding (an important feature for sharing 
database between tenants).


    <delegator name="default" entity-model-reader="main" 
entity-group-reader="main" entity-eca-reader="main" 
distributed-cache-clear-enabled="false">
        <group-map group-name="org.ofbiz" datasource-name="localpostgres"/>
        <group-map group-name="org.ofbiz.olap" datasource-name="localpostgres"/>
        <group-map group-name="com.emforium.deploy" datasource-name="emforium"/>
    </delegator>
   <delegator name="${instance}"  crypto-minimum-keys="0" 
entity-model-reader="main" entity-group-reader="main" entity-eca-reader="main" 
distributed-cache-clear-enabled="false" sequenced-id-prefix="${instance}-">
        <group-map group-name="org.ofbiz" datasource-name="${instance}"/>
        <group-map group-name="org.ofbiz.olap" datasource-name="${instance}"/>
        <group-map group-name="com.emforium.deploy" 
datasource-name="${instance}"/>
     </delegator>

    <datasource name="${instance}"
            helper-class="org.ofbiz.entity.datasource.GenericHelperDAO"
            schema-name="public"
            field-type-name="postgres"
            check-on-start="true"
            add-missing-on-start="true"
            generate-sql="false"
            use-fk-initially-deferred="false"
            alias-view-columns="false"
            join-style="ansi"
            use-binary-type-for-blob="true">
            
        <after-create-table>GRANT SELECT,INSERT,UPDATE,DELETE ON TABLE ${table} 
TO runtime</after-create-table>
        <after-create-table>GRANT SELECT ON TABLE ${table} TO 
readonly</after-create-table>
        <after-create-table>REVOKE ALL ON TABLE ${table} FROM 
public</after-create-table>
        <after-create-table>ALTER TABLE ${table} OWNER TO 
admin</after-create-table>
        <after-create-view>GRANT SELECT ON TABLE ${table} TO 
runtime</after-create-view>
        <after-create-view>GRANT SELECT ON TABLE ${table} TO 
readonly</after-create-view>
        <after-create-view>REVOKE ALL ON TABLE ${table} FROM 
public</after-create-view>
        <after-create-view>ALTER TABLE ${table} OWNER TO 
admin</after-create-view>

        <inline-jdbc
                jdbc-driver="org.postgresql.Driver"
                jdbc-uri="jdbc:postgresql://${internalHost}/${databaseName}"
                jdbc-username="${username}"
                jdbc-password="${password}"
                isolation-level="ReadCommitted"
                pool-minsize="2"
                pool-maxsize="250"/>
    </datasource>


----- Original Message -----
From: "Henning" <[email protected]>
To: [email protected]
Sent: Wednesday, July 8, 2009 6:25:15 AM GMT -05:00 US/Canada Eastern
Subject: Re: Using OfBiz modular, partially, and in many instances

After spending some more time on stepping through the OfBiz code and
trying to get the entity engine running outside of the OfBiz framework I
found that while you can run the entity engine like that, but it still
requires a single entityengine.xml from the classpath and will maintain
that in some static cache. I think I saw the same pattern applied for
other configurations. 

In my understanding that means that one instance of the entity engine
code can be used for exactly one configuration per VM and in particular,
for the multi-tenant use-case, all data sources for all tenants have to
be pre-defined in that one configuration file. If I understood Marc
correctly, that's also what he does.

So the entity engine can be configured exactly once and it will not
forget until the VM stops.

However, it seems that all you need to process a request for a tenant is
its delegator and subsequently a service dispatcher. Both, it seems,
could be created based on some tenant specific configuration and still
work correctly, if it wasn't for the static cache. 

Also, it seems that the ResourceLoader supports separation per class
loader, so that you could have different entityengine.xml files in
different deployable (assuming these use different classloaders at
runtime) and the one to be the first one to ask for a delegator would
actually provide the entity engine config. Unfortunately any other code
would then share that configuration. Plus... GenericDelegator,
EntityConfigUtil etc. would not know about different classloaders still.

Currently I have the impression that trying to change all those places
could be an endless endeavour and I better start looking into a solution
that - at runtime - has duplicate deployments of OfBiz.

Any thoughts?

Thanks,
  Henning


Reply via email to