Need help setting up multiple API structure

3 views
Skip to first unread message

Po

unread,
Sep 30, 2009, 12:52:10 PM9/30/09
to Mach-II for CFML
SETUP: mach-ii 1.8, coldspring, and transfer

I currently have an application which is used as the backbone for the
administration of multiple e-commerce sites. This contains many
services that will also be used in the actual sites, not just for
administration. However, each site can potentially have specialized
services, event-handlers, listeners, filters, plugins, and properties
that are not part of the backbone's API. These will be mainly handled
by another application which will be the direct "engine" for the
sites. Each site will in turn be it's own application since some of
them may require further specialized code.

[MAIN API] --> [ENGINE API] --> [SITES]
- MAIN API contains most of the services
- ENGINE API exposes MAIN API services and adds specialized services,
event-handlers, listeners, filters, plugins, and properties needed for
the sites as well
- SITES further specializes if needed

Does anybody have a similar setup or any recommendations as of how to
best reuse the code following best practices?


Thank you.

Peter J. Farrell

unread,
Oct 4, 2009, 4:00:37 PM10/4/09
to mach-ii-for...@googlegroups.com
Are each site going to be their separate application instance?
Basically, this means you are going to deploy each site as a separate
application or will application have to check some data (like the domain
name) and serve something different on each request?

If you are going to deploy each application (i.e. site) as a separate
application context, you can easily accomplish this by have a default
set of xml files (as an application base for each site) and using
Mach-II xml includes to layer in each site's customizations. You could
use SVN externals to pull in the base code and then have a repository
for each site with their customizations.

Mixing request from multiple sites (the other option) in the same
application gets harder and messier as the application grows. That's
why it's easier to have a base set of file (that are maintained
separately and therefore you can upgrade the base and have your
customized sites get upgraded) and then layer in the customizations via
Mach-II XML includes and there respective additional files (listeners,
filters, models objects, etc.).

Best,
.Peter

Po said the following on 09/30/2009 11:52 AM:

Po

unread,
Oct 7, 2009, 1:00:48 PM10/7/09
to Mach-II for CFML
Originally, the sites were going to just be skins, so having the site
engine change the skin on each request depending on the
cgi.server_name/cgi.http_host was fine. But as the requirements
changed, we realized we needed specialized code for some sites, so we
decided to make each site its own application.

We first tried to implement this by having the engine add each site as
a module. This would allow each site to inherit the engine's reusable
code and seemed like the best solution. The main drawback to this was
that we still needed a filter to change skin depending on the domain,
and that we had to load all modules on application start, which did
not seem best for performance reasons. (Is there a way to lazy-init
modules?).

So in the latest iteration, we have each site including the engine as
a module instead. (This is where my previous problems with module
environments came into play :D ). This has worked fine so far except
that we were hoping to have the engine module include the dashboard
module so that all sites would be able to access it. This apparently
is not possible since modules cannot include other modules. This is
not a huge problem since, for now, we can just include the dashboard
on each site.

I had thought about including a default set of xml files in each site
as you mentioned, but it seemed an easier approach to just include one
module which has all of the default code than to include all of the
xml files per site.

We also have a main API, separate from the engine, which is used for
administration reasons and has much of the default code. This is
exposed via coldspring to the engine module. For this, would it be
best to use an SVN external that would include all services and their
dependencies (model), or to just rely on mappings?

Do you see any advantages/disadvantages to our current approach?

Would it be better to forget the engine, add all that code to the main
API, and include it (where needed) per site through coldsping?
> > Thank you.- Hide quoted text -
>
> - Show quoted text -

Fernando Martel

unread,
Oct 7, 2009, 12:39:02 PM10/7/09
to mach-ii-for...@googlegroups.com
Originally, the sites were going to just be skins, so having the site engine change the skin on each request depending on the cgi.server_name/cgi.http_host was fine.  But as the requirements changed, we realized we needed specialized code for some sites, so we decided to make each site its own application.
 
We first tried to implement this by having the engine add each site as a module.  This would allow each site to inherit the engine's reusable code and seemed like the best solution.  The main drawback to this was that we still needed a filter to change skin depending on the domain, and that we had to load all modules on application start, which did not seem best for performance reasons.  (Is there a way to lazy-init modules?).
 
So in the latest iteration, we have each site including the engine as a module instead.  (This is where my previous problems with module environments came into play :D ).  This has worked fine so far except that we were hoping to have the engine module include the dashboard module so that all sites would be able to access it.  This apparently is not possible since modules cannot include other modules.   This is not a huge problem since, for now, we can just include the dashboard on each site.
 
I had thought about including a default set of xml files in each site as you mentioned, but it seemed an easier approach to just include one module which has all of the default code than to include all of the xml files per site.
 
We also have a main API, separate from the engine, which is used for administration reasons and has much of the default code.  This is exposed via coldspring to the engine module.  For this, would it be best to use an SVN external that would include all services and their dependencies (model), or to just rely on mappings?
 
Do you see any advantages/disadvantages to our current approach?
 
Would it be better to forget the engine, add all that code to the main API, and include it (where needed) per site through coldsping?

 
> Date: Sun, 4 Oct 2009 15:00:37 -0500
> From: pe...@mach-ii.com
> To: mach-ii-for...@googlegroups.com
> Subject: [Mach-II] Re: Need help setting up multiple API structure

Po

unread,
Oct 7, 2009, 1:21:44 PM10/7/09
to Mach-II for CFML
Sorry about duplicate post.
> _________________________________________________________________
> Hotmail: Trusted email with powerful SPAM protection.http://clk.atdmt.com/GBL/go/177141665/direct/01/- Hide quoted text -

Jorge Loyo

unread,
Nov 19, 2009, 1:24:43 PM11/19/09
to Mach-II for CFML
Peter,

I am looking into this same situation so I'll ask a few questions from
this thread:

> Are each site going to be their separate application instance?  

Yes. Each site will be its own MachII application that will have
access to the same Service methods that will pull from the same
database. Basically as Po mentioned, these sites will simply be a
different point of entry (Skin) to the exact same data.


> Basically, this means you are going to deploy each site as a separate application

Yes.


> If you are going to deploy each application (i.e. site) as a separate
> application context, you can easily accomplish this by have a default
> set of xml files (as an application base for each site) and using
> Mach-II xml includes to layer in each site's customizations.

I am not 100% sure how you would do this... What would you include in
the default set of xml files?

I have an admin application that is being used to populate the
database so the sites can access this data. The sites will mainly pull
data, not create it (except orders). Therefore, there are a lot of
service/listener methods that will only be accessed by the admin
application. Would you suggest creating a different set of listeners/
services to be included (Mach-II xml includes) in the sites? Or would
you just include the original ones even though some methods won't the
accessed?


> Mixing request from multiple sites (the other option) in the same
> application gets harder and messier as the application grows.

Agreed.



Thank you in advanced.

Peter J. Farrell

unread,
Nov 19, 2009, 2:01:58 PM11/19/09
to mach-ii-for...@googlegroups.com
I think you have to figure where you can break your application into a core "base" application in which the separate sites layers stuff in.

For example, core could be mean shared listeners.  Whether or not all applications will use all of them all the time doesn't matter. Core could also mean that all applications should implement certain view pages by default.  This doesn't mean the core app provides them, but thinks the .cfm files should be available (i.e. each application implements there own versions).

More inline below...

Jorge Loyo said the following on 11/19/2009 12:24 PM:
Peter,

I am looking into this same situation so I'll ask a few questions from
this thread:

  
Are each site going to be their separate application instance?  
    
Yes. Each site will be its own MachII application that will have
access to the same Service methods that will pull from the same
database. Basically as Po mentioned, these sites will simply be a
different point of entry (Skin) to the exact same data.


  
Basically, this means you are going to deploy each site as a separate application
    
Yes.


  
If you are going to deploy each application (i.e. site) as a separate
application context, you can easily accomplish this by have a default
set of xml files (as an application base for each site) and using
Mach-II xml includes to layer in each site's customizations.
    
I am not 100% sure how you would do this... What would you include in
the default set of xml files?
  
See above -- common related functionality.

I have an admin application that is being used to populate the
database so the sites can access this data. The sites will mainly pull
data, not create it (except orders). Therefore, there are a lot of
service/listener methods that will only be accessed by the admin
application. Would you suggest creating a different set of listeners/
services to be included (Mach-II xml includes) in the sites? Or would
you just include the original ones even though some methods won't the
accessed?
  
Because it's simpler and less to maintain, I'd just opt to re-use the same listeners unless you can justify a good architectural reason to maintain a separate set of listeners.

Mixing request from multiple sites (the other option) in the same
application gets harder and messier as the application grows.
    
Agreed.
  
Certainly does.  It really depends on what the application does.  For example, a blogging engine is much easier to build a simple re-skinning feature (just look at the hack fest in MachBlog).  It's simple because each blog implements the "same" features.  It's when you want site A's behavior to be Z and site B's behavior to be ZZ -- just slightly different.

If you start seeing a bunch of if, elseif, elseif, else statements in the "core" shared part of the application -- you might need to be looking at how to refactor it.  You could sub class a listener.  Consider this config file.

<mach-ii>
  <includes>
    <include file="/mach-ii_core.xml"/>
    <include file="/mach-ii_example-com.xml" override="true"/>
  </includes>
</mach-ii>

The base config file is nothing more an that a giant mixer.  You include the core functionality with the first include and the customizations for example.com in the second.  Notice the override attribute.  Without it, Mach-II would throw exceptions if say both includes contain a definition for a listener named "sample".

In the core.xml, imagine a listener definition:

<listener name="sample" type="core.listeners.SampleListener"/>

In the example-com.xml, image another listener defintion:

<listener name="sample" type="com.example.listeners.SampleListener"/>

(Note these paths to the listeners)

Now the definition in the example-com.xml is override the listener defined in the core.xml.  Includes are processed in the order they are defined.

What you can do for the certain circumstances that example-com differs in behavior in a listener is to have the "sample" listener defined in example-com.xml (with the path of com.example.listeners.SampleListener) extend (in the cfcomponent tag) the core.listeners.SampleLister and override one or more inherited methods.

My two cents...

.pjf

P.s.  Feel free to use my example and clean it up for a wiki entry -- I think this question gets asked enough that we should really have a wiki entry for it.


Thank you in advanced.

  

Jorge Loyo

unread,
Nov 19, 2009, 2:08:39 PM11/19/09
to Mach-II for CFML
Thank you Peter,

I will write up the Wiki entry tomorrow morning as I am heading out
now.

Great stuff though. Again, thank you.
Reply all
Reply to author
Forward
0 new messages